diff options
author | kobalicek <kobalicek.petr@gmail.com> | 2021-12-13 11:11:58 +0300 |
---|---|---|
committer | kobalicek <kobalicek.petr@gmail.com> | 2021-12-13 21:34:56 +0300 |
commit | 996deae3273073bf75fbd6ddeac038dff5fdb6eb (patch) | |
tree | 47b3078b82a6f4cecb9362b70a5b1395866eb2e4 | |
parent | 4ec760a3d1f69e32ba460ecd2513f29b8428700b (diff) |
[ABI] Refactored AsmJit to use strong-typed enums, this breaks both API and ABI
[ABI] Added ABI version as an inline namespace, which forms asmjit::_abi_MAJOR_MINOR
[ABI] Added support for AVX512_FP16, 16-bit broadcast, and AVX512_FP16 tests
[ABI] Added initial support for consecutive registers into instruction database and register allocator
[ABI] Added a possibility to use temporary memory in CodeHolder's zone
[ABI] Compiler::setArg() is now deprecated, use FuncNode::setArg()
[Bug] Fixed correct RW information of instructions that only support implicit zeroing with {k}
[Bug] Fixed broadcast to be able to broadcast bcst16 operands
154 files changed, 29354 insertions, 21007 deletions
diff --git a/.github/workflows/build-config.json b/.github/workflows/build-config.json index 3c76bd0..2be4612 100644 --- a/.github/workflows/build-config.json +++ b/.github/workflows/build-config.json @@ -20,6 +20,10 @@ "optional": true }, { + "cmd": ["asmjit_test_assembler", "--quiet", "--validate"], + "optional": true + }, + { "cmd": ["asmjit_test_emitters"], "optional": true }, diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b322364..d7877f1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,58 +31,59 @@ jobs: fail-fast: false matrix: include: - - { title: "linux-lib" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", problem_matcher: "cpp" } - - { title: "windows-lib" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Debug" , problem_matcher: "cpp" } - - - { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "address" } - - { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "undefined" } - - { title: "diag-valgrind" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "valgrind" } - - - { title: "no-deprecated" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_DEPRECATED=1" } - - { title: "no-intrinsics" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_INTRINSICS=1" } - - { title: "no-logging" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_LOGGING=1" } - - { title: "no-builder" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_BUILDER=1" } - - { title: "no-compiler" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_COMPILER=1" } - - - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-5" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-5" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-6" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-6" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-9" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - - { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux-lib" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", problem_matcher: "cpp" } + - { title: "windows-lib" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Debug" , problem_matcher: "cpp" } + + - { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "address" } + - { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "undefined" } + - { title: "diag-valgrind" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "valgrind" } + - { title: "diag-scan-build", os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON", diagnostics: "scan-build" } + + - { title: "no-deprecated" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_DEPRECATED=1" } + - { title: "no-intrinsics" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_INTRINSICS=1" } + - { title: "no-logging" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_LOGGING=1" } + - { title: "no-builder" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_BUILDER=1" } + - { title: "no-compiler" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_COMPILER=1" } + + - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "gcc" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-4.8" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-5" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-5" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-6" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-18.04" , cc: "gcc-6" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-9" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + + - { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } # Disabled, because of GitHub actions infrastructure issues (builds not starting). #- { title: "macos-11.0" , os: "macos-11.0" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } @@ -90,10 +91,15 @@ jobs: #- { title: "macos-11.0" , os: "macos-11.0" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } #- { title: "macos-11.0" , os: "macos-11.0" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } - - { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } + + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" } name: "${{matrix.title}} (${{matrix.cc}}, ${{matrix.arch}}, ${{matrix.build_type}})" runs-on: "${{matrix.os}}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a8c081..554722c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,9 +19,8 @@ endif() include(CheckCXXCompilerFlag) include(GNUInstallDirs) -# ============================================================================= -# [AsmJit - Deprecated] -# ============================================================================= +# AsmJit - Deprecated +# =================== if (DEFINED ASMJIT_BUILD_EMBED) message(DEPRECATION "ASMJIT_BUILD_EMBED is deprecated, use ASMJIT_EMBED") @@ -33,9 +32,8 @@ if (DEFINED ASMJIT_BUILD_STATIC) set(ASMJIT_STATIC "${ASMJIT_BUILD_STATIC}") endif() -# ============================================================================= -# [AsmJit - Configuration] -# ============================================================================= +# AsmJit - Configuration +# ====================== if (NOT DEFINED ASMJIT_TEST) set(ASMJIT_TEST FALSE) @@ -84,9 +82,8 @@ set(ASMJIT_NO_FOREIGN "${ASMJIT_NO_FOREIGN}" CACHE BOOL "Disable all f set(ASMJIT_NO_NATVIS "${ASMJIT_NO_NATVIS}" CACHE BOOL "Disable natvis support (embedding asmjit.natvis in PDB)") set(ASMJIT_NO_CUSTOM_FLAGS "${ASMJIT_NO_CUSTOM_FLAGS}" CACHE BOOL "Disable extra compilation flags added by AsmJit to its targets") -# ============================================================================= -# [AsmJit - Project] -# ============================================================================= +# AsmJit - Project +# ================ set(ASMJIT_INCLUDE_DIRS "${ASMJIT_DIR}/src") # Include directory is the same as source dir. set(ASMJIT_DEPS "") # AsmJit dependencies (libraries) for the linker. @@ -98,9 +95,8 @@ set(ASMJIT_PRIVATE_CFLAGS_REL "") # Private compiler flags used b set(ASMJIT_SANITIZE_CFLAGS "") # Compiler flags required by currently enabled sanitizers. set(ASMJIT_SANITIZE_LFLAGS "") # Linker flags required by currently enabled sanitizers. -# ============================================================================= -# [AsmJit - Utilities] -# ============================================================================= +# AsmJit - Utilities +# ================== function(asmjit_detect_cflags out) set(out_array ${${out}}) @@ -172,9 +168,8 @@ function(asmjit_add_target target target_type) endif() endfunction() -# ============================================================================= -# [AsmJit - Compiler Support] -# ============================================================================= +# AsmJit - Compiler Support +# ========================= set(ASMJIT_INCLUDE_DIRS "${ASMJIT_DIR}/src") # Include directory is the same as source dir. set(ASMJIT_DEPS "") # AsmJit dependencies (libraries) for the linker. @@ -283,9 +278,8 @@ foreach(build_option ASMJIT_STATIC endif() endforeach() -# ============================================================================= -# [AsmJit - Linker Support] -# ============================================================================= +# AsmJit - Linker Support +# ======================= if (WIN32) if(CMAKE_LINKER MATCHES "link\\.exe" OR CMAKE_LINKER MATCHES "lld-link\\.exe") @@ -293,9 +287,8 @@ if (WIN32) endif() endif() -# ============================================================================= -# [AsmJit - Source] -# ============================================================================= +# AsmJit - Source +# =============== set(ASMJIT_SRC_LIST asmjit/asmjit.h @@ -324,7 +317,6 @@ set(ASMJIT_SRC_LIST asmjit/core/constpool.h asmjit/core/cpuinfo.cpp asmjit/core/cpuinfo.h - asmjit/core/datatypes.h asmjit/core/emithelper.cpp asmjit/core/emithelper_p.h asmjit/core/emitter.cpp @@ -335,7 +327,6 @@ set(ASMJIT_SRC_LIST asmjit/core/environment.h asmjit/core/errorhandler.cpp asmjit/core/errorhandler.h - asmjit/core/features.h asmjit/core/formatter.cpp asmjit/core/formatter.h asmjit/core/func.cpp @@ -401,8 +392,6 @@ set(ASMJIT_SRC_LIST asmjit/x86/x86emithelper.cpp asmjit/x86/x86emithelper_p.h asmjit/x86/x86emitter.h - asmjit/x86/x86features.cpp - asmjit/x86/x86features.h asmjit/x86/x86formatter.cpp asmjit/x86/x86formatter_p.h asmjit/x86/x86func.cpp @@ -439,9 +428,8 @@ if (NOT ${CMAKE_VERSION} VERSION_LESS "3.8.0") source_group(TREE "${ASMJIT_DIR}" FILES ${ASMJIT_SRC}) endif() -# ============================================================================= -# [AsmJit - Summary] -# ============================================================================= +# AsmJit - Summary +# ================ message("** AsmJit Summary **") message(" ASMJIT_DIR=${ASMJIT_DIR}") @@ -454,9 +442,8 @@ message(" ASMJIT_PRIVATE_CFLAGS=${ASMJIT_PRIVATE_CFLAGS}") message(" ASMJIT_PRIVATE_CFLAGS_DBG=${ASMJIT_PRIVATE_CFLAGS_DBG}") message(" ASMJIT_PRIVATE_CFLAGS_REL=${ASMJIT_PRIVATE_CFLAGS_REL}") -# ============================================================================= -# [AsmJit - Targets] -# ============================================================================= +# AsmJit - Targets +# ================ if (NOT ASMJIT_EMBED) # Add AsmJit target. @@ -47,12 +47,10 @@ TODO * [ ] Core: * [ ] Add support for user external buffers in CodeBuffer / CodeHolder. - * [ ] Register allocator doesn't understand register pairs, affected instructions: - * [ ] v4fmaddps, v4fmaddss, v4fnmaddps, v4fnmaddss - * [ ] vp4dpwssd, vp4dpwssds - * [ ] vp2intersectd, vp2intersectq * [ ] Ports: - * [ ] ARM/Thumb/AArch64 support. + * [ ] 32-bit ARM/Thumb port. + * [ ] 64-bit ARM (AArch64) port. + * [ ] RISC-V port. Support ------- diff --git a/src/asmjit.natvis b/src/asmjit.natvis index b73d848..68012e0 100644 --- a/src/asmjit.natvis +++ b/src/asmjit.natvis @@ -34,50 +34,94 @@ </Expand> </Type> - <Type Name="asmjit::Operand_"> - <Intrinsic Name="opType" Expression="(unsigned int)(_signature & 0x7)" /> - <Intrinsic Name="opSize" Expression="(_signature >> 24) & 0xFF" /> - - <Intrinsic Name="regType" Expression="(_signature >> 3) & 0x1F" /> - <Intrinsic Name="regGroup" Expression="(_signature >> 8) & 0xF" /> - - <Intrinsic Name="memBaseType" Expression="(_signature >> 3) & 0x1F" /> - <Intrinsic Name="memIndexType" Expression="(_signature >> 8) & 0x1F" /> - <Intrinsic Name="memAddrType" Expression="(_signature >> 13) & 0x3" /> - <Intrinsic Name="memRegHome" Expression="(_signature >> 15) & 0x1" /> + <Type Name="asmjit::OperandSignature"> + <Intrinsic Name="opType" Expression="(asmjit::OperandType)(_bits & 0x7)" /> + <Intrinsic Name="opSize" Expression="(_bits >> 24) & 0xFF" /> + <Intrinsic Name="regType" Expression="(asmjit::RegType)((_bits >> 3) & 0x1F)" /> + <Intrinsic Name="regGroup" Expression="(asmjit::RegGroup)((_bits >> 8) & 0xF)" /> + <Intrinsic Name="memBaseType" Expression="(asmjit::RegType)((_bits >> 3) & 0x1F)" /> + <Intrinsic Name="memIndexType" Expression="(asmjit::RegType)((_bits >> 8) & 0x1F)" /> + <Intrinsic Name="memRegHome" Expression="(bool)((_bits >> 13) & 0x1)" /> + <Intrinsic Name="memX86Segment" Expression="(asmjit::x86::SReg::Id)((_bits >> 18) & 0x7)" /> + <Intrinsic Name="memX86AddrType" Expression="(asmjit::x86::Mem::AddrType)((_bits >> 14) & 0x3)" /> + <Intrinsic Name="memX86ShiftValue" Expression="((_bits >> 16) & 0x3)" /> + <Intrinsic Name="memX86Broadcast" Expression="(asmjit::x86::Mem::Broadcast)((_bits >> 21) & 0x7)" /> + <Intrinsic Name="immType" Expression="(asmjit::ImmType)((_bits >> 3) & 0x1)" /> + + <DisplayString Condition="opType() == asmjit::OperandType::kNone">[None]</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kReg">[Reg] {{ type={regType()} group={regGroup()} size={opSize(), d} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kMem">[Mem] {{ base={memBaseType()} index={memIndexType()} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kImm">[Imm] {{ type={immType()} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kLabel">[Label]</DisplayString> + <DisplayString Condition="opType() > asmjit::OperandType::kMaxValue">[Unknown]</DisplayString> + <Expand HideRawView="true"> + <Item Name="bits">_bits, X</Item> + <Item Name="op.type">opType()</Item> + <Item Name="reg.type" Condition="opType() == asmjit::OperandType::kReg">regType()</Item> + <Item Name="reg.group" Condition="opType() == asmjit::OperandType::kReg">regGroup()</Item> + <Item Name="reg.size" Condition="opType() == asmjit::OperandType::kReg">opSize(), d</Item> + <Item Name="mem.baseType" Condition="opType() == asmjit::OperandType::kMem">memBaseType()</Item> + <Item Name="mem.indexType" Condition="opType() == asmjit::OperandType::kMem">memIndexType()</Item> + <Item Name="mem.regHome" Condition="opType() == asmjit::OperandType::kMem">memRegHome()</Item> + <Item Name="mem.size" Condition="opType() == asmjit::OperandType::kMem">opSize(), d</Item> + <Item Name="mem.x86.segment" Condition="opType() == asmjit::OperandType::kMem">memX86Segment()</Item> + <Item Name="mem.x86.addrType" Condition="opType() == asmjit::OperandType::kMem">memX86AddrType()</Item> + <Item Name="mem.x86.shift" Condition="opType() == asmjit::OperandType::kMem">memX86ShiftValue()</Item> + <Item Name="mem.x86.broadcast" Condition="opType() == asmjit::OperandType::kMem">memX86Broadcast()</Item> + <Item Name="imm.type" Condition="opType() == asmjit::OperandType::kImm">immType()</Item> + </Expand> + </Type> + + <Type Name="asmjit::Operand_"> + <Intrinsic Name="opType" Expression="(asmjit::OperandType)(_signature._bits & 0x7)" /> + <Intrinsic Name="opSize" Expression="(_signature._bits >> 24) & 0xFF" /> + <Intrinsic Name="regType" Expression="(asmjit::RegType)((_signature._bits >> 3) & 0x1F)" /> + <Intrinsic Name="regGroup" Expression="(asmjit::RegGroup)((_signature._bits >> 8) & 0xF)" /> + <Intrinsic Name="memBaseType" Expression="(asmjit::RegType)((_signature._bits >> 3) & 0x1F)" /> + <Intrinsic Name="memIndexType" Expression="(asmjit::RegType)((_signature._bits >> 8) & 0x1F)" /> + <Intrinsic Name="memRegHome" Expression="(bool)((_signature._bits >> 13) & 0x1)" /> + <Intrinsic Name="memX86Segment" Expression="(asmjit::x86::SReg::Id)((_signature._bits >> 18) & 0x7)" /> + <Intrinsic Name="memX86AddrType" Expression="(asmjit::x86::Mem::AddrType)((_signature._bits >> 14) & 0x3)" /> + <Intrinsic Name="memX86ShiftValue" Expression="((_signature._bits >> 16) & 0x3)" /> + <Intrinsic Name="memX86Broadcast" Expression="(asmjit::x86::Mem::Broadcast)((_signature._bits >> 21) & 0x7)" /> <Intrinsic Name="memBaseId" Expression="_baseId" /> <Intrinsic Name="memIndexId" Expression="_data[0]" /> - <Intrinsic Name="memOffset32b" Expression="(__int64)int(_data[1])" /> <Intrinsic Name="memOffset64b" Expression="(__int64) ((unsigned __int64)_baseId << 32) | ((unsigned __int64)_data[1])" /> - <Intrinsic Name="memOffset" Expression="memBaseType() != 0 ? memOffset32b() : memOffset64b()" /> - + <Intrinsic Name="memOffset" Expression="memBaseType() != asmjit::RegType::kNone ? memOffset32b() : memOffset64b()" /> + <Intrinsic Name="immType" Expression="(asmjit::ImmType)((_signature._bits >> 3) & 0x1)" /> <Intrinsic Name="immValue" Expression="((__int64)_data[1] << 32) | (__int64)_data[0]" /> - <DisplayString Condition="opType() == 0">[None]</DisplayString> - <DisplayString Condition="opType() == 1">[Reg] {{ id={_baseId, d} group={regGroup(), d} type={regType(), d} size={opSize(), d} }}</DisplayString> - <DisplayString Condition="opType() == 2">[Mem] {{ baseId={memBaseId(), d} indexId={memIndexId(), d} offset={(__int64)memOffset(), d} }}</DisplayString> - <DisplayString Condition="opType() == 3">[Imm] {{ val={immValue(), d} hex={immValue(), X} }}</DisplayString> - <DisplayString Condition="opType() == 4">[Label] {{ id={_baseId} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kNone">[None]</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kReg">[Reg] {{ id={_baseId, d} group={regGroup(), d} type={regType(), d} size={opSize(), d} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kMem">[Mem] {{ baseId={memBaseId(), d} indexId={memIndexId(), d} offset={(__int64)memOffset(), d} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kImm">[Imm] {{ val={immValue(), d} hex={immValue(), X} }}</DisplayString> + <DisplayString Condition="opType() == asmjit::OperandType::kLabel">[Label] {{ id={_baseId} }}</DisplayString> <DisplayString Condition="opType() > 4">[Unknown]</DisplayString> <Expand HideRawView="true"> - <Item Name="_signature">_signature, X</Item> - <Item Name="_signature.any.type">(asmjit::Operand_::OpType)opType()</Item> - <Item Name="_signature.any.size">opSize(), d</Item> - <Item Name="_signature.reg.type" Condition="opType() == 1">(asmjit::BaseReg::RegType)regType()</Item> - <Item Name="_signature.reg.group" Condition="opType() == 1">(asmjit::BaseReg::RegGroup)regGroup()</Item> - <Item Name="_signature.mem.baseType" Condition="opType() == 2">(asmjit::BaseReg::RegType)memBaseType()</Item> - <Item Name="_signature.mem.indexType" Condition="opType() == 2">(asmjit::BaseReg::RegType)memIndexType()</Item> - <Item Name="_signature.mem.addrType" Condition="opType() == 2">(asmjit::BaseMem::AddrType)memAddrType()</Item> - <Item Name="_signature.mem.regHome" Condition="opType() == 2">(bool)memRegHome()</Item> - <Item Name="_baseId">_baseId</Item> - <Item Name="_data[0]" Condition="opType() != 2 && opType() != 3">_data[0]</Item> - <Item Name="_data[1]" Condition="opType() != 2 && opType() != 3">_data[1]</Item> - <Item Name="_data[IndexId]" Condition="opType() == 2">_data[0]</Item> - <Item Name="_data[OffsetLo]" Condition="opType() == 2">_data[1]</Item> - <Item Name="_data[ImmHi]" Condition="opType() == 3">_data[0]</Item> - <Item Name="_data[ImmLo]" Condition="opType() == 3">_data[1]</Item> + <Item Name="_signature">_signature._bits, X</Item> + <Item Name="op.type">opType()</Item> + <Item Name="op.size">opSize(), d</Item> + <Item Name="reg.type" Condition="opType() == asmjit::OperandType::kReg">regType()</Item> + <Item Name="reg.group" Condition="opType() == asmjit::OperandType::kReg">regGroup()</Item> + <Item Name="reg.id" Condition="opType() == asmjit::OperandType::kReg">_baseId, d</Item> + <Item Name="mem.baseType" Condition="opType() == asmjit::OperandType::kMem">memBaseType()</Item> + <Item Name="mem.baseId" Condition="opType() == asmjit::OperandType::kMem && memBaseType() != asmjit::RegType::kNone">memBaseId()</Item> + <Item Name="mem.indexType" Condition="opType() == asmjit::OperandType::kMem">memIndexType()</Item> + <Item Name="mem.indexId" Condition="opType() == asmjit::OperandType::kMem && memIndexType() != asmjit::RegType::kNone">memIndexId()</Item> + <Item Name="mem.regHome" Condition="opType() == asmjit::OperandType::kMem">memRegHome()</Item> + <Item Name="mem.offset" Condition="opType() == asmjit::OperandType::kMem">memOffset(), d</Item> + <Item Name="mem.x86.segment" Condition="opType() == asmjit::OperandType::kMem">memX86Segment()</Item> + <Item Name="mem.x86.addrType" Condition="opType() == asmjit::OperandType::kMem">memX86AddrType()</Item> + <Item Name="mem.x86.shift" Condition="opType() == asmjit::OperandType::kMem">memX86ShiftValue()</Item> + <Item Name="mem.x86.broadcast" Condition="opType() == asmjit::OperandType::kMem">memX86Broadcast()</Item> + <Item Name="imm.type" Condition="opType() == asmjit::OperandType::kImm">immType()</Item> + <Item Name="imm.value" Condition="opType() == asmjit::OperandType::kImm">immValue(), X</Item> + <Item Name="label.id" Condition="opType() == asmjit::OperandType::kLabel">_baseId, d</Item> + <Item Name="raw.baseId">_baseId</Item> + <Item Name="raw.data[0]">_data[0]</Item> + <Item Name="raw.data[1]">_data[1]</Item> </Expand> </Type> @@ -98,7 +142,7 @@ <Expand HideRawView="true"> <Item Name="data">_data</Item> - <Item Name="typeId">(asmjit::Type::Id)(typeId())</Item> + <Item Name="typeId">(asmjit::TypeId)(typeId())</Item> <Item Name="regType" Condition="isReg()">(asmjit::BaseReg::RegType)regType()</Item> <Item Name="regId" Condition="isReg()">regId()</Item> <Item Name="stackOffset" Condition="isStack()">stackOffset()</Item> @@ -108,26 +152,26 @@ <Type Name="asmjit::BaseNode"> <Intrinsic Name="nodeType" Expression="_any._nodeType" /> - <Intrinsic Name="isInst" Expression="nodeType() == asmjit::BaseNode::kNodeInst"></Intrinsic> - <Intrinsic Name="isSection" Expression="nodeType() == asmjit::BaseNode::kNodeSection"></Intrinsic> - <Intrinsic Name="isLabel" Expression="nodeType() == asmjit::BaseNode::kNodeLabel"></Intrinsic> - <Intrinsic Name="isAlign" Expression="nodeType() == asmjit::BaseNode::kNodeAlign"></Intrinsic> - <Intrinsic Name="isEmbedData" Expression="nodeType() == asmjit::BaseNode::kNodeEmbedData"></Intrinsic> - <Intrinsic Name="isEmbedLabel" Expression="nodeType() == asmjit::BaseNode::kNodeEmbedLabel"></Intrinsic> - <Intrinsic Name="isEmbedLabelDelta" Expression="nodeType() == asmjit::BaseNode::kNodeEmbedLabelDelta"></Intrinsic> - <Intrinsic Name="isConstPool" Expression="nodeType() == asmjit::BaseNode::kNodeConstPool"></Intrinsic> - <Intrinsic Name="isComment" Expression="nodeType() == asmjit::BaseNode::kNodeComment"></Intrinsic> - <Intrinsic Name="isSentinel" Expression="nodeType() == asmjit::BaseNode::kNodeSentinel"></Intrinsic> - <Intrinsic Name="isJump" Expression="nodeType() == asmjit::BaseNode::kNodeJump"></Intrinsic> - <Intrinsic Name="isFunc" Expression="nodeType() == asmjit::BaseNode::kNodeFunc"></Intrinsic> - <Intrinsic Name="isFuncRet" Expression="nodeType() == asmjit::BaseNode::kNodeFuncRet"></Intrinsic> - <Intrinsic Name="isInvoke" Expression="nodeType() == asmjit::BaseNode::kNodeInvoke"></Intrinsic> + <Intrinsic Name="isInst" Expression="nodeType() == asmjit::NodeType::kInst"></Intrinsic> + <Intrinsic Name="isSection" Expression="nodeType() == asmjit::NodeType::kSection"></Intrinsic> + <Intrinsic Name="isLabel" Expression="nodeType() == asmjit::NodeType::kLabel"></Intrinsic> + <Intrinsic Name="isAlign" Expression="nodeType() == asmjit::NodeType::kAlign"></Intrinsic> + <Intrinsic Name="isEmbedData" Expression="nodeType() == asmjit::NodeType::kEmbedData"></Intrinsic> + <Intrinsic Name="isEmbedLabel" Expression="nodeType() == asmjit::NodeType::kEmbedLabel"></Intrinsic> + <Intrinsic Name="isEmbedLabelDelta" Expression="nodeType() == asmjit::NodeType::kEmbedLabelDelta"></Intrinsic> + <Intrinsic Name="isConstPool" Expression="nodeType() == asmjit::NodeType::kConstPool"></Intrinsic> + <Intrinsic Name="isComment" Expression="nodeType() == asmjit::NodeType::kComment"></Intrinsic> + <Intrinsic Name="isSentinel" Expression="nodeType() == asmjit::NodeType::kSentinel"></Intrinsic> + <Intrinsic Name="isJump" Expression="nodeType() == asmjit::NodeType::kJump"></Intrinsic> + <Intrinsic Name="isFunc" Expression="nodeType() == asmjit::NodeType::kFunc"></Intrinsic> + <Intrinsic Name="isFuncRet" Expression="nodeType() == asmjit::NodeType::kFuncRet"></Intrinsic> + <Intrinsic Name="isInvoke" Expression="nodeType() == asmjit::NodeType::kInvoke"></Intrinsic> <Intrinsic Name="actsAsInst" Expression="isInst() || isJump() || isFunc() || isFuncRet() || isInvoke()" /> <Intrinsic Name="actsAsLabel" Expression="isLabel() || isFunc()" /> <DisplayString Condition="isInst()">[InstNode]</DisplayString> - <DisplayString Condition="isSentinel()">[SectionNode]</DisplayString> + <DisplayString Condition="isSection()">[SectionNode]</DisplayString> <DisplayString Condition="isLabel()">[LabelNode]</DisplayString> <DisplayString Condition="isAlign()">[AlignNode]</DisplayString> <DisplayString Condition="isEmbedData()">[EmbedDataNode]</DisplayString> @@ -140,14 +184,14 @@ <DisplayString Condition="isFunc()">[FuncNode]</DisplayString> <DisplayString Condition="isFuncRet()">[FuncRetNode]</DisplayString> <DisplayString Condition="isInvoke()">[InvokeNode]</DisplayString> - <DisplayString Condition="nodeType() == 0 || nodeType() > 18">[UnknownNode {nodeType(), d}]</DisplayString> + <DisplayString Condition="nodeType() == asmjit::NodeType::kNone || nodeType() > 18">[UnknownNode {nodeType(), d}]</DisplayString> <Expand HideRawView="true"> <Item Name="prev">_prev</Item> <Item Name="next">_next</Item> - <Item Name="nodeType">(asmjit::BaseNode::NodeType)_any._nodeType</Item> - <Item Name="nodeFlags">(asmjit::BaseNode::Flags)_any._nodeFlags</Item> + <Item Name="nodeType">_any._nodeType</Item> + <Item Name="nodeFlags">_any._nodeFlags</Item> <Item Name="position">_position</Item> <Item Name="userData.u64">_userDataU64</Item> @@ -163,9 +207,9 @@ <Item Name="sectionId" Condition="isSection()">((asmjit::SectionNode*)this)->_id</Item> <Item Name="nextSection" Condition="isSection()">((asmjit::SectionNode*)this)->_nextSection</Item> - <Item Name="labelId" Condition="isLabel()">((asmjit::LabelNode*)this)->_id</Item> + <Item Name="labelId" Condition="isLabel()">((asmjit::LabelNode*)this)->_labelId</Item> - <Item Name="alignMode" Condition="isAlign()">((asmjit::AlignNode*)this)->_alignMode</Item> + <Item Name="alignMode" Condition="isAlign()">((asmjit::AlignNode*)this)->_alignData._alignMode</Item> <Item Name="alignment" Condition="isAlign()">((asmjit::AlignNode*)this)->_alignment</Item> <Item Name="typeId" Condition="isEmbedData()">_embed._typeId, d</Item> @@ -175,15 +219,15 @@ <Item Name="inlineData" Condition="isEmbedData()">((asmjit::EmbedDataNode*)this)->_inlineData</Item> <Item Name="externalData" Condition="isEmbedData()">((asmjit::EmbedDataNode*)this)->_externalData</Item> - <Item Name="labelId" Condition="isEmbedLabel()">((asmjit::EmbedLabelNode*)this)->_id</Item> + <Item Name="labelId" Condition="isEmbedLabel()">((asmjit::EmbedLabelNode*)this)->_labelId</Item> - <Item Name="labelId" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_id</Item> - <Item Name="baseId" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_baseId</Item> + <Item Name="labelId" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_labelId</Item> + <Item Name="baseLabelId" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_baseLabelId</Item> <Item Name="dataSize" Condition="isEmbedLabelDelta()">((asmjit::EmbedLabelDeltaNode*)this)->_dataSize</Item> <Item Name="constPool" Condition="isConstPool()">((asmjit::ConstPoolNode*)this)->_constPool</Item> - <Item Name="sentinel.sentinelType" Condition="isSentinel()">(asmjit::SentinelNode::SentinelType)_sentinel._sentinelType</Item> + <Item Name="sentinel.sentinelType" Condition="isSentinel()">_sentinel._sentinelType</Item> <Item Name="annotation" Condition="isJump()">((asmjit::JumpNode*)this)->_annotation</Item> @@ -194,7 +238,7 @@ <Item Name="args" Condition="isFunc()">((asmjit::FuncNode*)this)->_args, [((asmjit::FuncNode*)this)->_funcDetail._argCount]</Item> <Item Name="funcDetail" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_funcDetail</Item> - <Item Name="rets" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_rets, [((asmjit::InvokeNode*)this)->_funcDetail._retCount]</Item> + <Item Name="rets" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_rets</Item> <Item Name="args" Condition="isInvoke()">((asmjit::InvokeNode*)this)->_args, [((asmjit::InvokeNode*)this)->_funcDetail._argCount]</Item> </Expand> </Type> diff --git a/src/asmjit/asmjit-scope-begin.h b/src/asmjit/asmjit-scope-begin.h index 6ee5050..93397b5 100644 --- a/src/asmjit/asmjit-scope-begin.h +++ b/src/asmjit/asmjit-scope-begin.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifdef _WIN32 #pragma push_macro("min") diff --git a/src/asmjit/asmjit-scope-end.h b/src/asmjit/asmjit-scope-end.h index 447105a..702cef4 100644 --- a/src/asmjit/asmjit-scope-end.h +++ b/src/asmjit/asmjit-scope-end.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifdef _WIN32 #pragma pop_macro("min") diff --git a/src/asmjit/asmjit.h b/src/asmjit/asmjit.h index 5f93fe4..1cd0651 100644 --- a/src/asmjit/asmjit.h +++ b/src/asmjit/asmjit.h @@ -1,9 +1,9 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit +// SPDX-License-Identifier: Zlib +// Official GitHub Repository: https://github.com/asmjit/asmjit // -// Copyright (c) 2008-2020 The AsmJit Authors +// Copyright (c) 2008-2021 The AsmJit Authors // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/asmjit/core.h b/src/asmjit/core.h index 7620343..58a380d 100644 --- a/src/asmjit/core.h +++ b/src/asmjit/core.h @@ -1,88 +1,56 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_H_INCLUDED #define ASMJIT_CORE_H_INCLUDED //! Root namespace used by AsmJit. -namespace asmjit { - -// ============================================================================ -// [Documentation - mainpage] -// ============================================================================ +namespace asmjit {} //! \mainpage API Reference //! //! AsmJit C++ API reference documentation generated by Doxygen. //! -//! AsmJit library uses one global namespace called \ref asmjit, which provides -//! the whole functionality. Core functionality is within \ref asmjit namespace -//! and architecture specific functionality is always in its own namespace. For -//! example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation. +//! AsmJit library uses one global namespace called \ref asmjit, which provides the whole functionality. Core +//! functionality is within \ref asmjit namespace and architecture specific functionality is always in its own +//! namespace. For example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation. //! //! \section main_groups Documentation Groups //! -//! AsmJit documentation is structured into groups. Groups can be followed in -//! order to learn AsmJit, but knowledge from multiple groups is required to -//! use AsmJit properly: +//! AsmJit documentation is structured into groups. Groups can be followed in order to learn AsmJit, but knowledge +//! from multiple groups is required to use AsmJit properly: //! //! $$DOCS_GROUP_OVERVIEW$$ //! -//! \note It's important to understand that in order to learn AsmJit all groups -//! are important. Some groups can be omitted if a particular tool is out of -//! interest - for example \ref asmjit_assembler users don't need to know about -//! \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users -//! must know about \ref asmjit_assembler as it also uses operands, labels, and -//! other concepts. Similarly \ref asmjit_compiler users must know how both \ref -//! asmjit_assembler and \ref asmjit_builder tools work. +//! \note It's important to understand that in order to learn AsmJit all groups are important. Some groups can be +//! omitted if a particular tool is out of interest - for example \ref asmjit_assembler users don't need to know +//! about \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users must know about \ref +//! asmjit_assembler as it also uses operands, labels, and other concepts. Similarly \ref asmjit_compiler users +//! must know how both \ref asmjit_assembler and \ref asmjit_builder tools work. //! //! \section where_to_start Where To Start //! -//! AsmJit \ref asmjit_core provides the following two classes that are essential -//! from the code generation perspective: +//! AsmJit \ref asmjit_core provides the following two classes that are essential from the code generation perspective: //! -//! - \ref CodeHolder provides functionality -//! to temporarily hold the generated code. It stores all the necessary -//! information about the code - code buffers, sections, labels, symbols, -//! and information about relocations. +//! - \ref CodeHolder provides functionality to temporarily hold the generated code. It stores all the necessary +//! information about the code - code buffers, sections, labels, symbols, and information about relocations. //! -//! - \ref BaseEmitter provides interface used -//! by emitter implementations. The interface provides basic building blocks -//! that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and -//! \ref BaseCompiler. +//! - \ref BaseEmitter provides interface used by emitter implementations. The interface provides basic building +//! blocks that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and \ref BaseCompiler. //! //! Code emitters: //! //! - \ref asmjit_assembler - provides direct machine code generation. //! -//! - \ref asmjit_builder - provides intermediate code generation that can -//! be processed before it's serialized to \ref BaseAssembler. +//! - \ref asmjit_builder - provides intermediate code generation that can be processed before it's serialized to +//! \ref BaseAssembler. //! -//! - \ref asmjit_compiler - provides high-level code generation with built-in -//! register allocation. +//! - \ref asmjit_compiler - provides high-level code generation with built-in register allocation. //! -//! - \ref FuncNode - provides insight into how function looks from the Compiler -//! perspective and how it's stored in a node-list. +//! - \ref FuncNode - provides insight into how function looks from the Compiler perspective and how it's stored in +//! a node-list. //! //! \section main_recommendations Recommendations //! @@ -92,76 +60,63 @@ namespace asmjit { //! //! - Make sure that you use \ref ErrorHandler, see \ref asmjit_error_handling. //! -//! - Instruction validation in your debug builds can reveal problems too. -//! AsmJit provides validation at instruction level, that can be enabled -//! by \ref BaseEmitter::addValidationOptions(). +//! - Instruction validation in your debug builds can reveal problems too. AsmJit provides validation at instruction +//! level that can be enabled via \ref BaseEmitter::addDiagnosticOptions(). See \ref DiagnosticOptions for more +//! details. //! -//! See \ref BaseEmitter::ValidationOptions for more details. +//! - If you are a Compiler user, use diagnostic options and read carefully if anything suspicious pops out. +//! Diagnostic options can be enabled via \ref BaseEmitter::addDiagnosticOptions(). If unsure which ones to use, +//! enable annotations and all debug options: `DiagnosticOptions::kRAAnnotate | DiagnosticOptions::kRADebugAll`. //! -//! - Make sure you put a breakpoint into \ref DebugUtils::errored() function -//! if you have a problem with AsmJit returning errors during instruction -//! encoding or register allocation. Having an active breakpoint there can -//! help to reveal the origin of the error, to inspect variables and other -//! conditions that caused to it. +//! - Make sure you put a breakpoint into \ref DebugUtils::errored() function if you have a problem with AsmJit +//! returning errors during instruction encoding or register allocation. Having an active breakpoint there can +//! help to reveal the origin of the error, to inspect variables and other conditions that caused to it. //! -//! The reason for using \ref Logger and \ref ErrorHandler is that they provide -//! a very useful information about what's happening inside emitters. In many -//! cases the information provided by these two is crucial to quickly fix issues -//! that happen during development (for example wrong instruction, address, or -//! register used). In addition, output from \ref Logger is always necessary -//! when filling bug reports. In other words, using logging and proper error -//! handling can save a lot of time during the development. +//! The reason for using \ref Logger and \ref ErrorHandler is that they provide a very useful information about what's +//! happening inside emitters. In many cases the information provided by these two is crucial to quickly fix issues +//! that happen during development (for example wrong instruction, address, or register used). In addition, output from +//! \ref Logger is always necessary when filling bug reports. In other words, using logging and proper error handling +//! can save a lot of time during the development. //! //! \section main_other Other Pages //! //! - <a href="annotated.html">Class List</a> - List of classes sorted alphabetically //! - <a href="namespaceasmjit.html">AsmJit Namespace</a> - List of symbols provided by `asmjit` namespace -// ============================================================================ -// [Documentation - asmjit_build] -// ============================================================================ //! \defgroup asmjit_build Build Instructions //! \brief Build instructions, supported environments, and feature selection. //! //! ### Overview //! -//! AsmJit is designed to be easy embeddable in any project. However, it depends -//! on some compile-time definitions that can be used to enable or disable -//! features to decrease the resulting binary size. A typical way of building -//! AsmJit is to use [cmake](https://www.cmake.org), but it's also possible to -//! just include AsmJit source code in your project and to just build it. The -//! easiest way to include AsmJit in your project is to just include **src** -//! directory in your project and to define \ref ASMJIT_STATIC. AsmJit can be -//! just updated from time to time without any changes to this integration -//! process. Do not embed AsmJit's `test` files in such case as these are used -//! exclusively for testing. +//! AsmJit is designed to be easy embeddable in any project. However, it depends on some compile-time definitions that +//! can be used to enable or disable features to decrease the resulting binary size. A typical way of building AsmJit +//! is to use [cmake](https://www.cmake.org), but it's also possible to just include AsmJit source code in your project +//! and to just build it. The easiest way to include AsmJit in your project is to just include **src** directory in +//! your project and to define \ref ASMJIT_STATIC. AsmJit can be just updated from time to time without any changes to +//! this integration process. Do not embed AsmJit's `test` files in such case as these are used exclusively for testing. //! //! ### Supported C++ Compilers //! //! - Requirements: //! -//! - AsmJit won't build without C++11 enabled. If you use older GCC or Clang -//! you would have to enable at least C++11 standard through compiler flags. +//! - AsmJit won't build without C++11 enabled. If you use older GCC or Clang you would have to enable at least +//! C++11 standard through compiler flags. //! //! - Tested: //! -//! - **Clang** - Tested by Travis-CI - Clang 3.9+ (with C++11 enabled) is -//! officially supported (older Clang versions having C++11 support are -//! probably fine, but are not regularly tested). +//! - **Clang** - Tested by GitHub Actions - Clang 3.9+ (with C++11 enabled) is officially supported (older Clang +//! versions having C++11 support are probably fine, but are not regularly tested). //! -//! - **GNU** - Tested by Travis-CI - GCC 4.8+ (with C++11 enabled) is -//! officially supported. +//! - **GNU** - Tested by GitHub Actions - GCC 4.8+ (with C++11 enabled) is officially supported. //! -//! - **MINGW** - Tested by Travis-CI - Use the latest version, if possible. +//! - **MINGW** - Should work, but it's not tested in our CI environment. //! -//! - **MSVC** - Tested by Travis-CI - VS2017+ is officially supported, VS2015 -//! is reported to work. +//! - **MSVC** - Tested by GitHub Actions - VS2017+ is officially supported, VS2015 is reported to work. //! //! - Untested: //! -//! - **Intel** - No maintainers and no CI environment to regularly test -//! this compiler. +//! - **Intel** - No maintainers and no CI environment to regularly test this compiler. //! //! - **Other** C++ compilers would require basic support in //! [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h). @@ -170,258 +125,259 @@ namespace asmjit { //! //! - Tested: //! -//! - **Linux** - Tested by Travis-CI (any distribution is generally supported). +//! - **Linux** - Tested by GitHub Actions (any distribution is generally supported). //! -//! - **OSX** - Tested by Travis-CI (any version is supported). +//! - **Mac OS** - Tested by GitHub Actions (any version is supported). //! -//! - **Windows** - Tested by Travis-CI - (Windows 7+ is officially supported). +//! - **Windows** - Tested by GitHub Actions - (Windows 7+ is officially supported). //! -//! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit -//! cannot generate WASM code, but can be used to generate X86/X64 code -//! within a browser, for example. +//! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit cannot generate WASM code, but can be +//! used to generate X86/X64 code within a browser, for example. //! //! - Untested: //! -//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, -//! but they should work out of box. +//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, but they should work out of box. //! //! - **Haiku** - Not regularly tested, but reported to work. //! -//! - **Other** operating systems would require some testing and support in -//! the following files: +//! - **Other** operating systems would require some testing and support in the following files: //! - [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h) //! - [core/osutils.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/osutils.cpp) //! - [core/virtmem.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/virtmem.cpp) //! //! ### Supported Backends / Architectures //! -//! - **X86** - Both 32-bit and 64-bit backends tested by Travis-CI. -//! - **ARM** - Work-in-progress (not public at the moment). +//! - **X86** - Both 32-bit and 64-bit backends tested on our CI. //! //! ### Static Builds and Embedding //! -//! These definitions can be used to enable static library build. Embed is used -//! when AsmJit's source code is embedded directly in another project, implies -//! static build as well. +//! These definitions can be used to enable static library build. Embed is used when AsmJit's source code is embedded +//! directly in another project, implies static build as well. //! //! - \ref ASMJIT_EMBED - Asmjit is embedded, implies \ref ASMJIT_STATIC. //! - \ref ASMJIT_STATIC - Enable static-library build. //! -//! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in -//! all compilation units that use AsmJit, otherwise AsmJit would use dynamic -//! library imports in \ref ASMJIT_API decorator. The recommendation is to -//! define this macro across the whole project that uses AsmJit this way. +//! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in all compilation units that use AsmJit, +//! otherwise AsmJit would use dynamic library imports in \ref ASMJIT_API decorator. The recommendation is to define +//! this macro across the whole project that uses AsmJit this way. //! //! ### Build Configuration //! -//! These definitions control whether asserts are active or not. By default -//! AsmJit would autodetect build configuration from existing pre-processor -//! definitions, but this behavior can be overridden, for example to enable -//! debug asserts in release configuration. +//! These definitions control whether asserts are active or not. By default AsmJit would autodetect build configuration +//! from existing pre-processor definitions, but this behavior can be overridden, for example to enable debug asserts +//! in release configuration. //! -//! - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, -//! asserts will be enabled in this case. -//! - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, -//! asserts will be disabled in this case. +//! - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, asserts will be enabled in this case. +//! - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, asserts will be disabled in this case. //! -//! \note There is usually no need to override the build configuration. AsmJit -//! detects the build configuration by checking whether `NDEBUG` is defined and -//! automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides -//! were not used. We only recommend using build configuration overrides in -//! special situations, like using AsmJit in release configuration with asserts -//! enabled for whatever reason. +//! \note There is usually no need to override the build configuration. AsmJit detects the build configuration by +//! checking whether `NDEBUG` is defined and automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides +//! were not used. We only recommend using build configuration overrides in special situations, like using AsmJit in +//! release configuration with asserts enabled for whatever reason. //! //! ### AsmJit Backends //! -//! AsmJit currently supports only X86/X64 backend, but the plan is to add more -//! backends in the future. By default AsmJit builds only the host backend, which -//! is autodetected at compile-time, but this can be overridden. +//! AsmJit currently supports only X86/X64 backend, but the plan is to add more backends in the future. By default +//! AsmJit builds only the host backend, which is autodetected at compile-time, but this can be overridden. //! //! - \ref ASMJIT_NO_X86 - Disable X86/X64 backends. //! - \ref ASMJIT_NO_FOREIGN - Disables the support for foreign architectures. -//! If defined, it would internally set \ref ASMJIT_BUILD_HOST to true. //! //! ### Features Selection //! -//! AsmJit builds by defaults all supported features, which includes all emitters, -//! logging, instruction validation and introspection, and JIT memory allocation. -//! Features can be disabled at compile time by using `ASMJIT_NO_...` definitions. +//! AsmJit builds by defaults all supported features, which includes all emitters, logging, instruction validation and +//! introspection, and JIT memory allocation. Features can be disabled at compile time by using `ASMJIT_NO_...` +//! definitions. //! -//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time -//! so it won't be available and the compilation will fail if there is -//! attempt to use such API. This includes deprecated classes, namespaces, +//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time so it won't be available and the +//! compilation will fail if there is attempt to use such API. This includes deprecated classes, namespaces, //! enumerations, and functions. //! -//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality -//! completely. This implies \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler -//! cannot be used without \ref asmjit_builder. +//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality completely. This implies \ref +//! ASMJIT_NO_COMPILER as \ref asmjit_compiler cannot be used without \ref asmjit_builder. //! -//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality -//! completely. +//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality completely. //! //! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. //! //! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. //! -//! - \ref ASMJIT_NO_TEXT - Disables everything that contains string -//! representation of AsmJit constants, should be used together with -//! \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the -//! ability to quiry instruction names, register names, etc... +//! - \ref ASMJIT_NO_TEXT - Disables everything that contains string representation of AsmJit constants, should +//! be used together with \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the ability to query +//! instruction names, register names, etc... //! //! - \ref ASMJIT_NO_VALIDATION - Disables validation API. //! -//! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, -//! must be used together with \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler -//! requires introspection for its liveness analysis and register allocation. +//! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, must be used together with \ref +//! ASMJIT_NO_COMPILER as \ref asmjit_compiler requires introspection for its liveness analysis and register +//! allocation. //! -//! \note It's not recommended to disable features if you plan to build AsmJit -//! as a shared library that will be used by multiple projects that you don't -//! control how AsmJit was built (for example AsmJit in a Linux distribution). -//! The possibility to disable certain features exists mainly for customized -//! AsmJit builds. +//! \note It's not recommended to disable features if you plan to build AsmJit as a shared library that will be +//! used by multiple projects that you don't control how AsmJit was built (for example AsmJit in a Linux distribution). +//! The possibility to disable certain features exists mainly for customized AsmJit builds. -// ============================================================================ -// [Documentation - asmjit_breaking_changes] -// ============================================================================ //! \defgroup asmjit_breaking_changes Breaking Changes //! \brief Documentation of breaking changes //! //! ### Overview //! -//! AsmJit is a live project that is being actively developed. Deprecating the -//! existing API in favor of a new one is preferred, but it's not always -//! possible if the changes are significant. AsmJit authors prefer to do -//! accumulated breaking changes at once instead of breaking the API often. -//! This page documents deprecated and removed APIs and should serve as a how-to -//! guide for people that want to port existing code to work with the newest AsmJit. +//! AsmJit is a live project that is being actively developed. Deprecating the existing API in favor of a new +//! one is preferred, but it's not always possible if the changes are significant. AsmJit authors prefer to do +//! accumulated breaking changes at once instead of breaking the API often. This page documents deprecated and +//! removed APIs and should serve as a how-to guide for people that want to port existing code to work with the +//! newest AsmJit. //! //! ### Tips //! //! Useful tips before you start: //! -//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if -//! you need a quick help. +//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if you need a quick help. +//! +//! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that you are not using deprecated +//! functionality at all. Deprecated functions are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes +//! it's not possible to decorate everything like classes, which are used by deprecated functions as well, +//! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED` +//! it's not using anything, which was deprecated. //! -//! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that -//! you are not using deprecated functionality at all. Deprecated functions -//! are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes it's not -//! possible to decorate everything like classes, which are used by deprecated -//! functions as well, because some compilers would warn about that. If your -//! project compiles fine with `ASMJIT_NO_DEPRECATED` it's not using anything, -//! which was deprecated. +//! ### Changes committed at XXXX-XX-XX +//! +//! Core changes: +//! +//! - Removed old deprecated API. +//! +//! - Many enumerations were changed to enum class, and many public APIs were changed to use such enums instead +//! of uint32_t. This change makes some APIs backward incompatible - there are no deprecations this time. +//! +//! - Extracted operand signature manipulation to `OperandSignature`. +//! - Setting function arguments through `Compiler::setArg()` was deprecated, use FuncNode::setArg() instead. +//! - Moved `{arch}::Features::k` to `CpuFeatures::{arch}::k`. +//! - Moved `BaseEmitter::kEncodingOption` to `EncodingOptions::k`. +//! - Moved `BaseEmitter::kFlag` to `EmitterFlags::k`. +//! - Moved `BaseEmitter::kType` to `EmitterType::k`. +//! - Moved `BaseEmitter::kValidationOption` to `DiagnosticOptions::kValidate`. +//! - Moved `BaseFeatures` to `CpuFeatures`. +//! - Moved `BaseInst::kControl` to `InstControlFlow::k`. +//! - Moved `BaseInst::kOption` and `x86::Inst::kOption` to `InstOptions::k`. +//! - Moved `BaseNode::kNode` to `NodeType::k`. +//! - Moved `BaseReg::kGroup` and `x86::Reg::kGroup` to `RegGroup::k`. +//! - Moved `BaseReg::kType` and `x86::Reg::kType` to `RegType::k`. +//! - Moved `CallConv::kFlag` to `CallConvFlags::k`. +//! - Moved `CallConv::kId` to `CallConvId::k`. +//! - Moved `CallConv::kStrategy` to `CallConvStrategy::k`. +//! - Moved `CodeBuffer::kFlag` to `CodeBufferFlags`. +//! - Moved `ConstPool::kScope` to `ConstPoolScope::k`. +//! - Moved `Environment::kArch` to `Arch::k`. +//! - Moved `Environment::kSubArch` to `SubArch::k`. +//! - Moved `Environment::kFormat` to `OjectFormat::k`. +//! - Moved `Environment::kPlatform` to `Platform::k`. +//! - Moved `Environment::kAbi` to `PlatformABI::k`. +//! - Moved `Environment::kVendor` to `Vendor::k`. +//! - Moved `FormatOptions::kFlag` to `FormatFlags::k` and `DiagnosticOptions::k` (Compiler diagnostics flags). +//! - Moved `FormatOptions::kIndentation` to `FormatIndentationGroup::k`. +//! - Moved `FuncFrame::kAttr` to `FuncAttributes::k`. +//! - Moved `Globals::kReset` to `ResetPolicy::k`. +//! - Moved `InstDB::kAvx512Flag` to `InstDB::Avx512Flags::k`. +//! - Moved `InstDB::kFlag` to `InstDB::InstFlags::k`. +//! - Moved `InstDB::kMemFlag` to `InstDB::OpFlags::kMem`. +//! - Moved `InstDB::kMode` to `InstDB::Mode::k`. +//! - Moved `InstDB::kOpFlag` to `InstDB::OpFlags::k{OpType}...`. +//! - Moved `JitAllocator::kOption` to `JitAllocatorOptions::k`. +//! - Moved `Label::kType` to `LabelType::k`. +//! - Moved `Operand::kOpType` to `OperandType::k`. +//! - Moved `OpRWInfo::kFlag` to `OpRWFlags::k`. +//! - Moved `Type::kId` to `TypeId::k`. +//! - Moved `VirtMem::k` to `VirtMem::MemoryFlags::k`. //! //! ### Changes committed at 2020-05-30 //! -//! AsmJit has been cleaned up significantly, many todo items have been fixed -//! and many functions and classes have been redesigned, some in an incompatible -//! way. +//! AsmJit has been cleaned up significantly, many todo items have been fixed and many functions and classes have +//! been redesigned, some in an incompatible way. //! //! Core changes: //! -//! - \ref Imm operand has now only \ref Imm::value() and \ref Imm::valueAs() -//! functions that return its value content, and \ref Imm::setValue() function -//! that sets the content. Functions like `setI8()`, `setU8()` were deprecated. +//! - `Imm` operand has now only `Imm::value()` and `Imm::valueAs()` functions that return its value content, +//! and `Imm::setValue()` function that sets the content. Functions like `setI8()`, `setU8()` were deprecated. //! //! Old functions were deprecated, but code using them should still compile. //! -//! - `ArchInfo` has been replaced with \ref Environment. Environment provides -//! more details about the architecture, but drops some properties that -//! were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can -//! be replaced with `registerSize()` getter, which returns a native register -//! size of the architecture the environment uses. However, `gpCount()` was -//! removed - at the moment \ref ArchRegs can be used to access such properties. +//! - `ArchInfo` has been replaced with `Environment`. Environment provides more details about the architecture, +//! but drops some properties that were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can be replaced +//! with `registerSize()` getter, which returns a native register size of the architecture the environment uses. +//! However, `gpCount()` was removed - at the moment `ArchTraits` can be used to access such properties. //! -//! Some other functions were renamed, like `ArchInfo::isX86Family()` is -//! now \ref Environment::isFamilyX86(), etc. The reason for changing the -//! order was support for more propertries and all the accessors now -//! start with the type of the property, like \ref Environment::isPlatformWindows(). +//! Some other functions were renamed, like `ArchInfo::isX86Family()` is now `Environment::isFamilyX86()`, etc. +//! The reason for changing the order was support for more propertries and all the accessors now start with the +//! type of the property, like `Environment::isPlatformWindows()`. //! -//! This function causes many other classes to provide `environment()` getter -//! instead of `archInfo()` getter. In addition, AsmJit now uses `arch()` to -//! get an architecture instead of `archId()`. `ArchInfo::kIdXXX` was renamed -//! to `Environment::kArchXXX`. +//! This function causes many other classes to provide `environment()` getter instead of `archInfo()` getter. +//! In addition, AsmJit now uses `arch()` to get an architecture instead of `archId()`. `ArchInfo::kIdXXX` was +//! renamed to `Environment::kArchXXX`. //! //! Some functions were deprecated, some removed... //! -//! - `CodeInfo` has been removed in favor of \ref Environment. If you used -//! `CodeInfo` to set architecture and base address, this is now possible -//! with \ref Environment and setting base address explicitly by \ref -//! CodeHolder::init() - the first argument is \ref Environment, and the -//! second argument is base address, which defaults to \ref -//! Globals::kNoBaseAddress. +//! - `CodeInfo` has been removed in favor of `Environment`. If you used `CodeInfo` to set architecture and base +//! address, this is now possible with `Environment` and setting base address explicitly by `CodeHolder::init()` +//! - the first argument is `Environment`, and the second argument is base address, which defaults to +//! `Globals::kNoBaseAddress`. //! -//! CodeInfo class was deprecated, but the code using it should still -//! compile with warnings. +//! CodeInfo class was deprecated, but the code using it should still compile with warnings. //! -//! - \ref CallConv has been updated to offer a more unified way of representing -//! calling conventions - many calling conventions were abstracted to follow -//! standard naming like \ref CallConv::kIdCDecl or \ref CallConv::kIdStdCall. +//! - `CallConv` has been updated to offer a more unified way of representing calling conventions - many calling +//! conventions were abstracted to follow standard naming like `CallConvId::kCDecl` or `CallConvId::kStdCall`. //! -//! This change means that other APIs like \ref FuncDetail::init() now -//! require both, calling convention and target \ref Environment. +//! This change means that other APIs like `FuncDetail::init()` now require both, calling convention and target +//! `Environment`. //! -//! - `Logging` namespace has been renamed to \ref Formatter, which now -//! provides general functionality for formatting in AsmJit. +//! - `Logging` namespace has been renamed to `Formatter`, which now provides general functionality for formatting +//! in AsmJit. //! -//! Logging namespace should still work, but its use is deprecated. -//! Unfortunately this will be without deprecation warnings, so please -//! make sure you don't use it. +//! Logging namespace should still work, but its use is deprecated. Unfortunately this will be without deprecation +//! warnings, so make sure you don't use it. //! -//! - `Data64`, `Data128`, and `Data256` structs were deprecated and should -//! no longer be used. There is no replacement, AsmJit users should simply -//! create their own structures if they need them or use the new repeated -//! embed API in emitters, see \ref BaseEmitter::embedDataArray(). +//! - `Data64`, `Data128`, and `Data256` structs were deprecated and should no longer be used. There is no replacement, +//! AsmJit users should simply create their own structures if they need them or use the new repeated embed API in +//! emitters, see `BaseEmitter::embedDataArray()`. //! //! Emitter changes: //! -//! - \ref BaseEmitter::emit() function signature has been changed to accept -//! 3 operands by reference and the rest 3 operands as a continuous array. -//! This change is purely cosmetic and shouldn't affect users as emit() -//! has many overloads that dispatch to the right function. +//! - `BaseEmitter::emit()` function signature has been changed to accept 3 operands by reference and the rest 3 +//! operands as a continuous array. This change is purely cosmetic and shouldn't affect users as emit() has many +//! overloads that dispatch to the right function. //! -//! - \ref x86::Emitter (Assembler, Builder, Compiler) deprecates embed -//! utilities like `dint8()`, `duint8()`, `duint16()`, `dxmm()`, etc... -//! in favor of a new and more powerful \ref BaseEmitter::embedDataArray(). -//! This function also allows emitting repeated values and/or patterns, -//! which is used by helpers \ref BaseEmitter::embedUInt8(), and others... +//! - `x86::Emitter` (Assembler, Builder, Compiler) deprecates embed utilities like `dint8()`, `duint8()`, `duint16()`, +//! `dxmm()`, etc... in favor of a new and more powerful `BaseEmitter::embedDataArray()`. This function also allows +//! emitting repeated values and/or patterns, which is used by helpers `BaseEmitter::embedUInt8()`, and others... //! -//! - Validation is now available through \ref BaseEmitter::ValidationOptions, -//! which can be enabled/disabled through \ref BaseEmitter::addValidationOptions() -//! and \ref BaseEmitter::clearValidationOptions(), respectively. Validation -//! options now separate between encoding and Builder/Compiler so it's possible -//! to choose the granularity required. +//! - Validation is now available through `BaseEmitter::DiagnosticOptions`, which can be enabled/disabled through +//! `BaseEmitter::addDiagnosticOptions()` and `BaseEmitter::clearDiagnosticOptions()`, respectively. Validation +//! options now separate between encoding and Builder/Compiler so it's possible to choose the granularity required. //! //! Builder changes: //! -//! - Internal functions for creating nodes were redesigned. They now accept -//! a pointer to the node created as a first parameter. These changes should -//! not affect AsmJit users as these functions were used internally. +//! - Internal functions for creating nodes were redesigned. They now accept a pointer to the node created as +//! a first parameter. These changes should not affect AsmJit users as these functions were used internally. //! //! Compiler changes: //! -//! - `FuncCallNode` has been renamed to \ref InvokeNode. Additionally, function -//! calls should now use \ref x86::Compiler::invoke() instead of `call()`. -//! The reason behind this is to remove the confusion between a `call` -//! instruction and AsmJit's `call()` intrinsic, which is now `invoke()`. +//! - `FuncCallNode` has been renamed to `InvokeNode`. Additionally, function calls should now use +//! `x86::Compiler::invoke()` instead of `call()`. The reason behind this is to remove the confusion between a +//! `call` instruction and AsmJit's `call()` intrinsic, which is now `invoke()`. //! -//! - Creating new nodes also changed. Now the preferred way of invoking a -//! function is to call \ref x86::Compiler::invoke() where the first -//! argument is `InvokeNode**`. The function now returns an error and would -//! call \ref ErrorHandler in case of a failure. Error handling was -//! unspecified in the past - the function was marked noexcept, but called -//! error handler, which could throw. +//! - Creating new nodes also changed. Now the preferred way of invoking a function is to call +//! `x86::Compiler::invoke()` where the first argument is `InvokeNode**`. The function now returns an error and +//! would call `ErrorHandler` in case of a failure. Error handling was unspecified in the past - the function was +//! marked noexcept, but called error handler, which could throw. //! -//! The reason behind this change is to make the API consistent with other -//! changes and to also make it possible to inspect the possible error. In -//! the previous API it returned a new node or `nullptr` in case of error, -//! which the user couldn't inspect unless there was an attached \ref -//! ErrorHandler. +//! The reason behind this change is to make the API consistent with other changes and to also make it possible +//! to inspect the possible error. In the previous API it returned a new node or `nullptr` in case of error, +//! which the user couldn't inspect unless there was an attached `ErrorHandler`. //! //! Samples: //! //! ``` //! #include <asmjit/x86.h> +//! //! using namespace asmjit; //! //! // The basic setup of JitRuntime and CodeHolder changed, use environment() @@ -438,55 +394,46 @@ namespace asmjit { //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_core] -// ============================================================================ //! \defgroup asmjit_core Core //! \brief Globals, code storage, and emitter interface. //! //! ### Overview //! -//! AsmJit library uses \ref CodeHolder to hold code during code generation and -//! emitters inheriting from \ref BaseEmitter to emit code. CodeHolder uses -//! containers to manage its data: +//! AsmJit library uses \ref CodeHolder to hold code during code generation and emitters inheriting from \ref +//! BaseEmitter to emit code. CodeHolder uses containers to manage its data: //! //! - \ref Section - stores information about a code or data section. //! - \ref CodeBuffer - stores actual code or data, part of \ref Section. -//! - \ref LabelEntry - stores information about a label - its name, offset, -//! section where it belongs to, and other bits. -//! - \ref LabelLink - stores information about yet unbound label, which was -//! already used by the assembler. +//! - \ref LabelEntry - stores information about a label - its name, offset, section where it belongs to, and +//! other bits. +//! - \ref LabelLink - stores information about yet unbound label, which was already used by the assembler. //! - \ref RelocEntry - stores information about a relocation. -//! - \ref AddressTableEntry - stores information about an address, which was -//! used in a jump or call. Such address may need relocation. +//! - \ref AddressTableEntry - stores information about an address, which was used in a jump or call. Such +//! address may need relocation. //! //! To generate code you would need to instantiate at least the following classes: //! //! - \ref CodeHolder - to hold code during code generation. //! - \ref BaseEmitter - to emit code into \ref CodeHolder. -//! - \ref Target (optional) - most likely \ref JitRuntime to keep the generated -//! code in executable memory. \ref Target can be customized by inheriting from -//! it. +//! - \ref Target (optional) - most likely \ref JitRuntime to keep the generated code in executable memory. \ref +//! Target can be customized by inheriting from it. //! //! There are also other core classes that are important: //! -//! - \ref Environment - describes where the code will run. Environment brings -//! the concept of target triples or tuples into AsmJit, which means that users -//! can specify target architecture, platform, and ABI. -//! - \ref Type - encapsulates lightweight type functionality that can be used -//! to describe primitive and vector types. Types are used by higher level -//! utilities, for example by \ref asmjit_function and \ref asmjit_compiler. -//! - \ref CpuInfo - encapsulates CPU information - stores both CPU information -//! and features described by \ref BaseFeatures. +//! - \ref Environment - describes where the code will run. Environment brings the concept of target triples or +//! tuples into AsmJit, which means that users can specify target architecture, platform, and ABI. +//! - \ref TypeId - encapsulates lightweight type functionality that can be used to describe primitive and vector +//! types. Types are used by higher level utilities, for example by \ref asmjit_function and \ref asmjit_compiler. +//! - \ref CpuInfo - encapsulates CPU information - stores both CPU information and CPU features described by \ref +//! CpuFeatures. //! //! AsmJit also provides global constants: //! //! - \ref Globals - namespace that provides global constants. //! - \ref ByteOrder - byte-order constants and functionality. //! -//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot -//! be used to generate code. +//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code. //! //! ### CodeHolder & Emitters //! @@ -529,8 +476,8 @@ namespace asmjit { //! } //! ``` //! -//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the -//! following emitters that offer various levels of abstraction: +//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the following emitters that offer various +//! levels of abstraction: //! //! - \ref asmjit_assembler - Low-level emitter that emits directly to \ref CodeBuffer. //! - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list. @@ -538,30 +485,25 @@ namespace asmjit { //! //! ### Targets and JitRuntime //! -//! AsmJit's \ref Target is an interface that provides basic target abstraction. -//! At the moment AsmJit provides only one implementation called \ref JitRuntime, -//! which as the name suggests provides JIT code target and execution runtime. -//! \ref JitRuntime provides all the necessary stuff to implement a simple JIT -//! compiler with basic memory management. It only provides \ref JitRuntime::add() -//! and \ref JitRuntime::release() functions that are used to either add code -//! to the runtime or release it. \ref JitRuntime doesn't do any decisions on -//! when the code should be released, the decision is up to the developer. +//! AsmJit's \ref Target is an interface that provides basic target abstraction. At the moment AsmJit provides only +//! one implementation called \ref JitRuntime, which as the name suggests provides JIT code target and execution +//! runtime. \ref JitRuntime provides all the necessary stuff to implement a simple JIT compiler with basic memory +//! management. It only provides \ref JitRuntime::add() and \ref JitRuntime::release() functions that are used to +//! either add code to the runtime or release it. \ref JitRuntime doesn't do any decisions on when the code should be +//! released, the decision is up to the developer. //! //! See more at \ref asmjit_virtual_memory group. //! //! ### More About Environment //! -//! In the previous example the \ref Environment is retrieved from \ref JitRuntime. -//! It's logical as \ref JitRuntime always returns an \ref Environment that is -//! compatible with the host. For example if your application runs in 64-bit mode -//! the \ref Environment returned will use \ref Environment::kArchX64 architecture -//! in contrast to \ref Environment::kArchX86, which will be used in 32-bit mode on -//! any X86 platform. +//! In the previous example the \ref Environment is retrieved from \ref JitRuntime. It's logical as \ref JitRuntime +//! always returns an \ref Environment that is compatible with the host. For example if your application runs on X86_64 +//! CPU the \ref Environment returned will use \ref Arch::kX64 architecture in contrast to \ref Arch::kX86, which will +//! be used in 32-bit mode on an X86 target. //! -//! AsmJit allows to setup the \ref Environment manually and to select a different -//! architecture and ABI when necessary. So let's do something else this time, let's -//! always generate a 32-bit code and print its binary representation. To do that, we -//! can create our own \ref Environment and initialize it to \ref Environment::kArchX86. +//! AsmJit allows to setup the \ref Environment manually and to select a different architecture and ABI when necessary. +//! So let's do something else this time, let's always generate a 32-bit code and print its binary representation. To +//! do that, we can create our own \ref Environment and initialize it to \ref Arch::kX86. //! //! ``` //! #include <asmjit/x86.h> @@ -574,7 +516,7 @@ namespace asmjit { //! //! // Create a custom environment initialized to 32-bit X86 architecture. //! Environment env; -//! env.setArch(Environment::kArchX86); +//! env.setArch(Arch::kX86); //! //! CodeHolder code; // Create a CodeHolder. //! code.init(env); // Initialize CodeHolder with custom environment. @@ -612,46 +554,37 @@ namespace asmjit { //! //! ### Explicit Code Relocation //! -//! In addition to \ref Environment, \ref CodeHolder can be configured to -//! specify a base-address (or a virtual base-address in a linker terminology), -//! which could be static (useful when you know the location where the target's -//! machine code will be) or dynamic. AsmJit assumes dynamic base-address by -//! default and relocates the code held by \ref CodeHolder to a user provided -//! address on-demand. To be able to relocate to a user provided address it needs -//! to store some information about relocations, which is represented by \ref -//! RelocEntry. Relocation entries are only required if you call external functions -//! from the generated code that cannot be encoded by using a 32-bit displacement -//! (64-bit displacements are not provided by aby supported architecture). -//! -//! There is also a concept called \ref LabelLink - label link is a lightweight -//! data structure that doesn't have any identifier and is stored in \ref LabelEntry -//! as a single-linked list. Label link represents either unbound yet used label -//! and cross-sections links (only relevant to code that uses multiple sections). -//! Since crossing sections is something that cannot be resolved immediately these -//! links persist until offsets of these sections are assigned and until -//! \ref CodeHolder::resolveUnresolvedLinks() is called. It's an error if you end -//! up with code that has unresolved label links after flattening. You can verify -//! it by calling \ref CodeHolder::hasUnresolvedLinks(), which inspects the value -//! returned by \ref CodeHolder::unresolvedLinkCount(). -//! -//! AsmJit can flatten code that uses multiple sections by assigning each section -//! an incrementing offset that respects its alignment. Use \ref CodeHolder::flatten() -//! to do that. After the sections are flattened their offsets and virtual-sizes -//! are adjusted to respect each section's buffer size and alignment. The \ref -//! CodeHolder::resolveUnresolvedLinks() function must be called before relocating -//! the code held by \ref CodeHolder. You can also flatten your code manually by -//! iterating over all sections and calculating their offsets (relative to base) -//! by your own algorithm. In that case \ref CodeHolder::flatten() should not be -//! called, however, \ref CodeHolder::resolveUnresolvedLinks() should be. -//! -//! The example below shows how to use a built-in virtual memory allocator -//! \ref JitAllocator instead of using \ref JitRuntime (just in case you want -//! to use your own memory management) and how to relocate the generated code -//! into your own memory block - you can use your own virtual memory allocator -//! if you prefer that, but that's OS specific and not covered by the documentation. -//! -//! The following code is similar to the previous one, but implements a function -//! working in both 32-bit and 64-bit environments: +//! In addition to \ref Environment, \ref CodeHolder can be configured to specify a base-address (or a virtual base +//! address in a linker terminology), which could be static (useful when you know the location where the target's +//! machine code will be) or dynamic. AsmJit assumes dynamic base-address by default and relocates the code held by +//! \ref CodeHolder to a user provided address on-demand. To be able to relocate to a user provided address it needs +//! to store some information about relocations, which is represented by \ref RelocEntry. Relocation entries are only +//! required if you call external functions from the generated code that cannot be encoded by using a 32-bit +//! displacement (64-bit displacements are not provided by aby supported architecture). +//! +//! There is also a concept called \ref LabelLink - label link is a lightweight data structure that doesn't have any +//! identifier and is stored in \ref LabelEntry as a single-linked list. Label link represents either unbound yet used +//! label and cross-sections links (only relevant to code that uses multiple sections). Since crossing sections is +//! something that cannot be resolved immediately these links persist until offsets of these sections are assigned and +//! until \ref CodeHolder::resolveUnresolvedLinks() is called. It's an error if you end up with code that has +//! unresolved label links after flattening. You can verify it by calling \ref CodeHolder::hasUnresolvedLinks(), which +//! inspects the value returned by \ref CodeHolder::unresolvedLinkCount(). +//! +//! AsmJit can flatten code that uses multiple sections by assigning each section an incrementing offset that respects +//! its alignment. Use \ref CodeHolder::flatten() to do that. After the sections are flattened their offsets and +//! virtual sizes are adjusted to respect each section's buffer size and alignment. The \ref +//! CodeHolder::resolveUnresolvedLinks() function must be called before relocating the code held by \ref CodeHolder. +//! You can also flatten your code manually by iterating over all sections and calculating their offsets (relative to +//! base) by your own algorithm. In that case \ref CodeHolder::flatten() should not be called, however, +//! \ref CodeHolder::resolveUnresolvedLinks() should be. +//! +//! The example below shows how to use a built-in virtual memory allocator \ref JitAllocator instead of using \ref +//! JitRuntime (just in case you want to use your own memory management) and how to relocate the generated code +//! into your own memory block - you can use your own virtual memory allocator if you prefer that, but that's OS +//! specific and not covered by the documentation. +//! +//! The following code is similar to the previous one, but implements a function working in both 32-bit and 64-bit +//! environments: //! //! ``` //! #include <asmjit/x86.h> @@ -663,7 +596,7 @@ namespace asmjit { //! //! int main() { //! // Create a custom environment that matches the current host environment. -//! Environment env = hostEnvironment(); +//! Environment env = Environment::host(); //! //! CodeHolder code; // Create a CodeHolder. //! code.init(env); // Initialize CodeHolder with environment. @@ -752,7 +685,7 @@ namespace asmjit { //! // memcpy((uint8_t*)p + section->offset(), //! // section->data(), //! // section->bufferSize()); -//! code.copyFlattenedData(p, codeSize, CodeHolder::kCopyPadSectionBuffer); +//! code.copyFlattenedData(p, codeSize, CopySectionFlags::kPadSectionBuffer); //! //! // Execute the generated function. //! int inA[4] = { 4, 3, 2, 1 }; @@ -774,18 +707,19 @@ namespace asmjit { //! } //! ``` //! -//! If you know the base-address in advance (before the code generation) it can -//! be passed as a second argument to \ref CodeHolder::init(). In that case the -//! Assembler will know the absolute position of each instruction and would be -//! able to use it during instruction encoding to prevent relocations where -//! possible. The following example shows how to configure the base address: +//! If you know the base-address in advance (before the code generation) it can be passed as a second argument to +//! \ref CodeHolder::init(). In that case the Assembler will know the absolute position of each instruction and +//! would be able to use it during instruction encoding to prevent relocations where possible. The following example +//! shows how to configure the base address: //! //! ``` //! #include <asmjit/x86.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void initializeCodeHolder(CodeHolder& code) { -//! Environment env = hostEnvironment(); +//! Environment env = Environment::host(); //! uint64_t baseAddress = uint64_t(0x1234); //! //! // initialize CodeHolder with environment and custom base address. @@ -795,16 +729,16 @@ namespace asmjit { //! //! ### Label Offsets and Links //! -//! When a label that is not yet bound is used by the Assembler, it creates a -//! \ref LabelLink, which is then added to a \ref LabelEntry. These links are -//! also created if a label is used in a different section than in which it -//! was bound. Let's examine some functions that can be used to check whether -//! there are any unresolved links. +//! When a label that is not yet bound is used by the Assembler, it creates a \ref LabelLink, which is then added to +//! a \ref LabelEntry. These links are also created if a label is used in a different section than in which it was +//! bound. Let's examine some functions that can be used to check whether there are any unresolved links. //! //! ``` //! #include <asmjit/core.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void labelLinksExample(CodeHolder& code, const Label& label) { //! // Tests whether the `label` is bound. //! bool isBound = code.isLabelBound(label); @@ -819,16 +753,17 @@ namespace asmjit { //! } //! ``` //! -//! There is no function that would return the number of unbound labels as this -//! is completely unimportant from CodeHolder's perspective. If a label is not -//! used then it doesn't matter whether it's bound or not, only actually used -//! labels matter. After a Label is bound it's possible to query its offset -//! offset relative to the start of the section where it was bound: +//! There is no function that would return the number of unbound labels as this is completely unimportant from +//! CodeHolder's perspective. If a label is not used then it doesn't matter whether it's bound or not, only actually +//! used labels matter. After a Label is bound it's possible to query its offset offset relative to the start of the +//! section where it was bound: //! //! ``` //! #include <asmjit/core.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void labelOffsetExample(CodeHolder& code, const Label& label) { //! // Label offset is known after it's bound. The offset provided is relative //! // to the start of the section, see below for alternative. If the given @@ -848,15 +783,16 @@ namespace asmjit { //! //! ### Sections //! -//! AsmJit allows to create multiple sections within the same \ref CodeHolder. -//! A test-case [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp) -//! can be used as a reference point although the following example should -//! also provide a useful insight: +//! AsmJit allows to create multiple sections within the same \ref CodeHolder. A test-case +//! [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp) +//! can be used as a reference point although the following example should also provide a useful insight: //! //! ``` //! #include <asmjit/x86.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! void sectionsExample(CodeHolder& code) { //! // Text section is always provided as the first section. //! Section* text = code.textSection(); // or code.sectionById(0); @@ -864,11 +800,11 @@ namespace asmjit { //! // To create another section use CodeHolder::newSection(). //! Section* data; //! Error err = code.newSection(&data, -//! ".data", // Section name -//! SIZE_MAX, // Name length if the name is not null terminated (or SIZE_MAX). -//! 0, // Section flags, see Section::Flags. -//! 8, // Section alignment, must be power of 2. -//! 0); // Section order value (optional, default 0). +//! ".data", // Section name +//! SIZE_MAX, // Name length if the name is not null terminated (or SIZE_MAX). +//! SectionFlags::kNone, // Section flags, see SectionFlags. +//! 8, // Section alignment, must be power of 2. +//! 0); // Section order value (optional, default 0). //! //! // When you switch sections in Assembler, Builder, or Compiler the cursor //! // will always move to the end of that section. When you create an Assembler @@ -893,17 +829,17 @@ namespace asmjit { //! } //! ``` //! -//! The last line in the example above shows that a LabelLink would be created -//! even for bound labels that cross sections. In this case a referenced label -//! was bound in another section, which means that the link couldn't be resolved -//! at that moment. If your code uses sections, but you wish AsmJit to flatten -//! these sections (you don't plan to flatten them manually) then there is an -//! API for that. +//! The last line in the example above shows that a LabelLink would be created even for bound labels that cross +//! sections. In this case a referenced label was bound in another section, which means that the link couldn't be +//! resolved at that moment. If your code uses sections, but you wish AsmJit to flatten these sections (you don't +//! plan to flatten them manually) then there is an API for that. //! //! ``` //! #include <asmjit/x86.h> //! #include <stdio.h> //! +//! using namespace asmjit; +//! //! // ... (continuing the previous example) ... //! void sectionsExampleContinued(CodeHolder& code) { //! // Suppose we have some code that contains multiple sections and @@ -938,18 +874,14 @@ namespace asmjit { //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_assembler] -// ============================================================================ //! \defgroup asmjit_assembler Assembler //! \brief Assembler interface and operands. //! //! ### Overview //! -//! AsmJit's Assembler is used to emit machine code directly into a \ref -//! CodeBuffer. In general, code generation with assembler requires the knowledge -//! of the following: +//! AsmJit's Assembler is used to emit machine code directly into a \ref CodeBuffer. In general, code generation +//! with assembler requires the knowledge of the following: //! //! - \ref BaseAssembler and architecture-specific assemblers: //! - \ref x86::Assembler - Assembler specific to X86 architecture @@ -961,76 +893,58 @@ namespace asmjit { //! - \ref Imm - Immediate (value) operand. //! - \ref Label - Label operand. //! -//! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot -//! be used to generate code. +//! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot be used to generate code. //! //! ### Operand Basics //! -//! Let's start with operands. \ref Operand is a data structure that defines a -//! data layout of any operand. It can be inherited, but any class inheriting -//! it cannot add any members to it, only the existing layout can be reused. -//! AsmJit allows to construct operands dynamically, to store them, and to query -//! a complete information about them at run-time. Operands are small (always 16 -//! bytes per \ref Operand) and can be copied and passed by value. Please never -//! allocate individual operands dynamically by using a `new` keyword - it would -//! work, but then you would have to be responsible for deleting such operands. -//! In AsmJit operands are always part of some other data structures like \ref -//! InstNode, which is part of \ref asmjit_builder tool. -//! -//! Operands contain only identifiers, but not pointers to any code-generation data. -//! For example \ref Label operand only provides label identifier, but not a pointer -//! to \ref LabelEntry structure. In AsmJit such IDs are used to link stuff together -//! without having to deal with pointers. -//! -//! AsmJit's operands all inherit from a base class called \ref Operand. Operands -//! have the following properties that are commonly accessible by getters and setters: -//! -//! - \ref Operand - Base operand, which only provides accessors that are common -//! to all operand types. -//! - \ref BaseReg - Describes either physical or virtual register. Physical -//! registers have id that matches the target's machine id directly whereas -//! virtual registers must be allocated into physical registers by a register +//! Let's start with operands. \ref Operand is a data structure that defines a data layout of any operand. It can be +//! inherited, but any class inheriting it cannot add any members to it, only the existing layout can be reused. +//! AsmJit allows to construct operands dynamically, to store them, and to query a complete information about them +//! at run-time. Operands are small (always 16 bytes per \ref Operand) and can be copied and passed by value. Please +//! never allocate individual operands dynamically by using a `new` keyword - it would work, but then you would have +//! to be responsible for deleting such operands. In AsmJit operands are always part of some other data structures +//! like \ref InstNode, which is part of \ref asmjit_builder tool. +//! +//! Operands contain only identifiers, but not pointers to any code-generation data. For example \ref Label operand +//! only provides label identifier, but not a pointer to \ref LabelEntry structure. In AsmJit such IDs are used to +//! link stuff together without having to deal with pointers. +//! +//! AsmJit's operands all inherit from a base class called \ref Operand. Operands have the following properties that +//! are commonly accessible by getters and setters: +//! +//! - \ref Operand - Base operand, which only provides accessors that are common to all operand types. +//! - \ref BaseReg - Describes either physical or virtual register. Physical registers have id that matches the +//! target's machine id directly whereas virtual registers must be allocated into physical registers by a register //! allocator pass. Register operand provides: -//! - Register Type - Unique id that describes each possible register provided -//! by the target architecture - for example X86 backend provides \ref -//! x86::Reg::RegType, which defines all variations of general purpose registers -//! (GPB-LO, GPB-HI, GPW, GPD, and GPQ) and all types of other registers like K, -//! MM, BND, XMM, YMM, and ZMM. -//! - Register Group - Groups multiple register types under a single group - for -//! example all general-purpose registers (of all sizes) on X86 are part of -//! \ref x86::Reg::kGroupGp and all SIMD registers (XMM, YMM, ZMM) are part -//! of \ref x86::Reg::kGroupVec. -//! - Register Size - Contains the size of the register in bytes. If the size -//! depends on the mode (32-bit vs 64-bit) then generally the higher size is -//! used (for example RIP register has size 8 by default). +//! - Register Type (\ref RegType) - Unique id that describes each possible register provided by the target +//! architecture - for example X86 backend provides general purpose registers (GPB-LO, GPB-HI, GPW, GPD, and GPQ) +//! and all types of other registers like K, MM, BND, XMM, YMM, ZMM, and TMM. +//! - Register Group (\ref RegGroup) - Groups multiple register types under a single group - for example all +//! general-purpose registers (of all sizes) on X86 are part of \ref RegGroup::kGp and all SIMD registers +//! (XMM, YMM, ZMM) are part of \ref RegGroup::kVec. +//! - Register Size - Contains the size of the register in bytes. If the size depends on the mode (32-bit vs +//! 64-bit) then generally the higher size is used (for example RIP register has size 8 by default). //! - Register Id - Contains physical or virtual id of the register. //! - \ref BaseMem - Used to reference a memory location. Memory operand provides: //! - Base Register - A base register type and id (physical or virtual). //! - Index Register - An index register type and id (physical or virtual). -//! - Offset - Displacement or absolute address to be referenced (32-bit if base -//! register is used and 64-bit if base register is not used). -//! - Flags that can describe various architecture dependent information (like -//! scale and segment-override on X86). -//! - \ref Imm - Immediate values are usually part of instructions (encoded within -//! the instruction itself) or data. -//! - \ref Label - used to reference a location in code or data. Labels must be -//! created by the \ref BaseEmitter or by \ref CodeHolder. Each label has its -//! unique id per \ref CodeHolder instance. +//! - Offset - Displacement or absolute address to be referenced (32-bit if base register is used and 64-bit if +//! base register is not used). +//! - Flags that can describe various architecture dependent information (like scale and segment-override on X86). +//! - \ref Imm - Immediate values are usually part of instructions (encoded within the instruction itself) or data. +//! - \ref Label - used to reference a location in code or data. Labels must be created by the \ref BaseEmitter or +//! by \ref CodeHolder. Each label has its unique id per \ref CodeHolder instance. //! //! ### Operand Manipulation //! -//! AsmJit allows to construct operands dynamically, to store them, and to query -//! a complete information about them at run-time. Operands are small (always 16 -//! bytes per `Operand`) and should be always copied (by value) if you intend to -//! store them (don't create operands by using `new` keyword, it's not recommended). -//! Operands are safe to be passed to `memcpy()` and `memset()`, which becomes -//! handy when working with arrays of operands. If you set all members of an \ref -//! Operand to zero the operand would become NONE operand, which is the same as a -//! default constructed Operand. +//! AsmJit allows to construct operands dynamically, to store them, and to query a complete information about them at +//! run-time. Operands are small (always 16 bytes per `Operand`) and should be always copied (by value) if you intend +//! to store them (don't create operands by using `new` keyword, it's not recommended). Operands are safe to be passed +//! to `memcpy()` and `memset()`, which becomes handy when working with arrays of operands. If you set all members of +//! an \ref Operand to zero the operand would become NONE operand, which is the same as a default constructed Operand. //! -//! The example below illustrates how operands can be used and modified even -//! without using any other code generation classes. The example uses X86 -//! architecture-specific operands. +//! The example below illustrates how operands can be used and modified even without using any other code generation +//! classes. The example uses X86 architecture-specific operands. //! //! ``` //! #include <asmjit/x86.h> @@ -1050,7 +964,7 @@ namespace asmjit { //! // Constructs [src + idx] memory address - referencing [rax + r10]. //! x86::Mem m = x86::ptr(src, idx); //! -//! // Examine `m`: Returns `x86::Reg::kTypeGpq`. +//! // Examine `m`: Returns `RegType::kX86_Gpq`. //! m.indexType(); //! // Examine `m`: Returns 10 (`r10`). //! m.indexId(); @@ -1088,23 +1002,20 @@ namespace asmjit { //! } //! ``` //! -//! Some operands have to be created explicitly by emitters. For example labels -//! must be created by \ref BaseEmitter::newLabel(), which creates a label entry -//! and returns a \ref Label operand with the id that refers to it. Such label -//! then can be used by emitters. +//! Some operands have to be created explicitly by emitters. For example labels must be created by \ref +//! BaseEmitter::newLabel(), which creates a label entry and returns a \ref Label operand with the id that refers +//! to it. Such label then can be used by emitters. //! //! ### Memory Operands //! -//! Some architectures like X86 provide a complex memory addressing model that -//! allows to encode addresses having a BASE register, INDEX register with a -//! possible scale (left shift), and displacement (called offset in AsmJit). -//! Memory address on X86 can also specify memory segment (segment-override in -//! X86 terminology) and some instructions (gather / scatter) require INDEX to -//! be a \ref x86::Vec register instead of a general-purpose register. +//! Some architectures like X86 provide a complex memory addressing model that allows to encode addresses having a +//! BASE register, INDEX register with a possible scale (left shift), and displacement (called offset in AsmJit). +//! Memory address on X86 can also specify memory segment (segment-override in X86 terminology) and some instructions +//! (gather / scatter) require INDEX to be a \ref x86::Vec register instead of a general-purpose register. //! -//! AsmJit allows to encode and work with all forms of addresses mentioned and -//! implemented by X86. In addition, it also allows to construct absolute 64-bit -//! memory address operands, which is only allowed in one form of 'mov' instruction. +//! AsmJit allows to encode and work with all forms of addresses mentioned and implemented by X86. In addition, it +//! also allows to construct absolute 64-bit memory address operands, which is only allowed in one form of 'mov' +//! instruction. //! //! ``` //! #include <asmjit/x86.h> @@ -1147,9 +1058,8 @@ namespace asmjit { //! } //! ``` //! -//! Memory operands can optionally contain memory size. This is required by -//! instructions where the memory size cannot be deduced from other operands, -//! like `inc` and `dec` on X86: +//! Memory operands can optionally contain memory size. This is required by instructions where the memory size cannot +//! be deduced from other operands, like `inc` and `dec` on X86: //! //! ``` //! #include <asmjit/x86.h> @@ -1233,34 +1143,26 @@ namespace asmjit { //! //! - \ref x86::Assembler provides many X86/X64 examples. -// ============================================================================ -// [Documentation - asmjit_builder] -// ============================================================================ //! \defgroup asmjit_builder Builder //! \brief Builder interface, nodes, and passes. //! //! ### Overview //! -//! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters -//! that emit into a representation that allows further processing. The code -//! stored in such representation is completely safe to be patched, simplified, -//! reordered, obfuscated, removed, injected, analyzed, or processed some other -//! way. Each instruction, label, directive, or other building block is stored -//! as \ref BaseNode (or derived class like \ref InstNode or \ref LabelNode) -//! and contains all the information necessary to pass that node later to the -//! assembler. -//! -//! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. -//! It was designed to provide a maximum compatibility with the existing \ref -//! BaseAssembler emitter so users can move from assembler to builder when needed, +//! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters that emit into a representation that +//! allows further processing. The code stored in such representation is completely safe to be patched, simplified, +//! reordered, obfuscated, removed, injected, analyzed, or processed some other way. Each instruction, label, +//! directive, or other building block is stored as \ref BaseNode (or derived class like \ref InstNode or \ref +//! LabelNode) and contains all the information necessary to pass that node later to the assembler. +//! +//! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. It was designed to provide a maximum +//! compatibility with the existing \ref BaseAssembler emitter so users can move from assembler to builder when needed, //! for example to implement post-processing, which is not possible with Assembler. //! //! ### Builder Nodes //! -//! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate -//! representation based on nodes, however, it allows to serialize to \ref BaseAssembler -//! when the code is ready to be encoded. +//! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate representation based on nodes, +//! however, it allows to serialize to \ref BaseAssembler when the code is ready to be encoded. //! //! There are multiple node types used by both \ref BaseBuilder and \ref BaseCompiler : //! @@ -1273,16 +1175,13 @@ namespace asmjit { //! - Data nodes: //! - \ref EmbedDataNode - Represents data. //! - \ref EmbedLabelNode - Represents \ref Label address embedded as data. -//! - \ref EmbedLabelDeltaNode - Represents a difference of two labels -//! embedded in data. +//! - \ref EmbedLabelDeltaNode - Represents a difference of two labels embedded in data. //! - \ref ConstPoolNode - Represents a constant pool data embedded as data. //! //! - Informative nodes: -//! - \ref CommentNode - Represents a comment string, doesn't affect code -//! generation. -//! - \ref SentinelNode - A marker that can be used to remember certain -//! position in code or data, doesn't affect code generation. Used by -//! \ref FuncNode to mark the end of a function. +//! - \ref CommentNode - Represents a comment string, doesn't affect code generation. +//! - \ref SentinelNode - A marker that can be used to remember certain position in code or data, doesn't affect +//! code generation. Used by \ref FuncNode to mark the end of a function. //! //! - Other nodes are provided by \ref asmjit_compiler infrastructure. //! @@ -1290,47 +1189,38 @@ namespace asmjit { //! //! - \ref x86::Builder provides many X86/X64 examples. -// ============================================================================ -// [Documentation - asmjit_compiler] -// ============================================================================ //! \defgroup asmjit_compiler Compiler //! \brief Compiler interface. //! //! ### Overview //! -//! \ref BaseCompiler is a high-level interface built on top of \ref BaseBuilder -//! interface, which provides register allocation and support for defining and -//! invoking functions. At the moment it's the easiest way of generating code -//! in AsmJit as most architecture and OS specifics is properly abstracted and -//! handled by AsmJit automatically. However, abstractions also mean restrictions, -//! which means that \ref BaseCompiler has more limitations than \ref BaseAssembler -//! or \ref BaseBuilder. -//! -//! Since \ref BaseCompiler provides register allocation it also establishes the -//! concept of functions - a function in Compiler sense is a unit in which virtual -//! registers are allocated into physical registers by the register allocator. -//! In addition, it enables to use such virtual registers in function invocations. -//! -//! \ref BaseCompiler automatically handles function calling conventions. It's -//! still architecture dependent, but makes the code generation much easies. -//! Functions are essential; the first-step to generate some code is to define a -//! signature of the function to be generated (before generating the function body -//! itself). Function arguments and return value(s) are handled by assigning -//! virtual registers to them. Similarly, function calls are handled the same way. +//! \ref BaseCompiler is a high-level interface, which provides register allocation and support for defining and +//! invoking functions, built on top of \ref BaseBuilder interface At the moment it's the easiest way of generating +//! code in AsmJit as most architecture and OS specifics is properly abstracted and handled by AsmJit automatically. +//! However, abstractions also mean restrictions, which means that \ref BaseCompiler has more limitations than \ref +//! BaseAssembler or \ref BaseBuilder. +//! +//! Since \ref BaseCompiler provides register allocation it also establishes the concept of functions - a function +//! in Compiler sense is a unit in which virtual registers are allocated into physical registers by the register +//! allocator. In addition, it enables to use such virtual registers in function invocations. +//! +//! \ref BaseCompiler automatically handles function calling conventions. It's still architecture dependent, but +//! makes the code generation much easies. Functions are essential; the first-step to generate some code is to define +//! a signature of the function to be generated (before generating the function body itself). Function arguments and +//! return value(s) are handled by assigning virtual registers to them. Similarly, function calls are handled the same +//! way. //! //! ### Compiler Nodes //! -//! \ref BaseCompiler adds some nodes that are required for function generation -//! and invocation: +//! \ref BaseCompiler adds some nodes that are required for function generation and invocation: //! //! - \ref FuncNode - Represents a function definition. //! - \ref FuncRetNode - Represents a function return. //! - \ref InvokeNode - Represents a function invocation. //! -//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically -//! adds an architecture-dependent register allocator pass to the list of passes -//! when attached to \ref CodeHolder. +//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically adds an architecture-dependent +//! register allocator pass to the list of passes when attached to \ref CodeHolder. //! //! ### Compiler Examples //! @@ -1338,134 +1228,110 @@ namespace asmjit { //! //! ### Compiler Tips //! -//! Users of AsmJit have done mistakes in the past, this section should provide -//! some useful tips for beginners: +//! Users of AsmJit have done mistakes in the past, this section should provide some useful tips for beginners: //! -//! - Virtual registers in compiler are bound to a single function. At the -//! moment the implementation doesn't care whether a single virtual register -//! is used in multiple functions, but it sees it as two independent virtual -//! registers in that case. This means that virtual registers cannot be used -//! to implement global variables. Global variables are basically memory -//! addresses which functions can read from and write to, and they have to -//! be implemented in the same way. +//! - Virtual registers in compiler are bound to a single function. At the moment the implementation doesn't +//! care whether a single virtual register is used in multiple functions, but it sees it as two independent +//! virtual registers in that case. This means that virtual registers cannot be used to implement global +//! variables. Global variables are basically memory addresses which functions can read from and write to, +//! and they have to be implemented in the same way. //! -//! - Compiler provides a useful debugging functionality, which can be turned -//! on through \ref FormatOptions::Flags. Use \ref Logger::addFlags() to -//! turn on additional logging features when using Compiler. +//! - Compiler provides a useful debugging functionality, which can be turned on through \ref FormatFlags. Use +//! \ref Logger::addFlags() to turn on additional logging features when using Compiler. -// ============================================================================ -// [Documentation - asmjit_function] -// ============================================================================ //! \defgroup asmjit_function Function //! \brief Function definitions. //! //! ### Overview //! -//! AsmJit provides functionality that can be used to define function signatures -//! and to calculate automatically optimal function frame that can be used directly -//! by a prolog and epilog insertion. This feature was exclusive to AsmJit's Compiler -//! for a very long time, but was abstracted out and is now available for all users -//! regardless of the emitter they use. The following use cases are possible: +//! AsmJit provides functionality that can be used to define function signatures and to calculate automatically +//! optimal function frame that can be used directly by a prolog and epilog insertion. This feature was exclusive +//! to AsmJit's Compiler for a very long time, but was abstracted out and is now available for all users regardless +//! of the emitter they use. The following use cases are possible: //! -//! - Calculate function frame before the function is generated - this is the -//! only way available to \ref BaseAssembler users and it will be described -//! in this section. +//! - Calculate function frame before the function is generated - this is the only way available to \ref +//! BaseAssembler users and it will be described in this section. //! -//! - Calculate function frame after the function is generated - this way is -//! generally used by \ref BaseBuilder and \ref BaseCompiler emitters and -//! this way is generally described in \ref asmjit_compiler section. +//! - Calculate function frame after the function is generated - this way is generally used by \ref BaseBuilder +//! and \ref BaseCompiler emitters and this way is generally described in \ref asmjit_compiler section. //! //! The following concepts are used to describe and create functions in AsmJit: //! -//! - \ref Type::Id - Type-id is an 8-bit value that describes a platform -//! independent type as we know from C/C++. It provides abstractions for -//! most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, -//! `double`, and all possible vector types to match ISAs up to AVX512. -//! \ref Type::Id was introduced originally for \ref asmjit_compiler, but -//! it's now used by \ref FuncSignature as well. -//! -//! - \ref CallConv - Describes a calling convention - this class contains -//! instructions to assign registers and stack addresses to function -//! arguments and return value(s), but doesn't specify any function -//! signature itself. Calling conventions are architecture and OS dependent. -//! -//! - \ref FuncSignature - Describes a function signature, for example -//! `int func(int, int)`. FuncSignature contains a function calling convention -//! id, return value type, and function arguments. The signature itself is -//! platform independent and uses \ref Type::Id to describe types of function -//! arguments and function return value(s). -//! -//! - \ref FuncDetail - Architecture and ABI dependent information that describes -//! \ref CallConv and expanded \ref FuncSignature. Each function argument and -//! return value is represented as \ref FuncValue that contains the original -//! \ref Type::Id enriched with additional information that specifies whether -//! the value is passed or returned by register (and which register) or by -//! stack. Each value also contains some other metadata that provide additional -//! information required to handle it properly (for example whether a vector is -//! passed indirectly by a pointer as required by WIN64 calling convention). -//! -//! - \ref FuncFrame - Contains information about the function frame that can -//! be used by prolog/epilog inserter (PEI). Holds call stack size size and -//! alignment, local stack size and alignment, and various attributes that -//! describe how prolog and epilog should be constructed. `FuncFrame` doesn't -//! know anything about function's arguments or return values, it hold only -//! information necessary to create a valid and ABI conforming function prologs -//! and epilogs. -//! -//! - \ref FuncArgsAssignment - A helper class that can be used to reassign -//! function arguments into user specified registers. It's architecture and -//! ABI dependent mapping from function arguments described by \ref CallConv +//! - \ref TypeId - Type-id is an 8-bit value that describes a platform independent type as we know from C/C++. +//! It provides abstractions for most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, `double`, +//! and all possible vector types to match ISAs up to AVX512. \ref TypeId was introduced originally for \ref +//! asmjit_compiler, but it's now used by \ref FuncSignature as well. +//! +//! - \ref CallConv - Describes a calling convention - this class contains instructions to assign registers and +//! stack addresses to function arguments and return value(s), but doesn't specify any function signature itself. +//! Calling conventions are architecture and OS dependent. +//! +//! - \ref FuncSignature - Describes a function signature, for example `int func(int, int)`. FuncSignature contains +//! a function calling convention id, return value type, and function arguments. The signature itself is platform +//! independent and uses \ref TypeId to describe types of function arguments and function return value(s). +//! +//! - \ref FuncDetail - Architecture and ABI dependent information that describes \ref CallConv and expanded \ref +//! FuncSignature. Each function argument and return value is represented as \ref FuncValue that contains the +//! original \ref TypeId enriched with additional information that specifies whether the value is passed or +//! returned by register (and which register) or by stack. Each value also contains some other metadata that +//! provide additional information required to handle it properly (for example whether a vector is passed +//! indirectly by a pointer as required by WIN64 calling convention). +//! +//! - \ref FuncFrame - Contains information about the function frame that can be used by prolog/epilog inserter +//! (PEI). Holds call stack size size and alignment, local stack size and alignment, and various attributes that +//! describe how prolog and epilog should be constructed. `FuncFrame` doesn't know anything about function's +//! arguments or return values, it hold only information necessary to create a valid and ABI conforming function +//! prologs and epilogs. +//! +//! - \ref FuncArgsAssignment - A helper class that can be used to reassign function arguments into user specified +//! registers. It's architecture and ABI dependent mapping from function arguments described by \ref CallConv //! and \ref FuncDetail into registers specified by the user. //! -//! It's a lot of concepts where each represents one step in a function frame -//! calculation. It can be used to create function prologs, epilogs, and also -//! to calculate information necessary to perform function calls. +//! It's a lot of concepts where each represents one step in a function frame calculation. It can be used to create +//! function prologs, epilogs, and also to calculate information necessary to perform function calls. -// ============================================================================ -// [Documentation - asmjit_logging] -// ============================================================================ //! \defgroup asmjit_logging Logging //! \brief Logging and formatting. //! //! ### Overview //! -//! The initial phase of a project that generates machine code is not always smooth. -//! Failure cases are common not just at the beginning phase, but also during the -//! development or refactoring. AsmJit provides logging functionality to address -//! this issue. AsmJit does already a good job with function overloading to prevent -//! from emitting unencodable instructions, but it can't prevent from emitting machine -//! code that is correct at instruction level, but doesn't work when it's executed as -//! a whole. Logging has always been an important part of AsmJit's infrastructure and -//! looking at logs can sometimes reveal code generation issues quickly. +//! The initial phase of a project that generates machine code is not always smooth. Failure cases are common not just +//! at the beginning phase, but also during the development or refactoring. AsmJit provides logging functionality to +//! address this issue. AsmJit does already a good job with function overloading to prevent from emitting unencodable +//! instructions, but it can't prevent from emitting machine code that is correct at instruction level, but doesn't +//! work when it's executed asa whole. Logging has always been an important part of AsmJit's infrastructure and looking +//! at logs can sometimes reveal code generation issues quickly. //! //! AsmJit provides API for logging and formatting: -//! - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters -//! that inherit from \ref BaseEmitter. -//! - \ref FormatOptions - Formatting options that can change how instructions and -//! operands are formatted. -//! - \ref Formatter - A namespace that provides functions that can format input -//! data like \ref Operand, \ref BaseReg, \ref Label, and \ref BaseNode into -//! \ref String. +//! +//! - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters that inherit from \ref BaseEmitter. +//! +//! - \ref FormatOptions - Formatting options that can change how instructions and operands are formatted. +//! +//! - \ref Formatter - A namespace that provides functions that can format input data like \ref Operand, \ref BaseReg, +//! \ref Label, and \ref BaseNode into \ref String. //! //! AsmJit's \ref Logger serves the following purposes: +//! //! - Provides a basic foundation for logging. -//! - Abstract class leaving the implementation on users. The following built-in -//! implementations are provided for simplicity: +//! +//! - Abstract class leaving the implementation on users. The following built-in implementations are provided for +//! simplicity: +//! //! - \ref FileLogger implements logging into a standard `FILE` stream. //! - \ref StringLogger serializes all logs into a \ref String instance. //! -//! AsmJit's \ref FormatOptions provides the following to customize the formatting of -//! instructions and operands through: -//! - \ref FormatOptions::Flags -//! - \ref FormatOptions::IndentationType +//! AsmJit's \ref FormatOptions provides the following to customize the formatting of instructions and operands through: +//! +//! - \ref FormatFlags +//! - \ref FormatIndentationGroup //! //! ### Logging //! -//! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it -//! to all attached emitters automatically. The example below illustrates how to -//! use \ref FileLogger that outputs to standard output: +//! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it to all attached emitters +//! automatically. The example below illustrates how to use \ref FileLogger that outputs to standard output: //! //! ``` //! #include <asmjit/core.h> @@ -1486,8 +1352,8 @@ namespace asmjit { //! } //! ``` //! -//! If output to FILE stream is not desired it's possible to use \ref StringLogger, -//! which concatenates everything into a multi-line string: +//! If output to FILE stream is not desired it's possible to use \ref StringLogger, which concatenates everything +//! into a multi-line string: //! //! ``` //! #include <asmjit/core.h> @@ -1520,11 +1386,10 @@ namespace asmjit { //! //! ### Formatting //! -//! AsmJit uses \ref Formatter to format inputs that are then passed to \ref -//! Logger. Formatting is public and can be used by AsmJit users as well. The -//! most important thing to know regarding formatting is that \ref Formatter -//! always appends to the output string, so it can be used to build complex -//! strings without having to concatenate intermediate strings. +//! AsmJit uses \ref Formatter to format inputs that are then passed to \ref Logger. Formatting is public and can be +//! used by AsmJit users as well. The most important thing to know regarding formatting is that \ref Formatter always +//! appends to the output string, so it can be used to build complex strings without having to concatenate +//! intermediate strings. //! //! The first example illustrates how to format operands: //! @@ -1534,12 +1399,12 @@ namespace asmjit { //! //! using namespace asmjit; //! -//! void logOperand(uint32_t arch, const Operand_& op) { +//! void logOperand(Arch arch, const Operand_& op) { //! // The emitter is optional (named labels and virtual registers need it). //! BaseEmitter* emitter = nullptr; //! //! // No flags by default. -//! uint32_t formatFlags = FormatOptions::kNoFlags; +//! FormatFlags formatFlags = FormatFlags::kNone; //! //! StringTmp<128> sb; //! Formatter::formatOperand(sb, formatFlags, emitter, arch, op); @@ -1552,7 +1417,7 @@ namespace asmjit { //! // Architecture is not part of operand, it must be passed explicitly. //! // Format flags. We pass it explicitly also to 'logOperand' to make //! // compatible with what AsmJit normally does. -//! uint32_t arch = Environment::kArchX64; +//! Arch arch = Arch::kX64; //! //! log(arch, rax); // Prints 'rax'. //! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. @@ -1571,12 +1436,12 @@ namespace asmjit { //! using namespace asmjit; //! //! template<typename... Args> -//! void logInstruction(uint32_t arch, const BaseInst& inst, Args&&... args) { +//! void logInstruction(Arch arch, const BaseInst& inst, Args&&... args) { //! // The emitter is optional (named labels and virtual registers need it). //! BaseEmitter* emitter = nullptr; //! //! // No flags by default. -//! uint32_t formatFlags = FormatOptions::kNoFlags; +//! FormatFlags formatFlags = FormatFlags::kNone; //! //! // The formatter expects operands in an array. //! Operand_ operands { std::forward<Args>(args)... }; @@ -1593,7 +1458,7 @@ namespace asmjit { //! // Architecture is not part of operand, it must be passed explicitly. //! // Format flags. We pass it explicitly also to 'logOperand' to make //! // compatible with what AsmJit normally does. -//! uint32_t arch = Environment::kArchX64; +//! Arch arch = Arch::kX64; //! //! // Prints 'mov rax, rcx'. //! logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx); @@ -1606,19 +1471,19 @@ namespace asmjit { //! // BaseInst abstracts instruction id, instruction options, and extraReg. //! // Prints 'lock add [rax], rcx'. //! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionLock), +//! BaseInst(Inst::kIdAdd, InstOptions::kX86_Lock), //! x86::ptr(rax), rcx); //! //! // Similarly an extra register (like AVX-512 selector) can be used. //! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'. //! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionZMask, k2), +//! BaseInst(Inst::kIdAdd, InstOptions::kX86_ZMask, k2), //! zmm0, zmm1, ptr(rax)); //! } //! ``` //! -//! And finally, the example below illustrates how to use a built-in function -//! to format the content of \ref BaseBuilder, which consists of nodes: +//! And finally, the example below illustrates how to use a built-in function to format the content of +//! \ref BaseBuilder, which consists of nodes: //! //! ``` //! #include <asmjit/core.h> @@ -1627,7 +1492,7 @@ namespace asmjit { //! using namespace asmjit; //! //! void formattingExample(BaseBuilder* builder) { -//! uint32_t formatFlags = FormatOptions::kNoFlags; +//! FormatFlags formatFlags = FormatFlags::kNone; //! //! // This also shows how temporary strings can be used. //! StringTmp<512> sb; @@ -1644,40 +1509,30 @@ namespace asmjit { //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_error_handling] -// ============================================================================ //! \defgroup asmjit_error_handling Error Handling //! \brief Error handling. //! //! ### Overview //! -//! AsmJit uses error codes to represent and return errors. Every function that -//! can fail returns an \ref Error code. Exceptions are never thrown by AsmJit -//! itself even in extreme conditions like out-of-memory, but it's possible to -//! override \ref ErrorHandler::handleError() to throw, in that case no error -//! will be returned and exception will be thrown instead. All functions where -//! this can happen are not marked `noexcept`. +//! AsmJit uses error codes to represent and return errors. Every function that can fail returns an \ref Error code. +//! Exceptions are never thrown by AsmJit itself even in extreme conditions like out-of-memory, but it's possible to +//! override \ref ErrorHandler::handleError() to throw, in that case no error will be returned and exception will be +//! thrown instead. All functions where this can happen are not marked `noexcept`. //! -//! Errors should never be ignored, however, checking errors after each AsmJit -//! API call would simply overcomplicate the whole code generation experience. -//! \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows +//! Errors should never be ignored, however, checking errors after each AsmJit API call would simply overcomplicate +//! the whole code generation experience. \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows //! to customize how errors can be handled: //! //! - Record the error and continue (the way how the error is user-implemented). -//! - Throw an exception. AsmJit doesn't use exceptions and is completely -//! exception-safe, but it's perfectly legal to throw an exception from -//! the error handler. -//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, -//! Builder and Compiler to a consistent state before calling \ref -//! ErrorHandler::handleError(), so `longjmp()` can be used without issues to -//! cancel the code-generation if an error occurred. This method can be used if -//! exception handling in your project is turned off and you still want some -//! comfort. In most cases it should be safe as AsmJit uses \ref Zone memory -//! and the ownership of memory it allocates always ends with the instance that -//! allocated it. If using this approach please never jump outside the life-time -//! of \ref CodeHolder and \ref BaseEmitter. +//! - Throw an exception. AsmJit doesn't use exceptions and is completely exception-safe, but it's perfectly legal +//! to throw an exception from the error handler. +//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, Builder and Compiler to a +//! consistent state before calling \ref ErrorHandler::handleError(), so `longjmp()` can be used without issues +//! to cancel the code-generation if an error occurred. This method can be used if exception handling in your +//! project is turned off and you still want some comfort. In most cases it should be safe as AsmJit uses \ref +//! Zone memory and the ownership of memory it allocates always ends with the instance that allocated it. If +//! using this approach please never jump outside the life-time of \ref CodeHolder and \ref BaseEmitter. //! //! ### Using ErrorHandler //! @@ -1719,69 +1574,56 @@ namespace asmjit { //! - See \ref Error that lists error codes that AsmJit uses. //! - See \ref ErrorHandler for more details about error handling. -// ============================================================================ -// [Documentation - asmjit_instruction_db] -// ============================================================================ //! \defgroup asmjit_instruction_db Instruction DB //! \brief Instruction database (introspection, read/write, validation, ...). //! //! ### Overview //! -//! AsmJit provides a public instruction database that can be used to query -//! information about a complete instruction. The instruction database requires -//! the knowledge of the following: +//! AsmJit provides a public instruction database that can be used to query information about a complete instruction. +//! The instruction database requires the knowledge of the following: +//! +//! - \ref BaseInst - Base instruction that contains instruction id, options, and a possible extra-register that +//! represents either REP prefix counter or AVX-512 selector (mask). //! -//! - \ref BaseInst - Base instruction that contains instruction id, options, -//! and a possible extra-register that represents either REP prefix counter -//! or AVX-512 selector (mask). //! - \ref Operand - Represents operands of an instruction. //! //! Each instruction can be then queried for the following information: //! -//! - \ref InstRWInfo - Read/write information of instruction and its oprands. -//! - \ref OpRWInfo - Read/write information of a single operand, part of -//! \ref InstRWInfo data structure. -//! - \ref BaseFeatures - CPU features required to execute the instruction. +//! - \ref InstRWInfo - Read/write information of instruction and its oprands (includes \ref OpRWInfo). +//! +//! - \ref CpuFeatures - CPU features required to execute the instruction. //! -//! In addition to query functionality AsmJit is also able to validate whether -//! an instruction and its operands are valid. This is useful for making sure -//! that what user tries to emit is correct and it can be also used by other +//! In addition to query functionality AsmJit is also able to validate whether an instruction and its operands are +//! valid. This is useful for making sure that what user tries to emit is correct and it can be also used by other //! projects that parse user input, like AsmTK project. //! //! ### Query API //! -//! The instruction query API is provided by \ref InstAPI namespace. The -//! following queries are possible: +//! The instruction query API is provided by \ref InstAPI namespace. The following queries are possible: //! -//! - \ref InstAPI::queryRWInfo() - queries read/write information of the -//! given instruction and its operands. Includes also CPU flags read/written. +//! - \ref InstAPI::queryRWInfo() - queries read/write information of the given instruction and its operands. +//! Includes also CPU flags read/written. //! -//! - \ref InstAPI::queryFeatures() - queries CPU features that are required -//! to execute the given instruction. A full instruction with operands must -//! be given as some architectures like X86 may require different features -//! for the same instruction based on its operands. +//! - \ref InstAPI::queryFeatures() - queries CPU features that are required to execute the given instruction. A full +//! instruction with operands must be given as some architectures like X86 may require different features for the +//! same instruction based on its operands. //! -//! - <a href="https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_instinfo.cpp">asmjit_test_x86_instinfo.cpp</a> +//! - <a href="https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_instinfo.cpp">asmjit_test_instinfo.cpp</a> //! can be also used as a reference about accessing instruction information. //! //! ### Validation API //! -//! The instruction validation API is provided by \ref InstAPI namespace in the -//! similar fashion like the Query API, however, validation can also be turned -//! on at \ref BaseEmitter level. The following is possible: +//! The instruction validation API is provided by \ref InstAPI namespace in the similar fashion like the Query API, +//! however, validation can also be turned on at \ref BaseEmitter level. The following is possible: //! -//! - \ref InstAPI::validate() - low-level instruction validation function -//! that is used internally by emitters if strict validation is enabled. +//! - \ref InstAPI::validate() - low-level instruction validation function that is used internally by emitters +//! if strict validation is enabled. //! -//! - \ref BaseEmitter::addValidationOptions() - can be used to enable -//! validation at emitter level, see \ref BaseEmitter::ValidationOptions. +//! - \ref BaseEmitter::addDiagnosticOptions() - can be used to enable validation at emitter level, see \ref +//! DiagnosticOptions. -// ============================================================================ -// [Documentation - asmjit_virtual_memory] -// ============================================================================ - //! \defgroup asmjit_virtual_memory Virtual Memory //! \brief Virtual memory management. //! @@ -1789,53 +1631,42 @@ namespace asmjit { //! //! AsmJit's virtual memory management is divided into two main categories: //! -//! - Low level API that provides cross-platform abstractions for virtual -//! memory allocation. Implemented in \ref VirtMem namespace. -//! - High level API that makes it very easy to store generated code for -//! execution. See \ref JitRuntime, which is used by many examples for its -//! simplicity and easy integration with \ref CodeHolder. There is also -//! \ref JitAllocator, which lays somewhere between RAW memory allocation -//! and \ref JitRuntime. +//! - Low level API that provides cross-platform abstractions for virtual memory allocation. Implemented in +//! \ref VirtMem namespace. +//! +//! - High level API that makes it very easy to store generated code for execution. See \ref JitRuntime, which is +//! used by many examples for its simplicity and easy integration with \ref CodeHolder. There is also \ref +//! JitAllocator, which lays somewhere between RAW memory allocation and \ref JitRuntime. -// ============================================================================ -// [Documentation - asmjit_zone_memory] -// ============================================================================ //! \defgroup asmjit_zone Zone Memory //! \brief Zone memory allocator and containers. //! //! ### Overview //! -//! AsmJit uses zone memory allocation (also known as Arena allocation) to allocate -//! most of the data it uses. It's a fast allocator that allows AsmJit to allocate -//! a lot of small data structures fast and without `malloc()` overhead. Since -//! code generators and all related classes are usually short-lived this approach -//! decreases memory usage and fragmentation as arena-based allocators always -//! allocate larger blocks of memory, which are then split into smaller chunks. -//! -//! Another advantage of zone memory allocation is that since the whole library -//! uses this strategy it's very easy to deallocate everything that a particular -//! instance is holding by simply releasing the memory the allocator holds. This -//! improves destruction time of such objects as there is no destruction at all. -//! Long-lived objects just reset its data in destructor or in their reset() -//! member function for a future reuse. For this purpose all containers in AsmJit -//! are also zone allocated. +//! AsmJit uses zone memory allocation (also known as Arena allocation) to allocate most of the data it uses. It's a +//! fast allocator that allows AsmJit to allocate a lot of small data structures fast and without `malloc()` overhead. +//! Since code generators and all related classes are usually short-lived this approach decreases memory usage and +//! fragmentation as arena-based allocators always allocate larger blocks of memory, which are then split into smaller +//! chunks. +//! +//! Another advantage of zone memory allocation is that since the whole library uses this strategy it's very easy to +//! deallocate everything that a particular instance is holding by simply releasing the memory the allocator holds. +//! This improves destruction time of such objects as there is no destruction at all. Long-lived objects just reset +//! its data in destructor or in their reset() member function for a future reuse. For this purpose all containers in +//! AsmJit are also zone allocated. //! //! ### Zone Allocation //! -//! - \ref Zone - Incremental zone memory allocator with minimum features. It -//! can only allocate memory without the possibility to return it back to -//! the allocator. +//! - \ref Zone - Incremental zone memory allocator with minimum features. It can only allocate memory without the +//! possibility to return it back to the allocator. //! -//! - \ref ZoneTmp - A temporary \ref Zone with some initial static storage. -//! If the allocation requests fit the static storage allocated then there -//! will be no dynamic memory allocation during the lifetime of \ref ZoneTmp, -//! otherwise it would act as \ref Zone with one preallocated block on the -//! stack. +//! - \ref ZoneTmp - A temporary \ref Zone with some initial static storage. If the allocation requests fit the +//! static storage allocated then there will be no dynamic memory allocation during the lifetime of \ref ZoneTmp, +//! otherwise it would act as \ref Zone with one preallocated block on the stack. //! -//! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability -//! of returning memory to the allocator. Such memory is stored in a pool for -//! later reuse. +//! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability of returning memory to the allocator. +//! Such memory is stored in a pool for later reuse. //! //! ### Zone Allocated Containers //! @@ -1849,11 +1680,10 @@ namespace asmjit { //! //! ### Using Zone Allocated Containers //! -//! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very -//! similar to `std::vector`, but the implementation doesn't use exceptions and -//! uses the mentioned \ref ZoneAllocator for performance reasons. You don't have -//! to worry about allocations as you should not need to add items to AsmJit's -//! data structures directly as there should be API for all required operations. +//! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very similar to `std::vector`, but the +//! implementation doesn't use exceptions and uses the mentioned \ref ZoneAllocator for performance reasons. You don't +//! have to worry about allocations as you should not need to add items to AsmJit's data structures directly as there +//! should be API for all required operations. //! //! The following APIs in \ref CodeHolder returns \ref ZoneVector reference: //! @@ -1875,10 +1705,9 @@ namespace asmjit { //! } //! ``` //! -//! \ref ZoneVector has overloaded array access operator to make it possible -//! to access its elements through operator[]. Some standard functions like -//! \ref ZoneVector::empty(), \ref ZoneVector::size(), and \ref ZoneVector::data() -//! are provided as well. Vectors are also iterable through a range-based for loop: +//! \ref ZoneVector has overloaded array access operator to make it possible to access its elements through operator[]. +//! Some standard functions like \ref ZoneVector::empty(), \ref ZoneVector::size(), and \ref ZoneVector::data() are +//! provided as well. Vectors are also iterable through a range-based for loop: //! //! ``` //! using namespace asmjit; @@ -1895,15 +1724,13 @@ namespace asmjit { //! //! ### Design Considerations //! -//! Zone-allocated containers do not store the allocator within the container. -//! This decision was made to reduce the footprint of such containers as AsmJit -//! tooling, especially Compiler's register allocation, may use many instances +//! Zone-allocated containers do not store the allocator within the container. This decision was made to reduce the +//! footprint of such containers as AsmJit tooling, especially Compiler's register allocation, may use many instances //! of such containers to perform code analysis and register allocation. //! -//! For example to append an item into a \ref ZoneVector it's required to pass -//! the allocator as the first argument, so it can be used in case that the -//! vector needs a reallocation. Such function also returns an error, which -//! must be propagated to the caller. +//! For example to append an item into a \ref ZoneVector it's required to pass the allocator as the first argument, +//! so it can be used in case that the vector needs a reallocation. Such function also returns an error, which must +//! be propagated to the caller. //! //! ``` //! using namespace asmjit @@ -1927,10 +1754,9 @@ namespace asmjit { //! } //! ``` //! -//! Containers like \ref ZoneVector also provide a functionality to reserve a -//! certain number of items before any items are added to it. This approach is -//! used internally in most places as it allows to prepare space for data that -//! will be added to some container before the data itself was created. +//! Containers like \ref ZoneVector also provide a functionality to reserve a certain number of items before any items +//! are added to it. This approach is used internally in most places as it allows to prepare space for data that will +//! be added to some container before the data itself was created. //! //! ``` //! using namespace asmjit @@ -1948,60 +1774,44 @@ namespace asmjit { //! } //! ``` -// ============================================================================ -// [Documentation - asmjit_utilities] -// ============================================================================ //! \defgroup asmjit_utilities Utilities //! \brief Utility classes and functions. //! //! ### Overview //! -//! AsmJit uses and provides utility classes and functions, that can be used -//! with AsmJit. The functionality can be divided into the following topics: +//! AsmJit uses and provides utility classes and functions, that can be used with AsmJit. The functionality can be +//! divided into the following topics: //! //! ### String Functionality //! -//! - \ref String - AsmJit's string container, which is used internally -//! and which doesn't use exceptions and has a stable layout, which is -//! not dependent on C++ standard library. -//! - \ref StringTmp - String that can have base storage allocated on -//! stack. The amount of storage on stack can be specified as a template -//! parameter. +//! - \ref String - AsmJit's string container, which is used internally and which doesn't use exceptions and has +//! a stable layout, which is not dependent on C++ standard library. +//! +//! - \ref StringTmp - String that can have base storage allocated on stack. The amount of storage on stack can +//! be specified as a template parameter. +//! //! - \ref FixedString - Fixed string container limited up to N characters. //! //! ### Code Generation Utilities //! -//! - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also -//! available to users that may find use of it. +//! - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also available to users that may find use of it. //! //! ### Support Functionality Used by AsmJit //! -//! - \ref Support namespace provides many other utility functions and -//! classes that are used by AsmJit, and made public. +//! - \ref Support namespace provides many other utility functions and classes that are used by AsmJit, and made +//! public. -// ============================================================================ -// [Documentation - asmjit_<arch> backends] -// ============================================================================ //! \defgroup asmjit_x86 X86 Backend //! \brief X86/X64 backend. -// ============================================================================ -// [Documentation - asmjit_ra] -// ============================================================================ //! \cond INTERNAL //! \defgroup asmjit_ra RA //! \brief Register allocator internals. //! \endcond -} // {asmjit} - -// ============================================================================ -// [Core Headers] -// ============================================================================ - #include "asmjit-scope-begin.h" #include "core/archtraits.h" #include "core/assembler.h" @@ -2010,11 +1820,9 @@ namespace asmjit { #include "core/compiler.h" #include "core/constpool.h" #include "core/cpuinfo.h" -#include "core/datatypes.h" #include "core/emitter.h" #include "core/environment.h" #include "core/errorhandler.h" -#include "core/features.h" #include "core/formatter.h" #include "core/func.h" #include "core/globals.h" @@ -2038,23 +1846,4 @@ namespace asmjit { #include "core/zonevector.h" #include "asmjit-scope-end.h" -// ============================================================================ -// [Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED -namespace asmjit { - -#ifndef ASMJIT_NO_COMPILER -ASMJIT_DEPRECATED("Use InvokeNode instead of FuncCallNode") -typedef InvokeNode FuncCallNode; -#endif // !ASMJIT_NO_COMPILER - -#ifndef ASMJIT_NO_LOGGING -namespace Logging { using namespace Formatter; } -#endif //! ASMJIT_NO_LOGGING - -} // {asmjit} -#endif // !ASMJIT_NO_DEPRECATED - #endif // ASMJIT_CORE_H_INCLUDED diff --git a/src/asmjit/core/api-build_p.h b/src/asmjit/core/api-build_p.h index db37ca7..6eca971 100644 --- a/src/asmjit/core/api-build_p.h +++ b/src/asmjit/core/api-build_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_API_BUILD_P_H_INCLUDED #define ASMJIT_CORE_API_BUILD_P_H_INCLUDED @@ -47,10 +29,6 @@ #include <windows.h> #endif -// ============================================================================ -// [asmjit::Build - Globals - Build-Only] -// ============================================================================ - #include "./api-config.h" #if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) && !defined(__clang__) diff --git a/src/asmjit/core/api-config.h b/src/asmjit/core/api-config.h index c3f1080..7407c57 100644 --- a/src/asmjit/core/api-config.h +++ b/src/asmjit/core/api-config.h @@ -1,48 +1,59 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_API_CONFIG_H_INCLUDED #define ASMJIT_CORE_API_CONFIG_H_INCLUDED -// ============================================================================ -// [asmjit::Version] -// ============================================================================ +// AsmJit Library & ABI Version +// ============================ //! \addtogroup asmjit_core //! \{ //! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format. -#define ASMJIT_LIBRARY_VERSION 0x010400 /* 1.4.0 */ +#define ASMJIT_LIBRARY_VERSION 0x010800 /* 1.8.0 */ + +//! \def ASMJIT_ABI_NAMESPACE +//! +//! AsmJit ABI namespace is an inline namespace within \ref asmjit namespace. +//! +//! It's used to make sure that when user links to an incompatible version of AsmJit, it won't link. It has also some +//! additional properties as well. When `ASMJIT_ABI_NAMESPACE` is defined by the user it would override the AsmJit +//! default, which makes it possible to use use multiple AsmJit libraries within a single project, totally controlled +//! by the users. This is useful especially in cases in which some of such library comes from a third party. +#ifndef ASMJIT_ABI_NAMESPACE + #define ASMJIT_ABI_NAMESPACE _abi_1_8 +#endif //! \} -// ============================================================================ -// [asmjit::Build - Documentation] -// ============================================================================ +// Global Dependencies +// =================== + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> // We really want std types as globals, not under 'std' namespace. +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <iterator> +#include <limits> +#include <new> +#include <type_traits> +#include <utility> + +#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) + #include <pthread.h> +#endif + +// Build Options +// ============= -// NOTE: Doxygen cannot document macros that are not defined, that's why we have -// to define them and then undefine them, so it won't use the macros with its -// own preprocessor. +// NOTE: Doxygen cannot document macros that are not defined, that's why we have to define them and then undefine +// them immediately, so it won't use the macros with its own preprocessor. #ifdef _DOXYGEN namespace asmjit { @@ -80,10 +91,10 @@ namespace asmjit { //! Disables \ref asmjit_compiler functionality completely. #define ASMJIT_NO_COMPILER -//! Disables JIT memory management and \ref JitRuntime. +//! Disables JIT memory management and \ref asmjit::JitRuntime. #define ASMJIT_NO_JIT -//! Disables \ref Logger and \ref Formatter. +//! Disables \ref asmjit::Logger and \ref asmjit::Formatter. #define ASMJIT_NO_LOGGING //! Disables everything that contains text. @@ -116,33 +127,6 @@ namespace asmjit { } // {asmjit} #endif // _DOXYGEN -// ============================================================================ -// [asmjit::Dependencies] -// ============================================================================ - -// We really want std-types as globals. -#include <stdarg.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <iterator> -#include <limits> -#include <new> -#include <type_traits> -#include <utility> - -#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) - #include <pthread.h> -#endif - - -// ============================================================================ -// [asmjit::Options] -// ============================================================================ - // ASMJIT_NO_BUILDER implies ASMJIT_NO_COMPILER. #if defined(ASMJIT_NO_BUILDER) && !defined(ASMJIT_NO_COMPILER) #define ASMJIT_NO_COMPILER @@ -150,37 +134,17 @@ namespace asmjit { // Prevent compile-time errors caused by misconfiguration. #if defined(ASMJIT_NO_TEXT) && !defined(ASMJIT_NO_LOGGING) - #pragma "ASMJIT_NO_TEXT can only be defined when ASMJIT_NO_LOGGING is defined." + #pragma message("'ASMJIT_NO_TEXT' can only be defined when 'ASMJIT_NO_LOGGING' is defined.") #undef ASMJIT_NO_TEXT #endif #if defined(ASMJIT_NO_INTROSPECTION) && !defined(ASMJIT_NO_COMPILER) - #pragma message("ASMJIT_NO_INTROSPECTION can only be defined when ASMJIT_NO_COMPILER is defined") + #pragma message("'ASMJIT_NO_INTROSPECTION' can only be defined when 'ASMJIT_NO_COMPILER' is defined") #undef ASMJIT_NO_INTROSPECTION #endif -// ============================================================================ -// [asmjit::Build - Globals - Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED - #if defined(ASMJIT_BUILD_EMBED) || defined(ASMJIT_BUILD_STATIC) - #if defined(ASMJIT_BUILD_EMBED) - #pragma message("'ASMJIT_BUILD_EMBED' is deprecated, use 'ASMJIT_STATIC'") - #endif - #if defined(ASMJIT_BUILD_STATIC) - #pragma message("'ASMJIT_BUILD_STATIC' is deprecated, use 'ASMJIT_STATIC'") - #endif - - #if !defined(ASMJIT_STATIC) - #define ASMJIT_STATIC - #endif - #endif -#endif // !ASMJIT_NO_DEPRECATED - -// ============================================================================ -// [asmjit::Build - Globals - Build Mode] -// ============================================================================ +// Build Mode +// ========== // Detect ASMJIT_BUILD_DEBUG and ASMJIT_BUILD_RELEASE if not defined. #if !defined(ASMJIT_BUILD_DEBUG) && !defined(ASMJIT_BUILD_RELEASE) @@ -191,9 +155,8 @@ namespace asmjit { #endif #endif -// ============================================================================ -// [asmjit::Build - Globals - Target Architecture Information] -// ============================================================================ +// Target Architecture Detection +// ============================= #if defined(_M_X64) || defined(__x86_64__) #define ASMJIT_ARCH_X86 64 @@ -239,19 +202,15 @@ namespace asmjit { #define ASMJIT_ARCH_BE 0 #endif -// ============================================================================ -// [asmjit::Build - Globals - Backends] -// ============================================================================ - #if defined(ASMJIT_NO_FOREIGN) #if !ASMJIT_ARCH_X86 && !defined(ASMJIT_NO_X86) #define ASMJIT_NO_X86 #endif #endif -// ============================================================================ -// [asmjit::Build - Globals - C++ Compiler and Features Detection] -// ============================================================================ + +// C++ Compiler and Features Detection +// =================================== #define ASMJIT_CXX_GNU 0 #define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR)) @@ -293,9 +252,12 @@ namespace asmjit { #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK))) #endif -// ============================================================================ -// [asmjit::Build - Globals - API Decorators & Language Extensions] -// ============================================================================ +// API Decorators & C++ Extensions +// =============================== + +//! \def ASMJIT_API +//! +//! A decorator that is used to decorate API that AsmJit exports when built as a shared library. // API (Export / Import). #if !defined(ASMJIT_STATIC) @@ -324,12 +286,12 @@ namespace asmjit { #define ASMJIT_VARAPI extern ASMJIT_API #endif -// This is basically a workaround. When using MSVC and marking class as DLL -// export everything gets exported, which is unwanted in most projects. MSVC -// automatically exports typeinfo and vtable if at least one symbol of the -// class is exported. However, GCC has some strange behavior that even if -// one or more symbol is exported it doesn't export typeinfo unless the -// class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). +//! \def ASMJIT_VIRTAPI +//! +//! This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which +//! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class +//! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export +//! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). #if !defined(_WIN32) && defined(__GNUC__) #define ASMJIT_VIRTAPI ASMJIT_API #else @@ -338,11 +300,11 @@ namespace asmjit { // Function attributes. #if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) - #define ASMJIT_INLINE inline __attribute__((__always_inline__)) + #define ASMJIT_FORCE_INLINE inline __attribute__((__always_inline__)) #elif !defined(ASMJIT_BUILD_DEBUG) && defined(_MSC_VER) - #define ASMJIT_INLINE __forceinline + #define ASMJIT_FORCE_INLINE __forceinline #else - #define ASMJIT_INLINE inline + #define ASMJIT_FORCE_INLINE inline #endif #if defined(__GNUC__) @@ -401,6 +363,17 @@ namespace asmjit { #define ASMJIT_MAY_ALIAS #endif +//! \def ASMJIT_MAYBE_UNUSED +//! +//! Expands to `[[maybe_unused]]` if supported or a compiler attribute instead. +#if __cplusplus >= 201703L + #define ASMJIT_MAYBE_UNUSED [[maybe_unused]] +#elif defined(__GNUC__) + #define ASMJIT_MAYBE_UNUSED __attribute__((unused)) +#else + #define ASMJIT_MAYBE_UNUSED +#endif + //! \def ASMJIT_LIKELY(...) //! //! Condition is likely to be taken (mostly error handling and edge cases). @@ -457,49 +430,51 @@ namespace asmjit { #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF #endif -// ============================================================================ -// [asmjit::Build - Globals - Begin-Namespace / End-Namespace] -// ============================================================================ +// Begin-Namespace & End-Namespace Macros +// ====================================== -#if defined(__clang__) +#if defined _DOXYGEN + #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { + #define ASMJIT_END_NAMESPACE } +#elif defined(__clang__) #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ + namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \ _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"") #define ASMJIT_END_NAMESPACE \ _Pragma("clang diagnostic pop") \ - } + }} #elif defined(__GNUC__) && __GNUC__ == 4 #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ + namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") #define ASMJIT_END_NAMESPACE \ _Pragma("GCC diagnostic pop") \ - } + }} #elif defined(__GNUC__) && __GNUC__ >= 8 #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ + namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") #define ASMJIT_END_NAMESPACE \ _Pragma("GCC diagnostic pop") \ - } + }} #elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ + namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ __pragma(warning(push)) \ __pragma(warning(disable: 4127)) /* conditional expression is const */ \ __pragma(warning(disable: 4201)) /* nameless struct/union */ #define ASMJIT_END_NAMESPACE \ __pragma(warning(pop)) \ - } + }} #endif #if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE) - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { - #define ASMJIT_END_NAMESPACE } + #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { + #define ASMJIT_END_NAMESPACE }} #endif #define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ @@ -510,9 +485,8 @@ namespace asmjit { } \ ASMJIT_END_NAMESPACE -// ============================================================================ -// [asmjit::Build - Globals - Utilities] -// ============================================================================ +// C++ Utilities +// ============= #define ASMJIT_NONCOPYABLE(Type) \ Type(const Type& other) = delete; \ @@ -523,11 +497,71 @@ namespace asmjit { Type(const Type& other) = delete; \ Type& operator=(const Type& other) = delete; -// ============================================================================ -// [asmjit::Build - Globals - Cleanup] -// ============================================================================ +//! \def ASMJIT_DEFINE_ENUM_FLAGS(T) +//! +//! Defines bit operations for enumeration flags. +#ifdef _DOXYGEN + #define ASMJIT_DEFINE_ENUM_FLAGS(T) +#else + #define ASMJIT_DEFINE_ENUM_FLAGS(T) \ + static ASMJIT_FORCE_INLINE constexpr T operator~(T a) noexcept { \ + return T(~(std::underlying_type<T>::type)(a)); \ + } \ + \ + static ASMJIT_FORCE_INLINE constexpr T operator|(T a, T b) noexcept { \ + return T((std::underlying_type<T>::type)(a) | \ + (std::underlying_type<T>::type)(b)); \ + } \ + static ASMJIT_FORCE_INLINE constexpr T operator&(T a, T b) noexcept { \ + return T((std::underlying_type<T>::type)(a) & \ + (std::underlying_type<T>::type)(b)); \ + } \ + static ASMJIT_FORCE_INLINE constexpr T operator^(T a, T b) noexcept { \ + return T((std::underlying_type<T>::type)(a) ^ \ + (std::underlying_type<T>::type)(b)); \ + } \ + \ + static ASMJIT_FORCE_INLINE T& operator|=(T& a, T b) noexcept { \ + a = T((std::underlying_type<T>::type)(a) | \ + (std::underlying_type<T>::type)(b)); \ + return a; \ + } \ + static ASMJIT_FORCE_INLINE T& operator&=(T& a, T b) noexcept { \ + a = T((std::underlying_type<T>::type)(a) & \ + (std::underlying_type<T>::type)(b)); \ + return a; \ + } \ + static ASMJIT_FORCE_INLINE T& operator^=(T& a, T b) noexcept { \ + a = T((std::underlying_type<T>::type)(a) ^ \ + (std::underlying_type<T>::type)(b)); \ + return a; \ + } +#endif + +//! \def ASMJIT_DEFINE_ENUM_COMPARE(T) +//! +//! Defines comparison operations for enumeration flags. +#ifdef _DOXYGEN + #define ASMJIT_DEFINE_ENUM_COMPARE(T) +#else + #define ASMJIT_DEFINE_ENUM_COMPARE(T) \ + static ASMJIT_FORCE_INLINE bool operator<(T a, T b) noexcept { \ + return (std::underlying_type<T>::type)(a) < (std::underlying_type<T>::type)(b); \ + } \ + static ASMJIT_FORCE_INLINE bool operator<=(T a, T b) noexcept { \ + return (std::underlying_type<T>::type)(a) <= (std::underlying_type<T>::type)(b); \ + } \ + static ASMJIT_FORCE_INLINE bool operator>(T a, T b) noexcept { \ + return (std::underlying_type<T>::type)(a) > (std::underlying_type<T>::type)(b); \ + } \ + static ASMJIT_FORCE_INLINE bool operator>=(T a, T b) noexcept { \ + return (std::underlying_type<T>::type)(a) >= (std::underlying_type<T>::type)(b); \ + } +#endif + +// Cleanup Api-Config Specific Macros +// ================================== -// Cleanup definitions that are only used within this header file. #undef ASMJIT_CXX_GNU #undef ASMJIT_CXX_MAKE_VER diff --git a/src/asmjit/core/archcommons.h b/src/asmjit/core/archcommons.h index fda2451..88b6069 100644 --- a/src/asmjit/core/archcommons.h +++ b/src/asmjit/core/archcommons.h @@ -1,106 +1,82 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED #define ASMJIT_CORE_ARCHCOMMONS_H_INCLUDED -// This file provides architecture-specific classes that are required in the -// core library. For example Imm operand allows to be created from arm::Shift -// in a const-expr way, so the arm::Shift must be provided. So this header -// file provides everything architecture-specific that is used by the Core API. +// This file provides architecture-specific classes that are required in the core library. For example Imm operand +// allows to be created from arm::Shift in a const-expr way, so the arm::Shift must be provided. So this header file +// provides everything architecture-specific that is used by the Core API. #include "../core/globals.h" -// ============================================================================ -// [asmjit::arm] -// ============================================================================ - ASMJIT_BEGIN_SUB_NAMESPACE(arm) //! \addtogroup asmjit_arm //! \{ +//! Shift operation predicate (ARM) describes either SHIFT or EXTEND operation. +//! +//! \note The constants are AsmJit specific. The first 5 values describe real constants on ARM32 and AArch64 hardware, +//! however, the addition constants that describe extend modes are specific to AsmJit and would be translated to the +//! AArch64 specific constants by the assembler. +enum class ShiftOp { + //! Shift left logical operation (default). + //! + //! Available to all ARM architectures. + kLSL = 0x00u, + + //! Shift right logical operation. + //! + //! Available to all ARM architectures. + kLSR = 0x01u, + + //! Shift right arithmetic operation. + //! + //! Available to all ARM architectures. + kASR = 0x02u, + + //! Rotate right operation. + //! + //! \note Not available in AArch64 mode. + kROR = 0x03u, + + //! Rotate right with carry operation (encoded as `kShiftROR` with zero). + //! + //! \note Not available in AArch64 mode. + kRRX = 0x04u, + + //! Shift left by filling low order bits with ones. + kMSL = 0x05u, + + //! UXTN extend register operation (AArch64 only). + kUXTB = 0x06u, + //! UXTH extend register operation (AArch64 only). + kUXTH = 0x07u, + //! UXTW extend register operation (AArch64 only). + kUXTW = 0x08u, + //! UXTX extend register operation (AArch64 only). + kUXTX = 0x09u, + + //! SXTB extend register operation (AArch64 only). + kSXTB = 0x0Au, + //! SXTH extend register operation (AArch64 only). + kSXTH = 0x0Bu, + //! SXTW extend register operation (AArch64 only). + kSXTW = 0x0Cu, + //! SXTX extend register operation (AArch64 only). + kSXTX = 0x0Du + + // NOTE: 0xE and 0xF are used by memory operand to specify POST|PRE offset mode. +}; + //! Represents ARM immediate shift operation type and value. class Shift { public: - //! Operation predicate (ARM) describes either SHIFT or EXTEND operation. - //! - //! \note The constants are AsmJit specific. The first 5 values describe real - //! constants on ARM32 and AArch64 hardware, however, the addition constants - //! that describe extend modes are specific to AsmJit and would be translated - //! to the AArch64 specific constants by the assembler. - enum Op : uint32_t { - //! Shift left logical operation (default). - //! - //! Available to all ARM architectures. - kOpLSL = 0x00u, - - //! Shift right logical operation. - //! - //! Available to all ARM architectures. - kOpLSR = 0x01u, - - //! Shift right arithmetic operation. - //! - //! Available to all ARM architectures. - kOpASR = 0x02u, - - //! Rotate right operation. - //! - //! \note Not available in AArch64 mode. - kOpROR = 0x03u, - - //! Rotate right with carry operation (encoded as `kShiftROR` with zero). - //! - //! \note Not available in AArch64 mode. - kOpRRX = 0x04u, - - //! Shift left by filling low order bits with ones. - kOpMSL = 0x05u, - - //! UXTN extend register operation (AArch64 only). - kOpUXTB = 0x06u, - //! UXTH extend register operation (AArch64 only). - kOpUXTH = 0x07u, - //! UXTW extend register operation (AArch64 only). - kOpUXTW = 0x08u, - //! UXTX extend register operation (AArch64 only). - kOpUXTX = 0x09u, - - //! SXTB extend register operation (AArch64 only). - kOpSXTB = 0x0Au, - //! SXTH extend register operation (AArch64 only). - kOpSXTH = 0x0Bu, - //! SXTW extend register operation (AArch64 only). - kOpSXTW = 0x0Cu, - //! SXTX extend register operation (AArch64 only). - kOpSXTX = 0x0Du - - // NOTE: 0xE and 0xF are used by memory operand to specify POST|PRE offset mode. - }; - //! Shift operation. - uint32_t _op; + ShiftOp _op; //! Shift Value. uint32_t _value; @@ -111,51 +87,51 @@ public: constexpr Shift(const Shift& other) noexcept = default; //! Constructs Shift from operation `op` and shift `value`. - constexpr Shift(uint32_t op, uint32_t value) noexcept + constexpr Shift(ShiftOp op, uint32_t value) noexcept : _op(op), _value(value) {} //! Returns the shift operation. - constexpr uint32_t op() const noexcept { return _op; } + constexpr ShiftOp op() const noexcept { return _op; } + //! Sets shift operation to `op`. + inline void setOp(ShiftOp op) noexcept { _op = op; } + //! Returns the shift smount. constexpr uint32_t value() const noexcept { return _value; } - - //! Sets shift operation to `op`. - inline void setOp(uint32_t op) noexcept { _op = op; } //! Sets shift amount to `value`. inline void setValue(uint32_t value) noexcept { _value = value; } }; //! Constructs a `LSL #value` shift (logical shift left). -static constexpr Shift lsl(uint32_t value) noexcept { return Shift(Shift::kOpLSL, value); } +static constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); } //! Constructs a `LSR #value` shift (logical shift right). -static constexpr Shift lsr(uint32_t value) noexcept { return Shift(Shift::kOpLSR, value); } +static constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); } //! Constructs a `ASR #value` shift (arithmetic shift right). -static constexpr Shift asr(uint32_t value) noexcept { return Shift(Shift::kOpASR, value); } +static constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); } //! Constructs a `ROR #value` shift (rotate right). -static constexpr Shift ror(uint32_t value) noexcept { return Shift(Shift::kOpROR, value); } +static constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); } //! Constructs a `RRX` shift (rotate with carry by 1). -static constexpr Shift rrx() noexcept { return Shift(Shift::kOpRRX, 0); } +static constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); } //! Constructs a `MSL #value` shift (logical shift left filling ones). -static constexpr Shift msl(uint32_t value) noexcept { return Shift(Shift::kOpMSL, value); } +static constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); } //! Constructs a `UXTB #value` extend and shift (unsigned byte extend). -static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(Shift::kOpUXTB, value); } +static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); } //! Constructs a `UXTH #value` extend and shift (unsigned hword extend). -static constexpr Shift uxth(uint32_t value) noexcept { return Shift(Shift::kOpUXTH, value); } +static constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); } //! Constructs a `UXTW #value` extend and shift (unsigned word extend). -static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(Shift::kOpUXTW, value); } +static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); } //! Constructs a `UXTX #value` extend and shift (unsigned dword extend). -static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(Shift::kOpUXTX, value); } +static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); } //! Constructs a `SXTB #value` extend and shift (signed byte extend). -static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(Shift::kOpSXTB, value); } +static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); } //! Constructs a `SXTH #value` extend and shift (signed hword extend). -static constexpr Shift sxth(uint32_t value) noexcept { return Shift(Shift::kOpSXTH, value); } +static constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); } //! Constructs a `SXTW #value` extend and shift (signed word extend). -static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(Shift::kOpSXTW, value); } +static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); } //! Constructs a `SXTX #value` extend and shift (signed dword extend). -static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(Shift::kOpSXTX, value); } +static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); } //! \} diff --git a/src/asmjit/core/archtraits.cpp b/src/asmjit/core/archtraits.cpp index 6c50bb1..8b79ee2 100644 --- a/src/asmjit/core/archtraits.cpp +++ b/src/asmjit/core/archtraits.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/archtraits.h" @@ -35,10 +17,6 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ArchTraits] -// ============================================================================ - static const constexpr ArchTraits noArchTraits = { // SP/FP/LR/PC. 0xFF, 0xFF, 0xFF, 0xFF, @@ -53,27 +31,38 @@ static const constexpr ArchTraits noArchTraits = { 0, 0, // ISA features [Gp, Vec, Other0, Other1]. - { 0, 0, 0, 0}, + {{ + InstHints::kNoHints, + InstHints::kNoHints, + InstHints::kNoHints, + InstHints::kNoHints + }}, // RegTypeToSignature. - { { 0 } }, + #define V(index) { OperandSignature(0) } + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, + #undef V // RegTypeToTypeId. - { 0 }, + #define V(index) TypeId::kVoid + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, + #undef V // TypeIdToRegType. - { 0 }, + #define V(index) RegType::kNone + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, + #undef V // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities. { - ISAWordNameId::kByte, - ISAWordNameId::kHalf, - ISAWordNameId::kWord, - ISAWordNameId::kQuad + ArchTypeNameId::kByte, + ArchTypeNameId::kHalf, + ArchTypeNameId::kWord, + ArchTypeNameId::kQuad } }; -ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount] = { +ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1] = { // No architecture. noArchTraits, @@ -111,63 +100,60 @@ ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount] = { noArchTraits }; -// ============================================================================ -// [asmjit::ArchUtils] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfoOut) noexcept { +ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegSignature(Arch arch, TypeId typeId, TypeId* typeIdOut, OperandSignature* regSignatureOut) noexcept { const ArchTraits& archTraits = ArchTraits::byArch(arch); + // TODO: Remove this, should never be used like this. // Passed RegType instead of TypeId? - if (typeId <= BaseReg::kTypeMax) - typeId = archTraits.regTypeToTypeId(typeId); + if (uint32_t(typeId) <= uint32_t(RegType::kMaxValue)) + typeId = archTraits.regTypeToTypeId(RegType(uint32_t(typeId))); - if (ASMJIT_UNLIKELY(!Type::isValid(typeId))) + if (ASMJIT_UNLIKELY(!TypeUtils::isValid(typeId))) return DebugUtils::errored(kErrorInvalidTypeId); // First normalize architecture dependent types. - if (Type::isAbstract(typeId)) { + if (TypeUtils::isAbstract(typeId)) { bool is32Bit = Environment::is32Bit(arch); - if (typeId == Type::kIdIntPtr) - typeId = is32Bit ? Type::kIdI32 : Type::kIdI64; + if (typeId == TypeId::kIntPtr) + typeId = is32Bit ? TypeId::kInt32 : TypeId::kInt64; else - typeId = is32Bit ? Type::kIdU32 : Type::kIdU64; + typeId = is32Bit ? TypeId::kUInt32 : TypeId::kUInt64; } // Type size helps to construct all groups of registers. // TypeId is invalid if the size is zero. - uint32_t size = Type::sizeOf(typeId); + uint32_t size = TypeUtils::sizeOf(typeId); if (ASMJIT_UNLIKELY(!size)) return DebugUtils::errored(kErrorInvalidTypeId); - if (ASMJIT_UNLIKELY(typeId == Type::kIdF80)) + if (ASMJIT_UNLIKELY(typeId == TypeId::kFloat80)) return DebugUtils::errored(kErrorInvalidUseOfF80); - uint32_t regType = 0; - if (typeId >= Type::_kIdBaseStart && typeId < Type::_kIdVec32Start) { - regType = archTraits._typeIdToRegType[typeId - Type::_kIdBaseStart]; - if (!regType) { - if (typeId == Type::kIdI64 || typeId == Type::kIdU64) + RegType regType = RegType::kNone; + if (TypeUtils::isBetween(typeId, TypeId::_kBaseStart, TypeId::_kVec32Start)) { + regType = archTraits._typeIdToRegType[uint32_t(typeId) - uint32_t(TypeId::_kBaseStart)]; + if (regType == RegType::kNone) { + if (typeId == TypeId::kInt64 || typeId == TypeId::kUInt64) return DebugUtils::errored(kErrorInvalidUseOfGpq); else return DebugUtils::errored(kErrorInvalidTypeId); } } else { - if (size <= 8 && archTraits._regInfo[BaseReg::kTypeVec64].isValid()) - regType = BaseReg::kTypeVec64; - else if (size <= 16 && archTraits._regInfo[BaseReg::kTypeVec128].isValid()) - regType = BaseReg::kTypeVec128; - else if (size == 32 && archTraits._regInfo[BaseReg::kTypeVec256].isValid()) - regType = BaseReg::kTypeVec256; - else if (archTraits._regInfo[BaseReg::kTypeVec512].isValid()) - regType = BaseReg::kTypeVec512; + if (size <= 8 && archTraits._regSignature[RegType::kVec64].isValid()) + regType = RegType::kVec64; + else if (size <= 16 && archTraits._regSignature[RegType::kVec128].isValid()) + regType = RegType::kVec128; + else if (size == 32 && archTraits._regSignature[RegType::kVec256].isValid()) + regType = RegType::kVec256; + else if (archTraits._regSignature[RegType::kVec512].isValid()) + regType = RegType::kVec512; else return DebugUtils::errored(kErrorInvalidTypeId); } *typeIdOut = typeId; - regInfoOut->reset(archTraits.regTypeToSignature(regType)); + *regSignatureOut = archTraits.regTypeToSignature(regType); return kErrorOk; } diff --git a/src/asmjit/core/archtraits.h b/src/asmjit/core/archtraits.h index 43ef10f..4d05c11 100644 --- a/src/asmjit/core/archtraits.h +++ b/src/asmjit/core/archtraits.h @@ -1,31 +1,13 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ARCHTRAITS_H_INCLUDED #define ASMJIT_CORE_ARCHTRAITS_H_INCLUDED -#include "../core/environment.h" #include "../core/operand.h" +#include "../core/support.h" #include "../core/type.h" ASMJIT_BEGIN_NAMESPACE @@ -33,8 +15,98 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ +//! Instruction set architecture (ISA). +enum class Arch : uint8_t { + //! Unknown or uninitialized ISA. + kUnknown = 0, + + //! 32-bit X86 ISA. + kX86 = 1, + //! 64-bit X86 ISA also known as X64, X86_64, and AMD64. + kX64 = 2, + + //! 32-bit RISC-V ISA. + kRISCV32 = 3, + //! 64-bit RISC-V ISA. + kRISCV64 = 4, + + //! 32-bit ARM ISA (little endian). + kARM = 5, + //! 64-bit ARM ISA in (little endian). + kAArch64 = 6, + //! 32-bit ARM ISA in Thumb mode (little endian). + kThumb = 7, + + // 8 is not used at the moment, even numbers are 64-bit architectures. + + //! 32-bit MIPS ISA in (little endian). + kMIPS32_LE = 9, + //! 64-bit MIPS ISA in (little endian). + kMIPS64_LE = 10, + + //! 32-bit ARM ISA (big endian). + kARM_BE = 11, + //! 64-bit ARM ISA in (big endian). + kAArch64_BE = 12, + //! 32-bit ARM ISA in Thumb mode (big endian). + kThumb_BE = 13, + + // 14 is not used at the moment, even numbers are 64-bit architectures. + + //! 32-bit MIPS ISA in (big endian). + kMIPS32_BE = 15, + //! 64-bit MIPS ISA in (big endian). + kMIPS64_BE = 16, + + //! Maximum value of `Arch`. + kMaxValue = kMIPS64_BE, + + //! Mask used by 32-bit ISAs (odd are 32-bit, even are 64-bit). + k32BitMask = 0x01, + //! First big-endian architecture. + kBigEndian = kARM_BE, + + //! ISA detected at compile-time (ISA of the host). + kHost = +#if defined(_DOXYGEN) + DETECTED_AT_COMPILE_TIME +#else + ASMJIT_ARCH_X86 == 32 ? kX86 : + ASMJIT_ARCH_X86 == 64 ? kX64 : + + ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kARM : + ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kARM_BE : + ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kAArch64 : + ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_BE ? kAArch64_BE : + + ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_LE ? kMIPS32_LE : + ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_BE ? kMIPS32_BE : + ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_LE ? kMIPS64_LE : + ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_BE ? kMIPS64_BE : + + kUnknown +#endif +}; + +//! Sub-architecture. +enum class SubArch : uint8_t { + //! Unknown or uninitialized architecture sub-type. + kUnknown = 0, + + //! Maximum value of `SubArch`. + kMaxValue = kUnknown, + + //! Sub-architecture detected at compile-time (sub-architecture of the host). + kHost = +#if defined(_DOXYGEN) + DETECTED_AT_COMPILE_TIME +#else + kUnknown +#endif +}; + //! Identifier used to represent names of different data types across architectures. -enum class ISAWordNameId : uint8_t { +enum class ArchTypeNameId : uint8_t { //! Describes 'db' (X86/X86_64 convention, always 8-bit quantity). kDB = 0, //! Describes 'dw' (X86/X86_64 convention, always 16-bit word). @@ -64,23 +136,33 @@ enum class ISAWordNameId : uint8_t { //! Describes 'quad' (64-bit word). kQuad, - //! Maximum value. + //! Maximum value of `ArchTypeNameId`. kMaxValue = kQuad }; -// ============================================================================ -// [asmjit::ArchTraits] -// ============================================================================ +//! Instruction feature hints for each register group provided by \ref ArchTraits. +//! +//! Instruction feature hints describe miscellaneous instructions provided by the architecture that can be used by +//! register allocator to make certain things simpler - like register swaps or emitting register push/pop sequences. +//! +//! \remarks Instruction feature hints are only defined for register groups that can be used with \ref +//! asmjit_compiler infrastructure. Register groups that are not managed by Compiler are not provided by +//! \ref ArchTraits and cannot be queried. +enum class InstHints : uint8_t { + //! No feature hints. + kNoHints = 0, + + //! Architecture supports a register swap by using a single instructio. + kRegSwap = 0x01u, + //! Architecture provides push/pop instructions. + kPushPop = 0x02u +}; +ASMJIT_DEFINE_ENUM_FLAGS(InstHints) //! Architecture traits used by Function API and Compiler's register allocator. struct ArchTraits { - //! ISA features for each register group. - enum IsaFeatures : uint32_t { - //! ISA features a register swap by using a single instruction. - kIsaFeatureSwap = 0x01u, - //! ISA features a push/pop like instruction for this register group. - kIsaFeaturePushPop = 0x02u, - }; + //! \name Members + //! \{ //! Stack pointer register id. uint8_t _spRegId; @@ -101,84 +183,69 @@ struct ArchTraits { //! Maximum addressable offset on stack depending on specific instruction. uint32_t _maxStackOffset; - //! Flags for each virtual register group (always covers GP and Vec groups). - uint8_t _isaFlags[BaseReg::kGroupVirt]; + //! Flags for each virtual register group. + Support::Array<InstHints, Globals::kNumVirtGroups> _instHints; - //! Maps register type into a signature, that provides group, size and can - //! be used to construct register operands. - RegInfo _regInfo[BaseReg::kTypeMax + 1]; - //! Maps a register to type-id, see \ref Type::Id. - uint8_t _regTypeToTypeId[BaseReg::kTypeMax + 1]; - //! Maps base TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref Type::Id. - uint8_t _typeIdToRegType[32]; + //! Maps register type into a signature, that provides group, size and can be used to construct register operands. + Support::Array<OperandSignature, uint32_t(RegType::kMaxValue) + 1> _regSignature; + //! Maps a register to type-id, see \ref TypeId. + Support::Array<TypeId, uint32_t(RegType::kMaxValue) + 1> _regTypeToTypeId; + //! Maps scalar TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref TypeId. + Support::Array<RegType, 32> _typeIdToRegType; //! Word name identifiers of 8-bit, 16-bit, 32-biit, and 64-bit quantities that appear in formatted text. - ISAWordNameId _isaWordNameIdTable[4]; + ArchTypeNameId _typeNameIdTable[4]; - //! Resets all members to zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + //! \} //! \name Accessors //! \{ //! Returns stack pointer register id. - inline constexpr uint32_t spRegId() const noexcept { return _spRegId; } + inline uint32_t spRegId() const noexcept { return _spRegId; } //! Returns stack frame register id. - inline constexpr uint32_t fpRegId() const noexcept { return _fpRegId; } + inline uint32_t fpRegId() const noexcept { return _fpRegId; } //! Returns link register id, if the architecture provides it. - inline constexpr uint32_t linkRegId() const noexcept { return _linkRegId; } + inline uint32_t linkRegId() const noexcept { return _linkRegId; } //! Returns instruction pointer register id, if the architecture provides it. - inline constexpr uint32_t ipRegId() const noexcept { return _ipRegId; } + inline uint32_t ipRegId() const noexcept { return _ipRegId; } //! Returns a hardware stack alignment requirement. //! - //! \note This is a hardware constraint. Architectures that don't constrain - //! it would return the lowest alignment (1), however, some architectures may - //! constrain the alignment, for example AArch64 requires 16-byte alignment. - inline constexpr uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; } + //! \note This is a hardware constraint. Architectures that don't constrain it would return the lowest alignment + //! (1), however, some architectures may constrain the alignment, for example AArch64 requires 16-byte alignment. + inline uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; } - //! Tests whether the architecture provides link register, which is used across - //! function calls. If the link register is not provided then a function call - //! pushes the return address on stack (X86/X64). - inline constexpr bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; } + //! Tests whether the architecture provides link register, which is used across function calls. If the link + //! register is not provided then a function call pushes the return address on stack (X86/X64). + inline bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; } //! Returns minimum addressable offset on stack guaranteed for all instructions. - inline constexpr uint32_t minStackOffset() const noexcept { return _minStackOffset; } + inline uint32_t minStackOffset() const noexcept { return _minStackOffset; } //! Returns maximum addressable offset on stack depending on specific instruction. - inline constexpr uint32_t maxStackOffset() const noexcept { return _maxStackOffset; } + inline uint32_t maxStackOffset() const noexcept { return _maxStackOffset; } //! Returns ISA flags of the given register `group`. - inline constexpr uint32_t isaFlags(uint32_t group) const noexcept { return _isaFlags[group]; } + inline InstHints instFeatureHints(RegGroup group) const noexcept { return _instHints[group]; } //! Tests whether the given register `group` has the given `flag` set. - inline constexpr bool hasIsaFlag(uint32_t group, uint32_t flag) const noexcept { return (_isaFlags[group] & flag) != 0; } + inline bool hasInstHint(RegGroup group, InstHints feature) const noexcept { return Support::test(_instHints[group], feature); } //! Tests whether the ISA provides register swap instruction for the given register `group`. - inline constexpr bool hasSwap(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeatureSwap); } + inline bool hasInstRegSwap(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kRegSwap); } //! Tests whether the ISA provides push/pop instructions for the given register `group`. - inline constexpr bool hasPushPop(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeaturePushPop); } + inline bool hasInstPushPop(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kPushPop); } - inline uint32_t hasRegType(uint32_t rType) const noexcept { - return rType <= BaseReg::kTypeMax && _regInfo[rType].signature() != 0; + inline bool hasRegType(RegType type) const noexcept { + return type <= RegType::kMaxValue && _regSignature[type].isValid(); } - inline uint32_t regTypeToSignature(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regInfo[rType].signature(); - } - - inline uint32_t regTypeToGroup(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regInfo[rType].group(); - } - - inline uint32_t regTypeToSize(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regInfo[rType].size(); - } - - inline uint32_t regTypeToTypeId(uint32_t rType) const noexcept { - ASMJIT_ASSERT(rType <= BaseReg::kTypeMax); - return _regTypeToTypeId[rType]; - } + //! Returns an operand signature from the given register `type` of this architecture. + inline OperandSignature regTypeToSignature(RegType type) const noexcept { return _regSignature[type]; } + //! Returns a register from the given register `type` of this architecture. + inline RegGroup regTypeToGroup(RegType type) const noexcept { return _regSignature[type].regGroup(); } + //! Returns a register size the given register `type` of this architecture. + inline uint32_t regTypeToSize(RegType type) const noexcept { return _regSignature[type].size(); } + //! Returns a corresponding `TypeId` from the given register `type` of this architecture. + inline TypeId regTypeToTypeId(RegType type) const noexcept { return _regTypeToTypeId[type]; } //! Returns a table of ISA word names that appear in formatted text. Word names are ISA dependent. //! @@ -187,10 +254,10 @@ struct ArchTraits { //! - [1] 16-bits //! - [2] 32-bits //! - [3] 64-bits - inline const ISAWordNameId* isaWordNameIdTable() const noexcept { return _isaWordNameIdTable; } + inline const ArchTypeNameId* typeNameIdTable() const noexcept { return _typeNameIdTable; } - //! Returns an ISA word name identifier of the given `index`, see \ref isaWordNameIdTable() for more details. - inline ISAWordNameId isaWordNameId(uint32_t index) const noexcept { return _isaWordNameIdTable[index]; } + //! Returns an ISA word name identifier of the given `index`, see \ref typeNameIdTable() for more details. + inline ArchTypeNameId typeNameIdByIndex(uint32_t index) const noexcept { return _typeNameIdTable[index]; } //! \} @@ -198,23 +265,21 @@ struct ArchTraits { //! \{ //! Returns a const reference to `ArchTraits` for the given architecture `arch`. - static inline const ArchTraits& byArch(uint32_t arch) noexcept; + static inline const ArchTraits& byArch(Arch arch) noexcept; //! \} }; -ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount]; - -inline const ArchTraits& ArchTraits::byArch(uint32_t arch) noexcept { return _archTraits[arch & ~Environment::kArchBigEndianMask]; } +ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1]; -// ============================================================================ -// [asmjit::ArchUtils] -// ============================================================================ +//! \cond +inline const ArchTraits& ArchTraits::byArch(Arch arch) noexcept { return _archTraits[uint32_t(arch)]; } +//! \endcond //! Architecture utilities. namespace ArchUtils { -ASMJIT_API Error typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfo) noexcept; +ASMJIT_API Error typeIdToRegSignature(Arch arch, TypeId typeId, TypeId* typeIdOut, OperandSignature* regSignatureOut) noexcept; } // {ArchUtils} diff --git a/src/asmjit/core/assembler.cpp b/src/asmjit/core/assembler.cpp index 6f9fe00..ea223a3 100644 --- a/src/asmjit/core/assembler.cpp +++ b/src/asmjit/core/assembler.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/assembler.h" @@ -32,18 +14,16 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::BaseAssembler - Construction / Destruction] -// ============================================================================ +// BaseAssembler - Construction & Destruction +// ========================================== BaseAssembler::BaseAssembler() noexcept - : BaseEmitter(kTypeAssembler) {} + : BaseEmitter(EmitterType::kAssembler) {} BaseAssembler::~BaseAssembler() noexcept {} -// ============================================================================ -// [asmjit::BaseAssembler - Buffer Management] -// ============================================================================ +// BaseAssembler - Buffer Management +// ================================= Error BaseAssembler::setOffset(size_t offset) { if (ASMJIT_UNLIKELY(!_code)) @@ -57,9 +37,8 @@ Error BaseAssembler::setOffset(size_t offset) { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseAssembler - Section Management] -// ============================================================================ +// BaseAssembler - Section Management +// ================================== static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept { uint8_t* p = section->_buffer._data; @@ -86,9 +65,8 @@ Error BaseAssembler::section(Section* section) { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseAssembler - Label Management] -// ============================================================================ +// BaseAssembler - Label Management +// ================================ Label BaseAssembler::newLabel() { uint32_t labelId = Globals::kInvalidId; @@ -103,7 +81,7 @@ Label BaseAssembler::newLabel() { return Label(labelId); } -Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) { +Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) { uint32_t labelId = Globals::kInvalidId; if (ASMJIT_LIKELY(_code)) { LabelEntry* le; @@ -134,9 +112,8 @@ Error BaseAssembler::bind(const Label& label) { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseAssembler - Embed] -// ============================================================================ +// BaseAssembler - Embed +// ===================== Error BaseAssembler::embed(const void* data, size_t dataSize) { if (ASMJIT_UNLIKELY(!_code)) @@ -154,7 +131,7 @@ Error BaseAssembler::embed(const void* data, size_t dataSize) { #ifndef ASMJIT_NO_LOGGING if (_logger) { StringTmp<512> sb; - Formatter::formatData(sb, _logger->flags(), arch(), Type::kIdU8, data, dataSize, 1); + Formatter::formatData(sb, _logger->flags(), arch(), TypeId::kUInt8, data, dataSize, 1); sb.append('\n'); _logger->log(sb); } @@ -163,17 +140,17 @@ Error BaseAssembler::embed(const void* data, size_t dataSize) { return kErrorOk; } -Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) { - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize()); - uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta); +Error BaseAssembler::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) { + uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize()); + TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta); - if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId))) + if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId))) return reportError(DebugUtils::errored(kErrorInvalidArgument)); if (itemCount == 0 || repeatCount == 0) return kErrorOk; - uint32_t typeSize = Type::sizeOf(finalTypeId); + uint32_t typeSize = TypeUtils::sizeOf(finalTypeId); Support::FastUInt8 of = 0; size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of); @@ -203,16 +180,16 @@ Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t it } #ifndef ASMJIT_NO_LOGGING -static const uint8_t dataTypeIdBySize[9] = { - Type::kIdVoid, // [0] (invalid) - Type::kIdU8, // [1] (uint8_t) - Type::kIdU16, // [2] (uint16_t) - Type::kIdVoid, // [3] (invalid) - Type::kIdU32, // [4] (uint32_t) - Type::kIdVoid, // [5] (invalid) - Type::kIdVoid, // [6] (invalid) - Type::kIdVoid, // [7] (invalid) - Type::kIdU64 // [8] (uint64_t) +static const TypeId dataTypeIdBySize[9] = { + TypeId::kVoid, // [0] (invalid) + TypeId::kUInt8, // [1] (uint8_t) + TypeId::kUInt16, // [2] (uint16_t) + TypeId::kVoid, // [3] (invalid) + TypeId::kUInt32, // [4] (uint32_t) + TypeId::kVoid, // [5] (invalid) + TypeId::kVoid, // [6] (invalid) + TypeId::kVoid, // [7] (invalid) + TypeId::kUInt64 // [8] (uint64_t) }; #endif @@ -223,7 +200,7 @@ Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) { if (ASMJIT_UNLIKELY(!isLabelValid(label))) return reportError(DebugUtils::errored(kErrorInvalidLabel)); - ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment()))); + ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment()))); ASMJIT_PROPAGATE(bind(label)); size_t size = pool.size(); @@ -282,13 +259,13 @@ Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) { sb.append('.'); Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]); sb.append(' '); - Formatter::formatLabel(sb, 0, this, label.id()); + Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id()); sb.append('\n'); _logger->log(sb); } #endif - Error err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs); + Error err = _code->newRelocEntry(&re, RelocType::kRelToAbs); if (ASMJIT_UNLIKELY(err)) return reportError(err); @@ -343,9 +320,9 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size sb.append('.'); Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]); sb.append(" ("); - Formatter::formatLabel(sb, 0, this, label.id()); + Formatter::formatLabel(sb, FormatFlags::kNone, this, label.id()); sb.append(" - "); - Formatter::formatLabel(sb, 0, this, base.id()); + Formatter::formatLabel(sb, FormatFlags::kNone, this, base.id()); sb.append(")\n"); _logger->log(sb); } @@ -358,7 +335,7 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size } else { RelocEntry* re; - Error err = _code->newRelocEntry(&re, RelocEntry::kTypeExpression); + Error err = _code->newRelocEntry(&re, RelocType::kExpression); if (ASMJIT_UNLIKELY(err)) return reportError(err); @@ -367,7 +344,7 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size return reportError(DebugUtils::errored(kErrorOutOfMemory)); exp->reset(); - exp->opType = Expression::kOpSub; + exp->opType = ExpressionOpType::kSub; exp->setValueAsLabel(0, labelEntry); exp->setValueAsLabel(1, baseEntry); @@ -383,19 +360,18 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size return kErrorOk; } -// ============================================================================ -// [asmjit::BaseAssembler - Comment] -// ============================================================================ +// BaseAssembler - Comment +// ======================= Error BaseAssembler::comment(const char* data, size_t size) { - if (!hasEmitterFlag(kFlagLogComments)) { - if (!hasEmitterFlag(kFlagAttached)) + if (!hasEmitterFlag(EmitterFlags::kLogComments)) { + if (!hasEmitterFlag(EmitterFlags::kAttached)) return reportError(DebugUtils::errored(kErrorNotInitialized)); return kErrorOk; } #ifndef ASMJIT_NO_LOGGING - // Logger cannot be NULL if `kFlagLogComments` is set. + // Logger cannot be NULL if `EmitterFlags::kLogComments` is set. ASMJIT_ASSERT(_logger != nullptr); _logger->log(data, size); @@ -407,9 +383,8 @@ Error BaseAssembler::comment(const char* data, size_t size) { #endif } -// ============================================================================ -// [asmjit::BaseAssembler - Events] -// ============================================================================ +// BaseAssembler - Events +// ====================== Error BaseAssembler::onAttach(CodeHolder* code) noexcept { ASMJIT_PROPAGATE(Base::onAttach(code)); diff --git a/src/asmjit/core/assembler.h b/src/asmjit/core/assembler.h index c0da819..7ea2505 100644 --- a/src/asmjit/core/assembler.h +++ b/src/asmjit/core/assembler.h @@ -1,31 +1,12 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ASSEMBLER_H_INCLUDED #define ASMJIT_CORE_ASSEMBLER_H_INCLUDED #include "../core/codeholder.h" -#include "../core/datatypes.h" #include "../core/emitter.h" #include "../core/operand.h" @@ -34,10 +15,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_assembler //! \{ -// ============================================================================ -// [asmjit::BaseAssembler] -// ============================================================================ - //! Base assembler. //! //! This is a base class that provides interface used by architecture specific @@ -112,7 +89,7 @@ public: //! \{ ASMJIT_API Label newLabel() override; - ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override; + ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) override; ASMJIT_API Error bind(const Label& label) override; //! \} @@ -121,7 +98,7 @@ public: //! \{ ASMJIT_API Error embed(const void* data, size_t dataSize) override; - ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) override; + ASMJIT_API Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) override; ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override; ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override; diff --git a/src/asmjit/core/builder.cpp b/src/asmjit/core/builder.cpp index ad89f1d..108a8b0 100644 --- a/src/asmjit/core/builder.cpp +++ b/src/asmjit/core/builder.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_BUILDER @@ -33,9 +15,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::PostponedErrorHandler (Internal)] -// ============================================================================ +// PostponedErrorHandler (Internal) +// ================================ //! Postponed error handler that never throws. Used as a temporal error handler //! to run passes. If error occurs, the caller is notified and will call the @@ -50,9 +31,8 @@ public: StringTmp<128> _message; }; -// ============================================================================ -// [asmjit::BaseBuilder - Utilities] -// ============================================================================ +// BaseBuilder - Utilities +// ======================= static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept { for (Pass* pass : self->_passes) @@ -60,12 +40,11 @@ static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept { self->_passes.reset(); } -// ============================================================================ -// [asmjit::BaseBuilder - Construction / Destruction] -// ============================================================================ +// BaseBuilder - Construction & Destruction +// ======================================== BaseBuilder::BaseBuilder() noexcept - : BaseEmitter(kTypeBuilder), + : BaseEmitter(EmitterType::kBuilder), _codeZone(32768 - Zone::kBlockOverhead), _dataZone(16384 - Zone::kBlockOverhead), _passZone(65536 - Zone::kBlockOverhead), @@ -75,11 +54,10 @@ BaseBuilder::~BaseBuilder() noexcept { BaseBuilder_deletePasses(this); } -// ============================================================================ -// [asmjit::BaseBuilder - Node Management] -// ============================================================================ +// BaseBuilder - Node Management +// ============================= -Error BaseBuilder::_newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount) { +Error BaseBuilder::newInstNode(InstNode** out, InstId instId, InstOptions instOptions, uint32_t opCount) { uint32_t opCapacity = InstNode::capacityOfOpCount(opCount); ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity); @@ -92,28 +70,28 @@ Error BaseBuilder::_newInstNode(InstNode** out, uint32_t instId, uint32_t instOp } -Error BaseBuilder::_newLabelNode(LabelNode** out) { +Error BaseBuilder::newLabelNode(LabelNode** out) { *out = nullptr; ASMJIT_PROPAGATE(_newNodeT<LabelNode>(out)); return registerLabelNode(*out); } -Error BaseBuilder::_newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment) { +Error BaseBuilder::newAlignNode(AlignNode** out, AlignMode alignMode, uint32_t alignment) { *out = nullptr; return _newNodeT<AlignNode>(out, alignMode, alignment); } -Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) { +Error BaseBuilder::newEmbedDataNode(EmbedDataNode** out, TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) { *out = nullptr; - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize()); - uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta); + uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize()); + TypeId finalTypeId = TypeUtils::deabstract(typeId, deabstractDelta); - if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId))) + if (ASMJIT_UNLIKELY(!TypeUtils::isValid(finalTypeId))) return reportError(DebugUtils::errored(kErrorInvalidArgument)); - uint32_t typeSize = Type::sizeOf(finalTypeId); + uint32_t typeSize = TypeUtils::sizeOf(finalTypeId); Support::FastUInt8 of = 0; size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of); @@ -123,7 +101,7 @@ Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const EmbedDataNode* node; ASMJIT_PROPAGATE(_newNodeT<EmbedDataNode>(&node)); - node->_embed._typeId = uint8_t(typeId); + node->_embed._typeId = typeId; node->_embed._typeSize = uint8_t(typeSize); node->_itemCount = itemCount; node->_repeatCount = repeatCount; @@ -143,14 +121,14 @@ Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const return kErrorOk; } -Error BaseBuilder::_newConstPoolNode(ConstPoolNode** out) { +Error BaseBuilder::newConstPoolNode(ConstPoolNode** out) { *out = nullptr; ASMJIT_PROPAGATE(_newNodeT<ConstPoolNode>(out)); return registerLabelNode(*out); } -Error BaseBuilder::_newCommentNode(CommentNode** out, const char* data, size_t size) { +Error BaseBuilder::newCommentNode(CommentNode** out, const char* data, size_t size) { *out = nullptr; if (data) { @@ -198,7 +176,7 @@ BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept { _lastNode = node; } - node->addFlags(BaseNode::kFlagIsActive); + node->addFlags(NodeFlags::kIsActive); if (node->isSection()) _dirtySectionLinks = true; @@ -219,7 +197,7 @@ BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept { node->_prev = prev; node->_next = next; - node->addFlags(BaseNode::kFlagIsActive); + node->addFlags(NodeFlags::kIsActive); if (node->isSection()) _dirtySectionLinks = true; @@ -246,7 +224,7 @@ BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept { node->_prev = prev; node->_next = next; - node->addFlags(BaseNode::kFlagIsActive); + node->addFlags(NodeFlags::kIsActive); if (node->isSection()) _dirtySectionLinks = true; @@ -278,7 +256,7 @@ BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept { node->_prev = nullptr; node->_next = nullptr; - node->clearFlags(BaseNode::kFlagIsActive); + node->clearFlags(NodeFlags::kIsActive); if (node->isSection()) _dirtySectionLinks = true; @@ -319,7 +297,7 @@ void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept { node->_prev = nullptr; node->_next = nullptr; - node->clearFlags(BaseNode::kFlagIsActive); + node->clearFlags(NodeFlags::kIsActive); didRemoveSection |= uint32_t(node->isSection()); if (_cursor == node) @@ -340,9 +318,8 @@ BaseNode* BaseBuilder::setCursor(BaseNode* node) noexcept { return old; } -// ============================================================================ -// [asmjit::BaseBuilder - Section] -// ============================================================================ +// BaseBuilder - Sections +// ====================== Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) { *out = nullptr; @@ -424,9 +401,8 @@ void BaseBuilder::updateSectionLinks() noexcept { _dirtySectionLinks = false; } -// ============================================================================ -// [asmjit::BaseBuilder - Labels] -// ============================================================================ +// BaseBuilder - Labels +// ==================== Error BaseBuilder::labelNodeOf(LabelNode** out, uint32_t labelId) { *out = nullptr; @@ -500,7 +476,7 @@ Label BaseBuilder::newLabel() { return Label(labelId); } -Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) { +Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, LabelType type, uint32_t parentId) { uint32_t labelId = Globals::kInvalidId; LabelEntry* le; @@ -521,9 +497,8 @@ Error BaseBuilder::bind(const Label& label) { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseBuilder - Passes] -// ============================================================================ +// BaseBuilder - Passes +// ==================== ASMJIT_FAVOR_SIZE Pass* BaseBuilder::passByName(const char* name) const noexcept { for (Pass* pass : _passes) @@ -603,21 +578,20 @@ Error BaseBuilder::runPasses() { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseBuilder - Emit] -// ============================================================================ +// BaseBuilder - Emit +// ================== -Error BaseBuilder::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { +Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { uint32_t opCount = EmitterUtils::opCountFromEmitArgs(o0, o1, o2, opExt); - uint32_t options = instOptions() | forcedInstOptions(); + InstOptions options = instOptions() | forcedInstOptions(); - if (options & BaseInst::kOptionReserved) { + if (Support::test(options, InstOptions::kReserved)) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); #ifndef ASMJIT_NO_VALIDATION // Strict validation. - if (hasValidationOption(kValidationOptionIntermediate)) { + if (hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate)) { Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); @@ -631,8 +605,8 @@ Error BaseBuilder::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1 } #endif - // Clear options that should never be part of `InstNode`. - options &= ~BaseInst::kOptionReserved; + // Clear instruction options that should never be part of a regular instruction. + options &= ~InstOptions::kReserved; } uint32_t opCapacity = InstNode::capacityOfOpCount(opCount); @@ -666,42 +640,40 @@ Error BaseBuilder::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1 return kErrorOk; } -// ============================================================================ -// [asmjit::BaseBuilder - Align] -// ============================================================================ +// BaseBuilder - Align +// =================== -Error BaseBuilder::align(uint32_t alignMode, uint32_t alignment) { +Error BaseBuilder::align(AlignMode alignMode, uint32_t alignment) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); AlignNode* node; - ASMJIT_PROPAGATE(_newAlignNode(&node, alignMode, alignment)); + ASMJIT_PROPAGATE(newAlignNode(&node, alignMode, alignment)); addNode(node); return kErrorOk; } -// ============================================================================ -// [asmjit::BaseBuilder - Embed] -// ============================================================================ +// BaseBuilder - Embed +// =================== Error BaseBuilder::embed(const void* data, size_t dataSize) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, data, dataSize)); + ASMJIT_PROPAGATE(newEmbedDataNode(&node, TypeId::kUInt8, data, dataSize)); addNode(node); return kErrorOk; } -Error BaseBuilder::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t itemRepeat) { +Error BaseBuilder::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t itemRepeat) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat)); + ASMJIT_PROPAGATE(newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat)); addNode(node); return kErrorOk; @@ -714,23 +686,22 @@ Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) { if (!isLabelValid(label)) return reportError(DebugUtils::errored(kErrorInvalidLabel)); - ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment()))); + ASMJIT_PROPAGATE(align(AlignMode::kData, uint32_t(pool.alignment()))); ASMJIT_PROPAGATE(bind(label)); EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, nullptr, pool.size())); + ASMJIT_PROPAGATE(newEmbedDataNode(&node, TypeId::kUInt8, nullptr, pool.size())); pool.fill(node->data()); addNode(node); return kErrorOk; } -// EmbedLabel / EmbedLabelDelta -// ---------------------------- +// BaseBuilder - EmbedLabel & EmbedLabelDelta +// ========================================== // -// If dataSize is zero it means that the size is the same as target register -// width, however, if it's provided we really want to validate whether it's -// within the possible range. +// If dataSize is zero it means that the size is the same as target register width, however, +// if it's provided we really want to validate whether it's within the possible range. static inline bool BaseBuilder_checkDataSize(size_t dataSize) noexcept { return !dataSize || (Support::isPowerOf2(dataSize) && dataSize <= 8); @@ -764,24 +735,22 @@ Error BaseBuilder::embedLabelDelta(const Label& label, const Label& base, size_t return kErrorOk; } -// ============================================================================ -// [asmjit::BaseBuilder - Comment] -// ============================================================================ +// BaseBuilder - Comment +// ===================== Error BaseBuilder::comment(const char* data, size_t size) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); CommentNode* node; - ASMJIT_PROPAGATE(_newCommentNode(&node, data, size)); + ASMJIT_PROPAGATE(newCommentNode(&node, data, size)); addNode(node); return kErrorOk; } -// ============================================================================ -// [asmjit::BaseBuilder - Serialize] -// ============================================================================ +// BaseBuilder - SerializeTo +// ========================= Error BaseBuilder::serializeTo(BaseEmitter* dst) { Error err = kErrorOk; @@ -796,7 +765,7 @@ Error BaseBuilder::serializeTo(BaseEmitter* dst) { InstNode* node = node_->as<InstNode>(); // NOTE: Inlined to remove one additional call per instruction. - dst->setInstOptions(node->instOptions()); + dst->setInstOptions(node->options()); dst->setExtraReg(node->extraReg()); const Operand_* op = node->operands(); @@ -862,9 +831,8 @@ Error BaseBuilder::serializeTo(BaseEmitter* dst) { return err; } -// ============================================================================ -// [asmjit::BaseBuilder - Events] -// ============================================================================ +// BaseBuilder - Events +// ==================== Error BaseBuilder::onAttach(CodeHolder* code) noexcept { ASMJIT_PROPAGATE(Base::onAttach(code)); @@ -883,7 +851,7 @@ Error BaseBuilder::onAttach(CodeHolder* code) noexcept { _cursor = initialSection; _firstNode = initialSection; _lastNode = initialSection; - initialSection->setFlags(BaseNode::kFlagIsActive); + initialSection->setFlags(NodeFlags::kIsActive); return kErrorOk; } @@ -898,8 +866,7 @@ Error BaseBuilder::onDetach(CodeHolder* code) noexcept { _dataZone.reset(); _passZone.reset(); - _nodeFlags = 0; - + _nodeFlags = NodeFlags::kNone; _cursor = nullptr; _firstNode = nullptr; _lastNode = nullptr; @@ -907,9 +874,8 @@ Error BaseBuilder::onDetach(CodeHolder* code) noexcept { return Base::onDetach(code); } -// ============================================================================ -// [asmjit::Pass - Construction / Destruction] -// ============================================================================ +// Pass - Construction & Destruction +// ================================= Pass::Pass(const char* name) noexcept : _name(name) {} diff --git a/src/asmjit/core/builder.h b/src/asmjit/core/builder.h index 317bda1..545471d 100644 --- a/src/asmjit/core/builder.h +++ b/src/asmjit/core/builder.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_BUILDER_H_INCLUDED #define ASMJIT_CORE_BUILDER_H_INCLUDED @@ -44,10 +26,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_builder //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class BaseBuilder; class Pass; @@ -63,21 +41,88 @@ class CommentNode; class SentinelNode; class LabelDeltaNode; -// Only used by Compiler infrastructure. -class JumpAnnotation; +//! Type of node used by \ref BaseBuilder and \ref BaseCompiler. +enum class NodeType : uint8_t { + //! Invalid node (internal, don't use). + kNone = 0, + + // [BaseBuilder] + + //! Node is \ref InstNode or \ref InstExNode. + kInst = 1, + //! Node is \ref SectionNode. + kSection = 2, + //! Node is \ref LabelNode. + kLabel = 3, + //! Node is \ref AlignNode. + kAlign = 4, + //! Node is \ref EmbedDataNode. + kEmbedData = 5, + //! Node is \ref EmbedLabelNode. + kEmbedLabel = 6, + //! Node is \ref EmbedLabelDeltaNode. + kEmbedLabelDelta = 7, + //! Node is \ref ConstPoolNode. + kConstPool = 8, + //! Node is \ref CommentNode. + kComment = 9, + //! Node is \ref SentinelNode. + kSentinel = 10, + + // [BaseCompiler] + + //! Node is \ref JumpNode (acts as InstNode). + kJump = 15, + //! Node is \ref FuncNode (acts as LabelNode). + kFunc = 16, + //! Node is \ref FuncRetNode (acts as InstNode). + kFuncRet = 17, + //! Node is \ref InvokeNode (acts as InstNode). + kInvoke = 18, + + // [UserDefined] + + //! First id of a user-defined node. + kUser = 32 +}; -// ============================================================================ -// [asmjit::BaseBuilder] -// ============================================================================ +//! Node flags, specify what the node is and/or does. +enum class NodeFlags : uint8_t { + //! No flags. + kNone = 0, + //! Node is code that can be executed (instruction, label, align, etc...). + kIsCode = 0x01u, + //! Node is data that cannot be executed (data, const-pool, etc...). + kIsData = 0x02u, + //! Node is informative, can be removed and ignored. + kIsInformative = 0x04u, + //! Node can be safely removed if unreachable. + kIsRemovable = 0x08u, + //! Node does nothing when executed (label, align, explicit nop). + kHasNoEffect = 0x10u, + //! Node is an instruction or acts as it. + kActsAsInst = 0x20u, + //! Node is a label or acts as it. + kActsAsLabel = 0x40u, + //! Node is active (part of the code). + kIsActive = 0x80u +}; +ASMJIT_DEFINE_ENUM_FLAGS(NodeFlags) + +//! Type of the sentinel (purery informative purpose). +enum class SentinelType : uint8_t { + //! Type of the sentinel is not known. + kUnknown = 0u, + //! This is a sentinel used at the end of \ref FuncNode. + kFuncEnd = 1u +}; //! Builder interface. //! -//! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler -//! replacement in case pre-processing or post-processing of the generated code -//! is required. The code can be modified during or after code generation. Pre -//! or post processing can be done manually or through a \ref Pass object. \ref -//! BaseBuilder stores the emitted code as a double-linked list of nodes, which -//! allows O(1) insertion and removal during processing. +//! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler replacement in case pre-processing or +//! post-processing of the generated code is required. The code can be modified during or after code generation. +//! Pre processing or post processing can be done manually or through a \ref Pass object. \ref BaseBuilder stores +//! the emitted code as a double-linked list of nodes, which allows O(1) insertion and removal during processing. //! //! Check out architecture specific builders for more details and examples: //! @@ -87,6 +132,9 @@ public: ASMJIT_NONCOPYABLE(BaseBuilder) typedef BaseEmitter Base; + //! \name Members + //! \{ + //! Base zone used to allocate nodes and passes. Zone _codeZone; //! Data zone used to allocate data and names. @@ -111,10 +159,12 @@ public: BaseNode* _lastNode = nullptr; //! Flags assigned to each new node. - uint32_t _nodeFlags = 0; + NodeFlags _nodeFlags = NodeFlags::kNone; //! The sections links are dirty (used internally). bool _dirtySectionLinks = false; + //! \} + //! \name Construction & Destruction //! \{ @@ -133,14 +183,13 @@ public: //! Returns the last node. inline BaseNode* lastNode() const noexcept { return _lastNode; } - //! Allocates and instantiates a new node of type `T` and returns its instance. - //! If the allocation fails `nullptr` is returned. + //! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr` + //! is returned. //! //! The template argument `T` must be a type that is extends \ref BaseNode. //! - //! \remarks The pointer returned (if non-null) is owned by the Builder or - //! Compiler. When the Builder/Compiler is destroyed it destroys all nodes - //! it created so no manual memory management is required. + //! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler + //! is destroyed it destroys all nodes it created so no manual memory management is required. template<typename T, typename... Args> inline Error _newNodeT(T** out, Args&&... args) { *out = _allocator.newT<T>(this, std::forward<Args>(args)...); @@ -150,17 +199,17 @@ public: } //! Creates a new \ref InstNode. - ASMJIT_API Error _newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount); + ASMJIT_API Error newInstNode(InstNode** out, InstId instId, InstOptions instOptions, uint32_t opCount); //! Creates a new \ref LabelNode. - ASMJIT_API Error _newLabelNode(LabelNode** out); + ASMJIT_API Error newLabelNode(LabelNode** out); //! Creates a new \ref AlignNode. - ASMJIT_API Error _newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment); + ASMJIT_API Error newAlignNode(AlignNode** out, AlignMode alignMode, uint32_t alignment); //! Creates a new \ref EmbedDataNode. - ASMJIT_API Error _newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1); + ASMJIT_API Error newEmbedDataNode(EmbedDataNode** out, TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1); //! Creates a new \ref ConstPoolNode. - ASMJIT_API Error _newConstPoolNode(ConstPoolNode** out); + ASMJIT_API Error newConstPoolNode(ConstPoolNode** out); //! Creates a new \ref CommentNode. - ASMJIT_API Error _newCommentNode(CommentNode** out, const char* data, size_t size); + ASMJIT_API Error newCommentNode(CommentNode** out, const char* data, size_t size); //! Adds `node` after the current and sets the current node to the given `node`. ASMJIT_API BaseNode* addNode(BaseNode* node) noexcept; @@ -175,11 +224,9 @@ public: //! Returns the cursor. //! - //! When the Builder/Compiler is created it automatically creates a '.text' - //! \ref SectionNode, which will be the initial one. When instructions are - //! added they are always added after the cursor and the cursor is changed - //! to be that newly added node. Use `setCursor()` to change where new nodes - //! are inserted. + //! When the Builder/Compiler is created it automatically creates a '.text' \ref SectionNode, which will be the + //! initial one. When instructions are added they are always added after the cursor and the cursor is changed + //! to be that newly added node. Use `setCursor()` to change where new nodes are inserted. inline BaseNode* cursor() const noexcept { return _cursor; } @@ -189,8 +236,8 @@ public: //! Sets the current node without returning the previous node. //! - //! Only use this function if you are concerned about performance and want - //! this inlined (for example if you set the cursor in a loop, etc...). + //! Only use this function if you are concerned about performance and want this inlined (for example if you set + //! the cursor in a loop, etc...). inline void _setCursor(BaseNode* node) noexcept { _cursor = node; } @@ -202,8 +249,8 @@ public: //! Returns a vector of SectionNode objects. //! - //! \note If a section of some id is not associated with the Builder/Compiler - //! it would be null, so always check for nulls if you iterate over the vector. + //! \note If a section of some id is not associated with the Builder/Compiler it would be null, so always check + //! for nulls if you iterate over the vector. inline const ZoneVector<SectionNode*>& sectionNodes() const noexcept { return _sectionNodes; } @@ -215,15 +262,14 @@ public: //! Returns or creates a `SectionNode` that matches the given `sectionId`. //! - //! \remarks This function will either get the existing `SectionNode` or create - //! it in case it wasn't created before. You can check whether a section has a - //! registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`. + //! \remarks This function will either get the existing `SectionNode` or create it in case it wasn't created before. + //! You can check whether a section has a registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`. ASMJIT_API Error sectionNodeOf(SectionNode** out, uint32_t sectionId); ASMJIT_API Error section(Section* section) override; - //! Returns whether the section links of active section nodes are dirty. You can - //! update these links by calling `updateSectionLinks()` in such case. + //! Returns whether the section links of active section nodes are dirty. You can update these links by calling + //! `updateSectionLinks()` in such case. inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; } //! Updates links of all active section nodes. @@ -236,8 +282,8 @@ public: //! Returns a vector of \ref LabelNode nodes. //! - //! \note If a label of some id is not associated with the Builder/Compiler - //! it would be null, so always check for nulls if you iterate over the vector. + //! \note If a label of some id is not associated with the Builder/Compiler it would be null, so always check for + //! nulls if you iterate over the vector. inline const ZoneVector<LabelNode*>& labelNodes() const noexcept { return _labelNodes; } //! Tests whether the `LabelNode` of the given `labelId` was registered. @@ -252,9 +298,8 @@ public: //! Gets or creates a \ref LabelNode that matches the given `labelId`. //! - //! \remarks This function will either get the existing `LabelNode` or create - //! it in case it wasn't created before. You can check whether a label has a - //! registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode(). + //! \remarks This function will either get the existing `LabelNode` or create it in case it wasn't created before. + //! You can check whether a label has a registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode(). ASMJIT_API Error labelNodeOf(LabelNode** out, uint32_t labelId); //! \overload @@ -264,13 +309,12 @@ public: //! Registers this \ref LabelNode (internal). //! - //! This function is used internally to register a newly created `LabelNode` - //! with this instance of Builder/Compiler. Use \ref labelNodeOf() functions - //! to get back \ref LabelNode from a label or its identifier. + //! This function is used internally to register a newly created `LabelNode` with this instance of Builder/Compiler. + //! Use \ref labelNodeOf() functions to get back \ref LabelNode from a label or its identifier. ASMJIT_API Error registerLabelNode(LabelNode* node); ASMJIT_API Label newLabel() override; - ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override; + ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) override; ASMJIT_API Error bind(const Label& label) override; //! \} @@ -281,14 +325,13 @@ public: //! Returns a vector of `Pass` instances that will be executed by `runPasses()`. inline const ZoneVector<Pass*>& passes() const noexcept { return _passes; } - //! Allocates and instantiates a new pass of type `T` and returns its instance. - //! If the allocation fails `nullptr` is returned. + //! Allocates and instantiates a new pass of type `T` and returns its instance. If the allocation fails `nullptr` is + //! returned. //! //! The template argument `T` must be a type that is extends \ref Pass. //! - //! \remarks The pointer returned (if non-null) is owned by the Builder or - //! Compiler. When the Builder/Compiler is destroyed it destroys all passes - //! it created so no manual memory management is required. + //! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler is + //! destroyed it destroys all passes it created so no manual memory management is required. template<typename T> inline T* newPassT() noexcept { return _codeZone.newT<T>(); } @@ -319,14 +362,14 @@ public: //! \name Emit //! \{ - ASMJIT_API Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; + ASMJIT_API Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; //! \} //! \name Align //! \{ - ASMJIT_API Error align(uint32_t alignMode, uint32_t alignment) override; + ASMJIT_API Error align(AlignMode alignMode, uint32_t alignment) override; //! \} @@ -334,7 +377,7 @@ public: //! \{ ASMJIT_API Error embed(const void* data, size_t dataSize) override; - ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t count, size_t repeat = 1) override; + ASMJIT_API Error embedDataArray(TypeId typeId, const void* data, size_t count, size_t repeat = 1) override; ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override; ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override; @@ -354,9 +397,8 @@ public: //! Serializes everything the given emitter `dst`. //! - //! Although not explicitly required the emitter will most probably be of - //! Assembler type. The reason is that there is no known use of serializing - //! nodes held by Builder/Compiler into another Builder-like emitter. + //! Although not explicitly required the emitter will most probably be of Assembler type. The reason is that + //! there is no known use of serializing nodes held by Builder/Compiler into another Builder-like emitter. ASMJIT_API Error serializeTo(BaseEmitter* dst); //! \} @@ -368,37 +410,21 @@ public: ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use serializeTo() instead, serialize() is now also an instruction.") - inline Error serialize(BaseEmitter* dst) { - return serializeTo(dst); - } - -#ifndef ASMJIT_NO_LOGGING - ASMJIT_DEPRECATED("Use Formatter::formatNodeList(sb, formatFlags, builder)") - inline Error dump(String& sb, uint32_t formatFlags = 0) const noexcept { - return Formatter::formatNodeList(sb, formatFlags, this); - } -#endif // !ASMJIT_NO_LOGGING -#endif // !ASMJIT_NO_DEPRECATED }; -// ============================================================================ -// [asmjit::BaseNode] -// ============================================================================ - //! Base node. //! -//! Every node represents a building-block used by \ref BaseBuilder. It can -//! be instruction, data, label, comment, directive, or any other high-level -//! representation that can be transformed to the building blocks mentioned. -//! Every class that inherits \ref BaseBuilder can define its own high-level -//! nodes that can be later lowered to basic nodes like instructions. +//! Every node represents a building-block used by \ref BaseBuilder. It can be instruction, data, label, comment, +//! directive, or any other high-level representation that can be transformed to the building blocks mentioned. +//! Every class that inherits \ref BaseBuilder can define its own high-level nodes that can be later lowered to +//! basic nodes like instructions. class BaseNode { public: ASMJIT_NONCOPYABLE(BaseNode) + //! \name Members + //! \{ + union { struct { //! Previous node. @@ -412,22 +438,34 @@ public: //! Data shared between all types of nodes. struct AnyData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; + //! Node type. + NodeType _nodeType; + //! Node flags. + NodeFlags _nodeFlags; //! Not used by BaseNode. uint8_t _reserved0; //! Not used by BaseNode. uint8_t _reserved1; }; + //! Data used by \ref AlignNode. + struct AlignData { + //! Node type. + NodeType _nodeType; + //! Node flags. + NodeFlags _nodeFlags; + //! Align mode. + AlignMode _alignMode; + //! Not used by AlignNode. + uint8_t _reserved; + }; + //! Data used by \ref InstNode. struct InstData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; + //! Node type. + NodeType _nodeType; + //! Node flags. + NodeFlags _nodeFlags; //! Instruction operands count (used). uint8_t _opCount; //! Instruction operands capacity (allocated). @@ -436,24 +474,24 @@ public: //! Data used by \ref EmbedDataNode. struct EmbedData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Type id, see \ref Type::Id. - uint8_t _typeId; + //! Node type. + NodeType _nodeType; + //! Node flags. + NodeFlags _nodeFlags; + //! Type id. + TypeId _typeId; //! Size of `_typeId`. uint8_t _typeSize; }; //! Data used by \ref SentinelNode. struct SentinelData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; + //! Node type. + NodeType _nodeType; + //! Node flags. + NodeFlags _nodeFlags; //! Sentinel type. - uint8_t _sentinelType; + SentinelType _sentinelType; //! Not used by BaseNode. uint8_t _reserved1; }; @@ -462,6 +500,8 @@ public: union { //! Data useful by any node type. AnyData _any; + //! Data specific to \ref AlignNode. + AlignData _alignData; //! Data specific to \ref InstNode. InstData _inst; //! Data specific to \ref EmbedDataNode. @@ -487,84 +527,17 @@ public: //! Inline comment/annotation or nullptr if not used. const char* _inlineComment; - //! Type of `BaseNode`. - enum NodeType : uint32_t { - //! Invalid node (internal, don't use). - kNodeNone = 0, - - // [BaseBuilder] - - //! Node is \ref InstNode or \ref InstExNode. - kNodeInst = 1, - //! Node is \ref SectionNode. - kNodeSection = 2, - //! Node is \ref LabelNode. - kNodeLabel = 3, - //! Node is \ref AlignNode. - kNodeAlign = 4, - //! Node is \ref EmbedDataNode. - kNodeEmbedData = 5, - //! Node is \ref EmbedLabelNode. - kNodeEmbedLabel = 6, - //! Node is \ref EmbedLabelDeltaNode. - kNodeEmbedLabelDelta = 7, - //! Node is \ref ConstPoolNode. - kNodeConstPool = 8, - //! Node is \ref CommentNode. - kNodeComment = 9, - //! Node is \ref SentinelNode. - kNodeSentinel = 10, - - // [BaseCompiler] - - //! Node is \ref JumpNode (acts as InstNode). - kNodeJump = 15, - //! Node is \ref FuncNode (acts as LabelNode). - kNodeFunc = 16, - //! Node is \ref FuncRetNode (acts as InstNode). - kNodeFuncRet = 17, - //! Node is \ref InvokeNode (acts as InstNode). - kNodeInvoke = 18, - - // [UserDefined] - - //! First id of a user-defined node. - kNodeUser = 32, - -#ifndef ASMJIT_NO_DEPRECATED - kNodeFuncCall = kNodeInvoke -#endif // !ASMJIT_NO_DEPRECATED - }; - - //! Node flags, specify what the node is and/or does. - enum Flags : uint32_t { - //! Node is code that can be executed (instruction, label, align, etc...). - kFlagIsCode = 0x01u, - //! Node is data that cannot be executed (data, const-pool, etc...). - kFlagIsData = 0x02u, - //! Node is informative, can be removed and ignored. - kFlagIsInformative = 0x04u, - //! Node can be safely removed if unreachable. - kFlagIsRemovable = 0x08u, - //! Node does nothing when executed (label, align, explicit nop). - kFlagHasNoEffect = 0x10u, - //! Node is an instruction or acts as it. - kFlagActsAsInst = 0x20u, - //! Node is a label or acts as it. - kFlagActsAsLabel = 0x40u, - //! Node is active (part of the code). - kFlagIsActive = 0x80u - }; + //! \} //! \name Construction & Destruction //! \{ //! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes. - ASMJIT_INLINE BaseNode(BaseBuilder* cb, uint32_t type, uint32_t flags = 0) noexcept { + inline BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept { _prev = nullptr; _next = nullptr; - _any._nodeType = uint8_t(type); - _any._nodeFlags = uint8_t(flags | cb->_nodeFlags); + _any._nodeType = nodeType; + _any._nodeFlags = nodeFlags | cb->_nodeFlags; _any._reserved0 = 0; _any._reserved1 = 0; _position = 0; @@ -593,71 +566,65 @@ public: inline BaseNode* next() const noexcept { return _next; } //! Returns the type of the node, see `NodeType`. - inline uint32_t type() const noexcept { return _any._nodeType; } + inline NodeType type() const noexcept { return _any._nodeType; } //! Sets the type of the node, see `NodeType` (internal). //! - //! \remarks You should never set a type of a node to anything else than the - //! initial value. This function is only provided for users that use custom - //! nodes and need to change the type either during construction or later. - inline void setType(uint32_t type) noexcept { _any._nodeType = uint8_t(type); } + //! \remarks You should never set a type of a node to anything else than the initial value. This function is only + //! provided for users that use custom nodes and need to change the type either during construction or later. + inline void setType(NodeType type) noexcept { _any._nodeType = type; } //! Tests whether this node is either `InstNode` or extends it. - inline bool isInst() const noexcept { return hasFlag(kFlagActsAsInst); } + inline bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); } //! Tests whether this node is `SectionNode`. - inline bool isSection() const noexcept { return type() == kNodeSection; } + inline bool isSection() const noexcept { return type() == NodeType::kSection; } //! Tests whether this node is either `LabelNode` or extends it. - inline bool isLabel() const noexcept { return hasFlag(kFlagActsAsLabel); } + inline bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); } //! Tests whether this node is `AlignNode`. - inline bool isAlign() const noexcept { return type() == kNodeAlign; } + inline bool isAlign() const noexcept { return type() == NodeType::kAlign; } //! Tests whether this node is `EmbedDataNode`. - inline bool isEmbedData() const noexcept { return type() == kNodeEmbedData; } + inline bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; } //! Tests whether this node is `EmbedLabelNode`. - inline bool isEmbedLabel() const noexcept { return type() == kNodeEmbedLabel; } + inline bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; } //! Tests whether this node is `EmbedLabelDeltaNode`. - inline bool isEmbedLabelDelta() const noexcept { return type() == kNodeEmbedLabelDelta; } + inline bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; } //! Tests whether this node is `ConstPoolNode`. - inline bool isConstPool() const noexcept { return type() == kNodeConstPool; } + inline bool isConstPool() const noexcept { return type() == NodeType::kConstPool; } //! Tests whether this node is `CommentNode`. - inline bool isComment() const noexcept { return type() == kNodeComment; } + inline bool isComment() const noexcept { return type() == NodeType::kComment; } //! Tests whether this node is `SentinelNode`. - inline bool isSentinel() const noexcept { return type() == kNodeSentinel; } + inline bool isSentinel() const noexcept { return type() == NodeType::kSentinel; } //! Tests whether this node is `FuncNode`. - inline bool isFunc() const noexcept { return type() == kNodeFunc; } + inline bool isFunc() const noexcept { return type() == NodeType::kFunc; } //! Tests whether this node is `FuncRetNode`. - inline bool isFuncRet() const noexcept { return type() == kNodeFuncRet; } + inline bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; } //! Tests whether this node is `InvokeNode`. - inline bool isInvoke() const noexcept { return type() == kNodeInvoke; } + inline bool isInvoke() const noexcept { return type() == NodeType::kInvoke; } -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use isInvoke") - inline bool isFuncCall() const noexcept { return isInvoke(); } -#endif // !ASMJIT_NO_DEPRECATED - - //! Returns the node flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _any._nodeFlags; } + //! Returns the node flags. + inline NodeFlags flags() const noexcept { return _any._nodeFlags; } //! Tests whether the node has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (uint32_t(_any._nodeFlags) & flag) != 0; } + inline bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); } //! Replaces node flags with `flags`. - inline void setFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(flags); } + inline void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; } //! Adds the given `flags` to node flags. - inline void addFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(_any._nodeFlags | flags); } + inline void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; } //! Clears the given `flags` from node flags. - inline void clearFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(_any._nodeFlags & (flags ^ 0xFF)); } + inline void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; } //! Tests whether the node is code that can be executed. - inline bool isCode() const noexcept { return hasFlag(kFlagIsCode); } + inline bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); } //! Tests whether the node is data that cannot be executed. - inline bool isData() const noexcept { return hasFlag(kFlagIsData); } + inline bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); } //! Tests whether the node is informative only (is never encoded like comment, etc...). - inline bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); } + inline bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); } //! Tests whether the node is removable if it's in an unreachable code block. - inline bool isRemovable() const noexcept { return hasFlag(kFlagIsRemovable); } + inline bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); } //! Tests whether the node has no effect when executed (label, .align, nop, ...). - inline bool hasNoEffect() const noexcept { return hasFlag(kFlagHasNoEffect); } + inline bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); } //! Tests whether the node is part of the code. - inline bool isActive() const noexcept { return hasFlag(kFlagIsActive); } + inline bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); } //! Tests whether the node has a position assigned. //! @@ -667,20 +634,18 @@ public: inline uint32_t position() const noexcept { return _position; } //! Sets node position. //! - //! Node position is a 32-bit unsigned integer that is used by Compiler to - //! track where the node is relatively to the start of the function. It doesn't - //! describe a byte position in a binary, instead it's just a pseudo position + //! Node position is a 32-bit unsigned integer that is used by Compiler to track where the node is relatively to + //! the start of the function. It doesn't describe a byte position in a binary, instead it's just a pseudo position //! used by liveness analysis and other tools around Compiler. //! - //! If you don't use Compiler then you may use `position()` and `setPosition()` - //! freely for your own purposes if the 32-bit value limit is okay for you. + //! If you don't use Compiler then you may use `position()` and `setPosition()` freely for your own purposes if + //! the 32-bit value limit is okay for you. inline void setPosition(uint32_t position) noexcept { _position = position; } //! Returns user data casted to `T*`. //! - //! User data is decicated to be used only by AsmJit users and not touched - //! by the library. The data has a pointer size so you can either store a - //! pointer or `intptr_t` value through `setUserDataAsIntPtr()`. + //! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer + //! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`. template<typename T> inline T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); } //! Returns user data casted to `int64_t`. @@ -722,10 +687,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::InstNode] -// ============================================================================ - //! Instruction node. //! //! Wraps an instruction with its options and operands. @@ -733,25 +694,34 @@ class InstNode : public BaseNode { public: ASMJIT_NONCOPYABLE(InstNode) + //! \name Constants + //! \{ + enum : uint32_t { - //! Count of embedded operands per `InstNode` that are always allocated as - //! a part of the instruction. Minimum embedded operands is 4, but in 32-bit - //! more pointers are smaller and we can embed 5. The rest (up to 6 operands) + //! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum + //! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands) //! is always stored in `InstExNode`. kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)) }; + //! \} + + //! \name Members + //! \{ + //! Base instruction data. BaseInst _baseInst; //! First 4 or 5 operands (indexed from 0). Operand_ _opArray[kBaseOpCapacity]; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `InstNode` instance. - ASMJIT_INLINE InstNode(BaseBuilder* cb, uint32_t instId, uint32_t options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept - : BaseNode(cb, kNodeInst, kFlagIsCode | kFlagIsRemovable | kFlagActsAsInst), + inline InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept + : BaseNode(cb, NodeType::kInst, NodeFlags::kIsCode | NodeFlags::kIsRemovable | NodeFlags::kActsAsInst), _baseInst(instId, options) { _inst._opCapacity = uint8_t(opCapacity); _inst._opCount = uint8_t(opCount); @@ -767,25 +737,38 @@ public: //! \} - //! \name Accessors + //! \name Instruction Object //! \{ inline BaseInst& baseInst() noexcept { return _baseInst; } inline const BaseInst& baseInst() const noexcept { return _baseInst; } + //! \} + + //! \name Instruction Id + //! \{ + //! Returns the instruction id, see `BaseInst::Id`. - inline uint32_t id() const noexcept { return _baseInst.id(); } + inline InstId id() const noexcept { return _baseInst.id(); } //! Sets the instruction id to `id`, see `BaseInst::Id`. - inline void setId(uint32_t id) noexcept { _baseInst.setId(id); } + inline void setId(InstId id) noexcept { _baseInst.setId(id); } + + //! \} - //! Returns instruction options. - inline uint32_t instOptions() const noexcept { return _baseInst.options(); } - //! Sets instruction options. - inline void setInstOptions(uint32_t options) noexcept { _baseInst.setOptions(options); } - //! Adds instruction options. - inline void addInstOptions(uint32_t options) noexcept { _baseInst.addOptions(options); } - //! Clears instruction options. - inline void clearInstOptions(uint32_t options) noexcept { _baseInst.clearOptions(options); } + //! \name Instruction Options + //! \{ + + inline InstOptions options() const noexcept { return _baseInst.options(); } + inline bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); } + inline void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); } + inline void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); } + inline void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); } + inline void resetOptions() noexcept { _baseInst.resetOptions(); } + + //! \} + + //! \name Extra Register + //! \{ //! Tests whether the node has an extra register operand. inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); } @@ -800,6 +783,11 @@ public: //! Resets extra register operand. inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); } + //! \} + + //! \name Instruction Operands + //! \{ + //! Returns operand count. inline uint32_t opCount() const noexcept { return _inst._opCount; } //! Returns operand capacity. @@ -848,19 +836,19 @@ public: //! \name Utilities //! \{ - inline bool hasOpType(uint32_t opType) const noexcept { + inline bool hasOpType(OperandType opType) const noexcept { for (uint32_t i = 0, count = opCount(); i < count; i++) if (_opArray[i].opType() == opType) return true; return false; } - inline bool hasRegOp() const noexcept { return hasOpType(Operand::kOpReg); } - inline bool hasMemOp() const noexcept { return hasOpType(Operand::kOpMem); } - inline bool hasImmOp() const noexcept { return hasOpType(Operand::kOpImm); } - inline bool hasLabelOp() const noexcept { return hasOpType(Operand::kOpLabel); } + inline bool hasRegOp() const noexcept { return hasOpType(OperandType::kReg); } + inline bool hasMemOp() const noexcept { return hasOpType(OperandType::kMem); } + inline bool hasImmOp() const noexcept { return hasOpType(OperandType::kImm); } + inline bool hasLabelOp() const noexcept { return hasOpType(OperandType::kLabel); } - inline uint32_t indexOfOpType(uint32_t opType) const noexcept { + inline uint32_t indexOfOpType(OperandType opType) const noexcept { uint32_t i = 0; uint32_t count = opCount(); @@ -873,9 +861,9 @@ public: return i; } - inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(Operand::kOpMem); } - inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(Operand::kOpImm); } - inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(Operand::kOpLabel); } + inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(OperandType::kMem); } + inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(OperandType::kImm); } + inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(OperandType::kLabel); } //! \} @@ -886,7 +874,7 @@ public: inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; } inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; } - ASMJIT_INLINE uint32_t getRewriteIndex(const uint32_t* id) const noexcept { + inline uint32_t getRewriteIndex(const uint32_t* id) const noexcept { const uint32_t* array = _getRewriteArray(); ASMJIT_ASSERT(array <= id); @@ -896,7 +884,7 @@ public: return uint32_t(index); } - ASMJIT_INLINE void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept { + inline void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept { uint32_t* array = _getRewriteArray(); array[index] = id; } @@ -921,58 +909,59 @@ public: //! \} }; -// ============================================================================ -// [asmjit::InstExNode] -// ============================================================================ - //! Instruction node with maximum number of operands. //! -//! This node is created automatically by Builder/Compiler in case that the -//! required number of operands exceeds the default capacity of `InstNode`. +//! This node is created automatically by Builder/Compiler in case that the required number of operands exceeds +//! the default capacity of `InstNode`. class InstExNode : public InstNode { public: ASMJIT_NONCOPYABLE(InstExNode) + //! \name Members + //! \{ + //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands. Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity]; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `InstExNode` instance. - inline InstExNode(BaseBuilder* cb, uint32_t instId, uint32_t options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept + inline InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept : InstNode(cb, instId, options, opCapacity) {} //! \} }; -// ============================================================================ -// [asmjit::SectionNode] -// ============================================================================ - //! Section node. class SectionNode : public BaseNode { public: ASMJIT_NONCOPYABLE(SectionNode) + //! \name Members + //! \{ + //! Section id. uint32_t _id; //! Next section node that follows this section. //! - //! This link is only valid when the section is active (is part of the code) - //! and when `Builder::hasDirtySectionLinks()` returns `false`. If you intend - //! to use this field you should always call `Builder::updateSectionLinks()` - //! before you do so. + //! This link is only valid when the section is active (is part of the code) and when `Builder::hasDirtySectionLinks()` + //! returns `false`. If you intend to use this field you should always call `Builder::updateSectionLinks()` before you + //! do so. SectionNode* _nextSection; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `SectionNode` instance. - inline SectionNode(BaseBuilder* cb, uint32_t id = 0) noexcept - : BaseNode(cb, kNodeSection, kFlagHasNoEffect), - _id(id), + inline SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept + : BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect), + _id(secionId), _nextSection(nullptr) {} //! \} @@ -986,24 +975,25 @@ public: //! \} }; -// ============================================================================ -// [asmjit::LabelNode] -// ============================================================================ - //! Label node. class LabelNode : public BaseNode { public: ASMJIT_NONCOPYABLE(LabelNode) + //! \name Members + //! \{ + //! Label identifier. uint32_t _labelId; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `LabelNode` instance. inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept - : BaseNode(cb, kNodeLabel, kFlagHasNoEffect | kFlagActsAsLabel), + : BaseNode(cb, NodeType::kLabel, NodeFlags::kHasNoEffect | NodeFlags::kActsAsLabel), _labelId(labelId) {} //! \} @@ -1017,17 +1007,8 @@ public: inline uint32_t labelId() const noexcept { return _labelId; } //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } -#endif // !ASMJIT_NO_DEPRECATED }; -// ============================================================================ -// [asmjit::AlignNode] -// ============================================================================ - //! Align directive (BaseBuilder). //! //! Wraps `.align` directive. @@ -1035,19 +1016,24 @@ class AlignNode : public BaseNode { public: ASMJIT_NONCOPYABLE(AlignNode) - //! Align mode, see `AlignMode`. - uint32_t _alignMode; + //! \name Members + //! \{ + //! Alignment (in bytes). uint32_t _alignment; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `AlignNode` instance. - inline AlignNode(BaseBuilder* cb, uint32_t alignMode, uint32_t alignment) noexcept - : BaseNode(cb, kNodeAlign, kFlagIsCode | kFlagHasNoEffect), - _alignMode(alignMode), - _alignment(alignment) {} + inline AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept + : BaseNode(cb, NodeType::kAlign, NodeFlags::kIsCode | NodeFlags::kHasNoEffect) { + + _alignData._alignMode = alignMode; + _alignment = alignment; + } //! \} @@ -1055,9 +1041,9 @@ public: //! \{ //! Returns align mode. - inline uint32_t alignMode() const noexcept { return _alignMode; } + inline AlignMode alignMode() const noexcept { return _alignData._alignMode; } //! Sets align mode to `alignMode`. - inline void setAlignMode(uint32_t alignMode) noexcept { _alignMode = alignMode; } + inline void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; } //! Returns align offset in bytes. inline uint32_t alignment() const noexcept { return _alignment; } @@ -1067,22 +1053,22 @@ public: //! \} }; -// ============================================================================ -// [asmjit::EmbedDataNode] -// ============================================================================ - //! Embed data node. //! -//! Wraps `.data` directive. The node contains data that will be placed at the -//! node's position in the assembler stream. The data is considered to be RAW; -//! no analysis nor byte-order conversion is performed on RAW data. +//! Wraps `.data` directive. The node contains data that will be placed at the node's position in the assembler +//! stream. The data is considered to be RAW; no analysis nor byte-order conversion is performed on RAW data. class EmbedDataNode : public BaseNode { public: ASMJIT_NONCOPYABLE(EmbedDataNode) + //! \cond INTERNAL enum : uint32_t { kInlineBufferSize = 128 - (sizeof(BaseNode) + sizeof(size_t) * 2) }; + //! \endcond + + //! \name Members + //! \{ size_t _itemCount; size_t _repeatCount; @@ -1092,15 +1078,17 @@ public: uint8_t _inlineData[kInlineBufferSize]; }; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `EmbedDataNode` instance. inline EmbedDataNode(BaseBuilder* cb) noexcept - : BaseNode(cb, kNodeEmbedData, kFlagIsData), + : BaseNode(cb, NodeType::kEmbedData, NodeFlags::kIsData), _itemCount(0), _repeatCount(0) { - _embed._typeId = uint8_t(Type::kIdU8), + _embed._typeId = TypeId::kUInt8; _embed._typeSize = uint8_t(1); memset(_inlineData, 0, kInlineBufferSize); } @@ -1110,8 +1098,8 @@ public: //! \name Accessors //! \{ - //! Returns \ref Type::Id of the data. - inline uint32_t typeId() const noexcept { return _embed._typeId; } + //! Returns data type as \ref TypeId. + inline TypeId typeId() const noexcept { return _embed._typeId; } //! Returns the size of a single data element. inline uint32_t typeSize() const noexcept { return _embed._typeSize; } @@ -1140,24 +1128,25 @@ public: //! \} }; -// ============================================================================ -// [asmjit::EmbedLabelNode] -// ============================================================================ - //! Label data node. class EmbedLabelNode : public BaseNode { public: ASMJIT_NONCOPYABLE(EmbedLabelNode) + //! \name Members + //! \{ + uint32_t _labelId; uint32_t _dataSize; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `EmbedLabelNode` instance. inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept - : BaseNode(cb, kNodeEmbedLabel, kFlagIsData), + : BaseNode(cb, NodeType::kEmbedLabel, NodeFlags::kIsData), _labelId(labelId), _dataSize(dataSize) {} @@ -1182,32 +1171,28 @@ public: inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } -#endif // !ASMJIT_NO_DEPRECATED }; -// ============================================================================ -// [asmjit::EmbedLabelDeltaNode] -// ============================================================================ - //! Label data node. class EmbedLabelDeltaNode : public BaseNode { public: ASMJIT_NONCOPYABLE(EmbedLabelDeltaNode) + //! \name Members + //! \{ + uint32_t _labelId; uint32_t _baseLabelId; uint32_t _dataSize; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `EmbedLabelDeltaNode` instance. inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept - : BaseNode(cb, kNodeEmbedLabelDelta, kFlagIsData), + : BaseNode(cb, NodeType::kEmbedLabelDelta, NodeFlags::kIsData), _labelId(labelId), _baseLabelId(baseLabelId), _dataSize(dataSize) {} @@ -1243,33 +1228,20 @@ public: inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } - - ASMJIT_DEPRECATED("Use setLabelId() instead") - inline void setId(uint32_t id) noexcept { setLabelId(id); } - - ASMJIT_DEPRECATED("Use baseLabelId() instead") - inline uint32_t baseId() const noexcept { return baseLabelId(); } - - ASMJIT_DEPRECATED("Use setBaseLabelId() instead") - inline void setBaseId(uint32_t id) noexcept { setBaseLabelId(id); } -#endif // !ASMJIT_NO_DEPRECATED }; -// ============================================================================ -// [asmjit::ConstPoolNode] -// ============================================================================ - //! A node that wraps `ConstPool`. class ConstPoolNode : public LabelNode { public: ASMJIT_NONCOPYABLE(ConstPoolNode) + //! \name Members + //! \{ + ConstPool _constPool; + //! \} + //! \name Construction & Destruction //! \{ @@ -1278,9 +1250,9 @@ public: : LabelNode(cb, id), _constPool(&cb->_codeZone) { - setType(kNodeConstPool); - addFlags(kFlagIsData); - clearFlags(kFlagIsCode | kFlagHasNoEffect); + setType(NodeType::kConstPool); + addFlags(NodeFlags::kIsData); + clearFlags(NodeFlags::kIsCode | NodeFlags::kHasNoEffect); } //! \} @@ -1313,10 +1285,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::CommentNode] -// ============================================================================ - //! Comment node. class CommentNode : public BaseNode { public: @@ -1327,41 +1295,29 @@ public: //! Creates a new `CommentNode` instance. inline CommentNode(BaseBuilder* cb, const char* comment) noexcept - : BaseNode(cb, kNodeComment, kFlagIsInformative | kFlagHasNoEffect | kFlagIsRemovable) { + : BaseNode(cb, NodeType::kComment, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect | NodeFlags::kIsRemovable) { _inlineComment = comment; } //! \} }; -// ============================================================================ -// [asmjit::SentinelNode] -// ============================================================================ - //! Sentinel node. //! -//! Sentinel is a marker that is completely ignored by the code builder. It's -//! used to remember a position in a code as it never gets removed by any pass. +//! Sentinel is a marker that is completely ignored by the code builder. It's used to remember a position in a code +//! as it never gets removed by any pass. class SentinelNode : public BaseNode { public: ASMJIT_NONCOPYABLE(SentinelNode) - //! Type of the sentinel (purery informative purpose). - enum SentinelType : uint32_t { - //! Type of the sentinel is not known. - kSentinelUnknown = 0u, - //! This is a sentinel used at the end of \ref FuncNode. - kSentinelFuncEnd = 1u - }; - //! \name Construction & Destruction //! \{ //! Creates a new `SentinelNode` instance. - inline SentinelNode(BaseBuilder* cb, uint32_t sentinelType = kSentinelUnknown) noexcept - : BaseNode(cb, kNodeSentinel, kFlagIsInformative | kFlagHasNoEffect) { + inline SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept + : BaseNode(cb, NodeType::kSentinel, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect) { - _sentinel._sentinelType = uint8_t(sentinelType); + _sentinel._sentinelType = sentinelType; } //! \} @@ -1370,33 +1326,34 @@ public: //! \{ //! Returns the type of the sentinel. - inline uint32_t sentinelType() const noexcept { + inline SentinelType sentinelType() const noexcept { return _sentinel._sentinelType; } //! Sets the type of the sentinel. - inline void setSentinelType(uint32_t type) noexcept { - _sentinel._sentinelType = uint8_t(type); + inline void setSentinelType(SentinelType type) noexcept { + _sentinel._sentinelType = type; } //! \} }; -// ============================================================================ -// [asmjit::Pass] -// ============================================================================ - //! Pass can be used to implement code transformations, analysis, and lowering. class ASMJIT_VIRTAPI Pass { public: ASMJIT_BASE_CLASS(Pass) ASMJIT_NONCOPYABLE(Pass) + //! \name Members + //! \{ + //! BaseBuilder this pass is assigned to. BaseBuilder* _cb = nullptr; //! Name of the pass. const char* _name = nullptr; + //! \} + //! \name Construction & Destruction //! \{ @@ -1420,8 +1377,8 @@ public: //! Processes the code stored in Builder or Compiler. //! - //! This is the only function that is called by the `BaseBuilder` to process - //! the code. It passes `zone`, which will be reset after the `run()` finishes. + //! This is the only function that is called by the `BaseBuilder` to process the code. It passes `zone`, + //! which will be reset after the `run()` finishes. virtual Error run(Zone* zone, Logger* logger) = 0; //! \} diff --git a/src/asmjit/core/codebuffer.h b/src/asmjit/core/codebuffer.h index 76c86b1..4946e7a 100644 --- a/src/asmjit/core/codebuffer.h +++ b/src/asmjit/core/codebuffer.h @@ -1,42 +1,35 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_CODEBUFFER_H_INCLUDED #define ASMJIT_CORE_CODEBUFFER_H_INCLUDED #include "../core/globals.h" +#include "../core/support.h" ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::CodeBuffer] -// ============================================================================ +//! Flags used by \ref CodeBuffer. +enum class CodeBufferFlags : uint32_t { + //! No flags. + kNone = 0, + //! Buffer is external (not allocated by asmjit). + kIsExternal = 0x00000001u, + //! Buffer is fixed (cannot be reallocated). + kIsFixed = 0x00000002u +}; +ASMJIT_DEFINE_ENUM_FLAGS(CodeBufferFlags) //! Code or data buffer. struct CodeBuffer { + //! \name Members + //! \{ + //! The content of the buffer (data). uint8_t* _data; //! Number of bytes of `data` used. @@ -44,15 +37,9 @@ struct CodeBuffer { //! Buffer capacity (in bytes). size_t _capacity; //! Buffer flags. - uint32_t _flags; + CodeBufferFlags _flags; - //! Code buffer flags. - enum Flags : uint32_t { - //! Buffer is external (not allocated by asmjit). - kFlagIsExternal = 0x00000001u, - //! Buffer is fixed (cannot be reallocated). - kFlagIsFixed = 0x00000002u - }; + //! \} //! \name Overloaded Operators //! \{ @@ -73,20 +60,20 @@ struct CodeBuffer { //! \name Accessors //! \{ - //! Returns code buffer flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } + //! Returns code buffer flags. + inline CodeBufferFlags flags() const noexcept { return _flags; } //! Tests whether the code buffer has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } + inline bool hasFlag(CodeBufferFlags flag) const noexcept { return Support::test(_flags, flag); } //! Tests whether this code buffer has a fixed size. //! //! Fixed size means that the code buffer is fixed and cannot grow. - inline bool isFixed() const noexcept { return hasFlag(kFlagIsFixed); } + inline bool isFixed() const noexcept { return hasFlag(CodeBufferFlags::kIsFixed); } //! Tests whether the data in this code buffer is external. //! //! External data can only be provided by users, it's never used by AsmJit. - inline bool isExternal() const noexcept { return hasFlag(kFlagIsExternal); } + inline bool isExternal() const noexcept { return hasFlag(CodeBufferFlags::kIsExternal); } //! Tests whether the data in this code buffer is allocated (non-null). inline bool isAllocated() const noexcept { return _data != nullptr; } diff --git a/src/asmjit/core/codeholder.cpp b/src/asmjit/core/codeholder.cpp index 3c4154e..f446801 100644 --- a/src/asmjit/core/codeholder.cpp +++ b/src/asmjit/core/codeholder.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/assembler.h" @@ -32,9 +14,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [Globals] -// ============================================================================ +// Globals +// ======= static const char CodeHolder_addrTabName[] = ".addrtab"; @@ -43,31 +24,30 @@ static inline uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcep return (m << 6) | (o << 3) | rm; } -// ============================================================================ -// [asmjit::LabelLinkIterator] -// ============================================================================ +// LabelLinkIterator +// ================= class LabelLinkIterator { public: - ASMJIT_INLINE LabelLinkIterator(LabelEntry* le) noexcept { reset(le); } + inline LabelLinkIterator(LabelEntry* le) noexcept { reset(le); } - ASMJIT_INLINE explicit operator bool() const noexcept { return isValid(); } - ASMJIT_INLINE bool isValid() const noexcept { return _link != nullptr; } + inline explicit operator bool() const noexcept { return isValid(); } + inline bool isValid() const noexcept { return _link != nullptr; } - ASMJIT_INLINE LabelLink* link() const noexcept { return _link; } - ASMJIT_INLINE LabelLink* operator->() const noexcept { return _link; } + inline LabelLink* link() const noexcept { return _link; } + inline LabelLink* operator->() const noexcept { return _link; } - ASMJIT_INLINE void reset(LabelEntry* le) noexcept { + inline void reset(LabelEntry* le) noexcept { _pPrev = &le->_links; _link = *_pPrev; } - ASMJIT_INLINE void next() noexcept { + inline void next() noexcept { _pPrev = &_link->next; _link = *_pPrev; } - ASMJIT_INLINE void resolveAndNext(CodeHolder* code) noexcept { + inline void resolveAndNext(CodeHolder* code) noexcept { LabelLink* linkToDelete = _link; _link = _link->next; @@ -81,11 +61,10 @@ public: LabelLink* _link; }; -// ============================================================================ -// [asmjit::CodeHolder - Utilities] -// ============================================================================ +// CodeHolder - Utilities +// ====================== -static void CodeHolder_resetInternal(CodeHolder* self, uint32_t resetPolicy) noexcept { +static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy) noexcept { uint32_t i; const ZoneVector<BaseEmitter*>& emitters = self->emitters(); @@ -134,27 +113,25 @@ static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept { } } -// ============================================================================ -// [asmjit::CodeHolder - Construction / Destruction] -// ============================================================================ +// CodeHolder - Construction & Destruction +// ======================================= -CodeHolder::CodeHolder() noexcept +CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept : _environment(), _baseAddress(Globals::kNoBaseAddress), _logger(nullptr), _errorHandler(nullptr), - _zone(16384 - Zone::kBlockOverhead), + _zone(16384 - Zone::kBlockOverhead, 1, temporary), _allocator(&_zone), _unresolvedLinkCount(0), _addressTableSection(nullptr) {} CodeHolder::~CodeHolder() noexcept { - CodeHolder_resetInternal(this, Globals::kResetHard); + CodeHolder_resetInternal(this, ResetPolicy::kHard); } -// ============================================================================ -// [asmjit::CodeHolder - Init / Reset] -// ============================================================================ +// CodeHolder - Init & Reset +// ========================= inline void CodeHolder_setSectionDefaultName( Section* section, @@ -179,7 +156,7 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe if (err == kErrorOk) { Section* section = _allocator.allocZeroedT<Section>(); if (ASMJIT_LIKELY(section)) { - section->_flags = Section::kFlagExec | Section::kFlagConst; + section->_flags = SectionFlags::kExecutable | SectionFlags::kReadOnly; CodeHolder_setSectionDefaultName(section, '.', 't', 'e', 'x', 't'); _sections.appendUnsafe(section); _sectionsByOrder.appendUnsafe(section); @@ -200,13 +177,12 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe } } -void CodeHolder::reset(uint32_t resetPolicy) noexcept { +void CodeHolder::reset(ResetPolicy resetPolicy) noexcept { CodeHolder_resetInternal(this, resetPolicy); } -// ============================================================================ -// [asmjit::CodeHolder - Attach / Detach] -// ============================================================================ +// CodeHolder - Attach / Detach +// ============================ Error CodeHolder::attach(BaseEmitter* emitter) noexcept { // Catch a possible misuse of the API. @@ -214,8 +190,8 @@ Error CodeHolder::attach(BaseEmitter* emitter) noexcept { return DebugUtils::errored(kErrorInvalidArgument); // Invalid emitter, this should not be possible. - uint32_t type = emitter->emitterType(); - if (ASMJIT_UNLIKELY(type == BaseEmitter::kTypeNone || type >= BaseEmitter::kTypeCount)) + EmitterType type = emitter->emitterType(); + if (ASMJIT_UNLIKELY(type == EmitterType::kNone || uint32_t(type) > uint32_t(EmitterType::kMaxValue))) return DebugUtils::errored(kErrorInvalidState); // This is suspicious, but don't fail if `emitter` is already attached @@ -261,9 +237,8 @@ Error CodeHolder::detach(BaseEmitter* emitter) noexcept { return err; } -// ============================================================================ -// [asmjit::CodeHolder - Logging] -// ============================================================================ +// CodeHolder - Logging +// ==================== void CodeHolder::setLogger(Logger* logger) noexcept { #ifndef ASMJIT_NO_LOGGING @@ -274,18 +249,16 @@ void CodeHolder::setLogger(Logger* logger) noexcept { #endif } -// ============================================================================ -// [asmjit::CodeHolder - Error Handling] -// ============================================================================ +// CodeHolder - Error Handling +// =========================== void CodeHolder::setErrorHandler(ErrorHandler* errorHandler) noexcept { _errorHandler = errorHandler; CodeHolder_onSettingsUpdated(this); } -// ============================================================================ -// [asmjit::CodeHolder - Code Buffer] -// ============================================================================ +// CodeHolder - Code Buffer +// ======================== static Error CodeHolder_reserveInternal(CodeHolder* self, CodeBuffer* cb, size_t n) noexcept { uint8_t* oldData = cb->_data; @@ -368,11 +341,10 @@ Error CodeHolder::reserveBuffer(CodeBuffer* cb, size_t n) noexcept { return CodeHolder_reserveInternal(this, cb, n); } -// ============================================================================ -// [asmjit::CodeHolder - Sections] -// ============================================================================ +// CodeHolder - Sections +// ===================== -Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, uint32_t flags, uint32_t alignment, int32_t order) noexcept { +Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, SectionFlags flags, uint32_t alignment, int32_t order) noexcept { *sectionOut = nullptr; if (nameSize == SIZE_MAX) @@ -435,7 +407,12 @@ Section* CodeHolder::ensureAddressTableSection() noexcept { if (_addressTableSection) return _addressTableSection; - newSection(&_addressTableSection, CodeHolder_addrTabName, sizeof(CodeHolder_addrTabName) - 1, 0, _environment.registerSize(), std::numeric_limits<int32_t>::max()); + newSection(&_addressTableSection, + CodeHolder_addrTabName, + sizeof(CodeHolder_addrTabName) - 1, + SectionFlags::kNone, + _environment.registerSize(), + std::numeric_limits<int32_t>::max()); return _addressTableSection; } @@ -458,9 +435,8 @@ Error CodeHolder::addAddressToAddressTable(uint64_t address) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::CodeHolder - Labels / Symbols] -// ============================================================================ +// CodeHolder - Labels & Symbols +// ============================= //! Only used to lookup a label from `_namedLabels`. class LabelByName { @@ -547,32 +523,66 @@ Error CodeHolder::newLabelEntry(LabelEntry** entryOut) noexcept { return kErrorOk; } -Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId) noexcept { +Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, LabelType type, uint32_t parentId) noexcept { *entryOut = nullptr; uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize); - if (ASMJIT_UNLIKELY(nameSize == 0)) - return DebugUtils::errored(kErrorInvalidLabelName); + if (ASMJIT_UNLIKELY(nameSize == 0)) { + if (type == LabelType::kAnonymous) + return newLabelEntry(entryOut); + else + return DebugUtils::errored(kErrorInvalidLabelName); + } if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxLabelNameSize)) return DebugUtils::errored(kErrorLabelNameTooLong); switch (type) { - case Label::kTypeLocal: + case LabelType::kAnonymous: { + // Anonymous labels cannot have a parent (or more specifically, parent is useless here). + if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId)) + return DebugUtils::errored(kErrorInvalidParentLabel); + + uint32_t labelId = _labelEntries.size(); + if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId)) + return DebugUtils::errored(kErrorTooManyLabels); + + ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator)); + LabelEntry* le = _allocator.allocZeroedT<LabelEntry>(); + + if (ASMJIT_UNLIKELY(!le)) + return DebugUtils::errored(kErrorOutOfMemory); + + // NOTE: This LabelEntry has a name, but we leave its hashCode as zero as it's anonymous. + le->_setId(labelId); + le->_parentId = Globals::kInvalidId; + le->_offset = 0; + ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize)); + + _labelEntries.appendUnsafe(le); + + *entryOut = le; + return kErrorOk; + } + + case LabelType::kLocal: { if (ASMJIT_UNLIKELY(parentId >= _labelEntries.size())) return DebugUtils::errored(kErrorInvalidParentLabel); hashCode ^= parentId; break; + } - case Label::kTypeGlobal: - case Label::kTypeExternal: + case LabelType::kGlobal: + case LabelType::kExternal: { if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId)) - return DebugUtils::errored(kErrorNonLocalLabelCannotHaveParent); + return DebugUtils::errored(kErrorInvalidParentLabel); break; + } - default: + default: { return DebugUtils::errored(kErrorInvalidArgument); + } } // Don't allow to insert duplicates. Local labels allow duplicates that have @@ -596,7 +606,7 @@ Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, si le->_hashCode = hashCode; le->_setId(labelId); - le->_type = uint8_t(type); + le->_type = type; le->_parentId = parentId; le->_offset = 0; ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize)); @@ -733,11 +743,10 @@ ASMJIT_API Error CodeHolder::bindLabel(const Label& label, uint32_t toSectionId, return err; } -// ============================================================================ -// [asmjit::BaseEmitter - Relocations] -// ============================================================================ +// CodeHolder - Relocations +// ======================== -Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType) noexcept { +Error CodeHolder::newRelocEntry(RelocEntry** dst, RelocType relocType) noexcept { ASMJIT_PROPAGATE(_relocations.willGrow(&_allocator)); uint32_t relocId = _relocations.size(); @@ -749,7 +758,7 @@ Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType) noexcept { return DebugUtils::errored(kErrorOutOfMemory); re->_id = relocId; - re->_relocType = uint8_t(relocType); + re->_relocType = relocType; re->_sourceSectionId = Globals::kInvalidId; re->_targetSectionId = Globals::kInvalidId; _relocations.appendUnsafe(re); @@ -758,26 +767,25 @@ Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseEmitter - Expression Evaluation] -// ============================================================================ +// CodeHolder - Expression Evaluation +// ================================== static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, uint64_t* out) noexcept { uint64_t value[2]; for (size_t i = 0; i < 2; i++) { uint64_t v; switch (exp->valueType[i]) { - case Expression::kValueNone: { + case ExpressionValueType::kNone: { v = 0; break; } - case Expression::kValueConstant: { + case ExpressionValueType::kConstant: { v = exp->value[i].constant; break; } - case Expression::kValueLabel: { + case ExpressionValueType::kLabel: { LabelEntry* le = exp->value[i].label; if (!le->isBound()) return DebugUtils::errored(kErrorExpressionLabelNotBound); @@ -785,7 +793,7 @@ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, ui break; } - case Expression::kValueExpression: { + case ExpressionValueType::kExpression: { Expression* nested = exp->value[i].expression; ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(self, nested, &v)); break; @@ -803,27 +811,27 @@ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, ui uint64_t& b = value[1]; switch (exp->opType) { - case Expression::kOpAdd: + case ExpressionOpType::kAdd: result = a + b; break; - case Expression::kOpSub: + case ExpressionOpType::kSub: result = a - b; break; - case Expression::kOpMul: + case ExpressionOpType::kMul: result = a * b; break; - case Expression::kOpSll: + case ExpressionOpType::kSll: result = (b > 63) ? uint64_t(0) : uint64_t(a << b); break; - case Expression::kOpSrl: + case ExpressionOpType::kSrl: result = (b > 63) ? uint64_t(0) : uint64_t(a >> b); break; - case Expression::kOpSra: + case ExpressionOpType::kSra: result = Support::sar(a, Support::min<uint64_t>(b, 63)); break; @@ -835,9 +843,8 @@ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, ui return kErrorOk; } -// ============================================================================ -// [asmjit::BaseEmitter - Utilities] -// ============================================================================ +// CodeHolder - Utilities +// ====================== Error CodeHolder::flatten() noexcept { uint64_t offset = 0; @@ -917,7 +924,7 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { // Relocate all recorded locations. for (const RelocEntry* re : _relocations) { // Possibly deleted or optimized-out entry. - if (re->relocType() == RelocEntry::kTypeNone) + if (re->relocType() == RelocType::kNone) continue; Section* sourceSection = sectionById(re->sourceSectionId()); @@ -940,17 +947,17 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { size_t valueOffset = size_t(re->sourceOffset()) + re->format().valueOffset(); switch (re->relocType()) { - case RelocEntry::kTypeExpression: { + case RelocType::kExpression: { Expression* expression = (Expression*)(uintptr_t(value)); ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(this, expression, &value)); break; } - case RelocEntry::kTypeAbsToAbs: { + case RelocType::kAbsToAbs: { break; } - case RelocEntry::kTypeRelToAbs: { + case RelocType::kRelToAbs: { // Value is currently a relative offset from the start of its section. // We have to convert it to an absolute offset (including base address). if (ASMJIT_UNLIKELY(!targetSection)) @@ -961,14 +968,14 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { break; } - case RelocEntry::kTypeAbsToRel: { + case RelocType::kAbsToRel: { value -= baseAddress + sectionOffset + sourceOffset + regionSize; if (addressSize > 4 && !Support::isInt32(int64_t(value))) return DebugUtils::errored(kErrorRelocOffsetOutOfRange); break; } - case RelocEntry::kTypeX64AddressEntry: { + case RelocType::kX64AddressEntry: { if (re->format().valueSize() != 4 || valueOffset < 2) return DebugUtils::errored(kErrorInvalidRelocEntry); @@ -1055,7 +1062,7 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { return kErrorOk; } -Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions) noexcept { +Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, CopySectionFlags copyFlags) noexcept { if (ASMJIT_UNLIKELY(!isSectionValid(sectionId))) return DebugUtils::errored(kErrorInvalidSection); @@ -1067,7 +1074,7 @@ Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, memcpy(dst, section->data(), bufferSize); - if (bufferSize < dstSize && (copyOptions & kCopyPadSectionBuffer)) { + if (bufferSize < dstSize && Support::test(copyFlags, CopySectionFlags::kPadSectionBuffer)) { size_t paddingSize = dstSize - bufferSize; memset(static_cast<uint8_t*>(dst) + bufferSize, 0, paddingSize); } @@ -1075,7 +1082,7 @@ Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, return kErrorOk; } -Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions) noexcept { +Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, CopySectionFlags copyFlags) noexcept { size_t end = 0; for (Section* section : _sectionsByOrder) { if (section->offset() > dstSize) @@ -1091,7 +1098,7 @@ Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOpti size_t paddingSize = 0; memcpy(dstTarget, section->data(), bufferSize); - if ((copyOptions & kCopyPadSectionBuffer) && bufferSize < section->virtualSize()) { + if (Support::test(copyFlags, CopySectionFlags::kPadSectionBuffer) && bufferSize < section->virtualSize()) { paddingSize = Support::min<size_t>(dstSize - offset, size_t(section->virtualSize())) - bufferSize; memset(dstTarget + bufferSize, 0, paddingSize); } @@ -1099,16 +1106,15 @@ Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOpti end = Support::max(end, offset + bufferSize + paddingSize); } - if (end < dstSize && (copyOptions & kCopyPadTargetBuffer)) { + if (end < dstSize && Support::test(copyFlags, CopySectionFlags::kPadTargetBuffer)) { memset(static_cast<uint8_t*>(dst) + end, 0, dstSize - end); } return kErrorOk; } -// ============================================================================ -// [asmjit::CodeHolder - Unit] -// ============================================================================ +// CodeHolder - Tests +// ================== #if defined(ASMJIT_TEST) UNIT(code_holder) { @@ -1116,34 +1122,33 @@ UNIT(code_holder) { INFO("Verifying CodeHolder::init()"); Environment env; - env.init(Environment::kArchX86); + env.init(Arch::kX86); code.init(env); - EXPECT(code.arch() == Environment::kArchX86); + EXPECT(code.arch() == Arch::kX86); INFO("Verifying named labels"); LabelEntry* le; - EXPECT(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, Label::kTypeGlobal) == kErrorOk); + EXPECT(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, LabelType::kGlobal) == kErrorOk); EXPECT(strcmp(le->name(), "NamedLabel") == 0); EXPECT(code.labelIdByName("NamedLabel") == le->id()); INFO("Verifying section ordering"); Section* section1; - EXPECT(code.newSection(§ion1, "high-priority", SIZE_MAX, 0, 1, -1) == kErrorOk); + EXPECT(code.newSection(§ion1, "high-priority", SIZE_MAX, SectionFlags::kNone, 1, -1) == kErrorOk); EXPECT(code.sections()[1] == section1); EXPECT(code.sectionsByOrder()[0] == section1); Section* section0; - EXPECT(code.newSection(§ion0, "higher-priority", SIZE_MAX, 0, 1, -2) == kErrorOk); + EXPECT(code.newSection(§ion0, "higher-priority", SIZE_MAX, SectionFlags::kNone, 1, -2) == kErrorOk); EXPECT(code.sections()[2] == section0); EXPECT(code.sectionsByOrder()[0] == section0); EXPECT(code.sectionsByOrder()[1] == section1); Section* section3; - EXPECT(code.newSection(§ion3, "low-priority", SIZE_MAX, 0, 1, 2) == kErrorOk); + EXPECT(code.newSection(§ion3, "low-priority", SIZE_MAX, SectionFlags::kNone, 1, 2) == kErrorOk); EXPECT(code.sections()[3] == section3); EXPECT(code.sectionsByOrder()[3] == section3); - } #endif diff --git a/src/asmjit/core/codeholder.h b/src/asmjit/core/codeholder.h index 2a6ee49..b6257f2 100644 --- a/src/asmjit/core/codeholder.h +++ b/src/asmjit/core/codeholder.h @@ -1,32 +1,13 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_CODEHOLDER_H_INCLUDED #define ASMJIT_CORE_CODEHOLDER_H_INCLUDED #include "../core/archtraits.h" #include "../core/codebuffer.h" -#include "../core/datatypes.h" #include "../core/errorhandler.h" #include "../core/operand.h" #include "../core/string.h" @@ -43,65 +24,41 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class BaseEmitter; class CodeHolder; class LabelEntry; class Logger; -// ============================================================================ -// [asmjit::AlignMode] -// ============================================================================ - -//! Align mode. -enum AlignMode : uint32_t { - //! Align executable code. - kAlignCode = 0, - //! Align non-executable code. - kAlignData = 1, - //! Align by a sequence of zeros. - kAlignZero = 2, - //! Count of alignment modes. - kAlignCount = 3 +//! Operator type that can be used within an \ref Expression. +enum class ExpressionOpType : uint8_t { + //! Addition. + kAdd = 0, + //! Subtraction. + kSub = 1, + //! Multiplication + kMul = 2, + //! Logical left shift. + kSll = 3, + //! Logical right shift. + kSrl = 4, + //! Arithmetic right shift. + kSra = 5 }; -// ============================================================================ -// [asmjit::Expression] -// ============================================================================ +//! Value tyoe that can be used within an \ref Expression. +enum class ExpressionValueType : uint8_t { + //! No value or invalid. + kNone = 0, + //! Value is 64-bit unsigned integer (constant). + kConstant = 1, + //! Value is \ref LabelEntry, which references a \ref Label. + kLabel = 2, + //! Value is \ref Expression + kExpression = 3 +}; //! Expression node that can reference constants, labels, and another expressions. struct Expression { - //! Operation type. - enum OpType : uint8_t { - //! Addition. - kOpAdd = 0, - //! Subtraction. - kOpSub = 1, - //! Multiplication - kOpMul = 2, - //! Logical left shift. - kOpSll = 3, - //! Logical right shift. - kOpSrl = 4, - //! Arithmetic right shift. - kOpSra = 5 - }; - - //! Type of \ref Value. - enum ValueType : uint8_t { - //! No value or invalid. - kValueNone = 0, - //! Value is 64-bit unsigned integer (constant). - kValueConstant = 1, - //! Value is \ref LabelEntry, which references a \ref Label. - kValueLabel = 2, - //! Value is \ref Expression - kValueExpression = 3 - }; - //! Expression value. union Value { //! Constant. @@ -112,50 +69,93 @@ struct Expression { LabelEntry* label; }; + //! \name Members + //! \{ + //! Operation type. - uint8_t opType; + ExpressionOpType opType; //! Value types of \ref value. - uint8_t valueType[2]; + ExpressionValueType valueType[2]; //! Reserved for future use, should be initialized to zero. uint8_t reserved[5]; //! Expression left and right values. Value value[2]; + //! \} + + //! \name Accessors + //! \{ + //! Resets the whole expression. //! - //! Changes both values to \ref kValueNone. + //! Changes both values to \ref ExpressionValueType::kNone. inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - //! Sets the value type at `index` to \ref kValueConstant and its content to `constant`. + //! Sets the value type at `index` to \ref ExpressionValueType::kConstant and its content to `constant`. inline void setValueAsConstant(size_t index, uint64_t constant) noexcept { - valueType[index] = kValueConstant; + valueType[index] = ExpressionValueType::kConstant; value[index].constant = constant; } - //! Sets the value type at `index` to \ref kValueLabel and its content to `labelEntry`. + //! Sets the value type at `index` to \ref ExpressionValueType::kLabel and its content to `labelEntry`. inline void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept { - valueType[index] = kValueLabel; + valueType[index] = ExpressionValueType::kLabel; value[index].label = labelEntry; } - //! Sets the value type at `index` to \ref kValueExpression and its content to `expression`. + //! Sets the value type at `index` to \ref ExpressionValueType::kExpression and its content to `expression`. inline void setValueAsExpression(size_t index, Expression* expression) noexcept { - valueType[index] = kValueLabel; + valueType[index] = ExpressionValueType::kExpression; value[index].expression = expression; } + + //! \} }; -// ============================================================================ -// [asmjit::Section] -// ============================================================================ +//! Section flags, used by \ref Section. +enum class SectionFlags : uint32_t { + //! No flags. + kNone = 0, + //! Executable (.text sections). + kExecutable = 0x00000001u, + //! Read-only (.text and .data sections). + kReadOnly = 0x00000002u, + //! Zero initialized by the loader (BSS). + kZeroInitialized = 0x00000004u, + //! Info / comment flag. + kComment = 0x00000008u, + //! Section created implicitly, can be deleted by \ref Target. + kImplicit = 0x80000000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(SectionFlags) + +//! Flags that can be used with \ref CodeHolder::copySectionData() and \ref CodeHolder::copyFlattenedData(). +enum class CopySectionFlags : uint32_t { + //! No flags. + kNone = 0, + + //! If virtual size of a section is greater than the size of its \ref CodeBuffer then all bytes between the buffer + //! size and virtual size will be zeroed. If this option is not set then those bytes would be left as is, which + //! means that if the user didn't initialize them they would have a previous content, which may be unwanted. + kPadSectionBuffer = 0x00000001u, + + //! Clears the target buffer if the flattened data is less than the destination size. This option works + //! only with \ref CodeHolder::copyFlattenedData() as it processes multiple sections. It is ignored by + //! \ref CodeHolder::copySectionData(). + kPadTargetBuffer = 0x00000002u +}; +ASMJIT_DEFINE_ENUM_FLAGS(CopySectionFlags) //! Section entry. class Section { public: + //! \name Members + //! \{ + //! Section id. uint32_t _id; //! Section flags. - uint32_t _flags; + SectionFlags _flags; //! Section alignment requirements (0 if no requirements). uint32_t _alignment; //! Order (lower value means higher priority). @@ -169,19 +169,7 @@ public: //! Code or data buffer. CodeBuffer _buffer; - //! Section flags. - enum Flags : uint32_t { - //! Executable (.text sections). - kFlagExec = 0x00000001u, - //! Read-only (.text and .data sections). - kFlagConst = 0x00000002u, - //! Zero initialized by the loader (BSS). - kFlagZero = 0x00000004u, - //! Info / comment flag. - kFlagInfo = 0x00000008u, - //! Section created implicitly and can be deleted by \ref Target. - kFlagImplicit = 0x80000000u - }; + //! \} //! \name Accessors //! \{ @@ -196,14 +184,14 @@ public: //! \overload inline const uint8_t* data() const noexcept { return _buffer.data(); } - //! Returns the section flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } + //! Returns the section flags. + inline SectionFlags flags() const noexcept { return _flags; } //! Tests whether the section has the given `flag`. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } + inline bool hasFlag(SectionFlags flag) const noexcept { return Support::test(_flags, flag); } //! Adds `flags` to the section flags. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } + inline void addFlags(SectionFlags flags) noexcept { _flags |= flags; } //! Removes `flags` from the section flags. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } + inline void clearFlags(SectionFlags flags) noexcept { _flags &= ~flags; } //! Returns the minimum section alignment inline uint32_t alignment() const noexcept { return _alignment; } @@ -220,9 +208,8 @@ public: //! Returns the virtual size of the section. //! - //! Virtual size is initially zero and is never changed by AsmJit. It's normal - //! if virtual size is smaller than size returned by `bufferSize()` as the buffer - //! stores real data emitted by assemblers or appended by users. + //! Virtual size is initially zero and is never changed by AsmJit. It's normal if virtual size is smaller than + //! size returned by `bufferSize()` as the buffer stores real data emitted by assemblers or appended by users. //! //! Use `realSize()` to get the real and final size of this section. inline uint64_t virtualSize() const noexcept { return _virtualSize; } @@ -242,16 +229,71 @@ public: //! \} }; -// ============================================================================ -// [asmjit::OffsetFormat] -// ============================================================================ +//! Entry in an address table. +class AddressTableEntry : public ZoneTreeNodeT<AddressTableEntry> { +public: + ASMJIT_NONCOPYABLE(AddressTableEntry) + + //! \name Members + //! \{ -//! Provides information about formatting offsets, absolute addresses, or their -//! parts. Offset format is used by both \ref RelocEntry and \ref LabelLink. -//! -//! The illustration above describes the relation of region size and offset size. -//! Region size is the size of the whole unit whereas offset size is the size of -//! the unit that will be patched. + //! Address. + uint64_t _address; + //! Slot. + uint32_t _slot; + + //! \} + + //! \name Construction & Destruction + //! \{ + + inline explicit AddressTableEntry(uint64_t address) noexcept + : _address(address), + _slot(0xFFFFFFFFu) {} + + //! \} + + //! \name Accessors + //! \{ + + inline uint64_t address() const noexcept { return _address; } + inline uint32_t slot() const noexcept { return _slot; } + + inline bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; } + + inline bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; } + inline bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; } + + inline bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; } + inline bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; } + + //! \} +}; + +//! Offset format type, used by \ref OffsetFormat. +enum class OffsetType : uint8_t { + //! A value having `_immBitCount` bits and shifted by `_immBitShift`. + //! + //! This offset type is sufficient for many targets that store offset as a continuous set bits within an + //! instruction word / sequence of bytes. + kCommon = 0, + + // AArch64 Specific Offset Formats + // ------------------------------- + + //! AARCH64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. + kAArch64_ADR, + + //! AARCH64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). + kAArch64_ADRP, + + //! Maximum value of `OffsetFormatType`. + kMaxValue = kAArch64_ADRP +}; + +//! Provides information about formatting offsets, absolute addresses, or their parts. Offset format is used by both +//! \ref RelocEntry and \ref LabelLink. The illustration below describes the relation of region size and offset size. +//! Region size is the size of the whole unit whereas offset size is the size of the unit that will be patched. //! //! ``` //! +-> Code buffer | The subject of the relocation (region) | @@ -274,77 +316,64 @@ public: //! (ImmBitCount) +- ImmBitShift //! ``` struct OffsetFormat { - //! Type of the displacement. - uint8_t _type; + //! \name Members + //! \{ + + //! Type of the offset. + OffsetType _type; //! Encoding flags. uint8_t _flags; - //! Size of the region (in bytes) containing the offset value, if the offset - //! value is part of an instruction, otherwise it would be the same as - //! `_valueSize`. + //! Size of the region (in bytes) containing the offset value, if the offset value is part of an instruction, + //! otherwise it would be the same as `_valueSize`. uint8_t _regionSize; //! Size of the offset value, in bytes (1, 2, 4, or 8). uint8_t _valueSize; - //! Offset of the offset value, in bytes, relative to the start of the region - //! or data. Value offset would be zero if both region size and value size are - //! equal. + //! Offset of the offset value, in bytes, relative to the start of the region or data. Value offset would be + //! zero if both region size and value size are equal. uint8_t _valueOffset; - //! Size of the displacement immediate value in bits. + //! Size of the offset immediate value in bits. uint8_t _immBitCount; - //! Shift of the displacement immediate value in bits in the target word. + //! Shift of the offset immediate value in bits in the target word. uint8_t _immBitShift; - //! Number of least significant bits to discard before writing the immediate - //! to the destination. All discarded bits must be zero otherwise the value - //! is invalid. + //! Number of least significant bits to discard before writing the immediate to the destination. All discarded + //! bits must be zero otherwise the value is invalid. uint8_t _immDiscardLsb; - //! Type of the displacement. - enum Type : uint8_t { - //! A value having `_immBitCount` bits and shifted by `_immBitShift`. - //! - //! This displacement type is sufficient for both X86/X64 and many other - //! architectures that store displacement as continuous bits within a machine - //! word. - kTypeCommon = 0, - //! AARCH64 ADR format of `[.|immlo:2|.....|immhi:19|.....]`. - kTypeAArch64_ADR, - //! AARCH64 ADRP format of `[.|immlo:2|.....|immhi:19|.....]` (4kB pages). - kTypeAArch64_ADRP, - - //! Count of displacement types. - kTypeCount - }; + //! \} - //! Returns the type of the displacement. - inline uint32_t type() const noexcept { return _type; } + //! \name Accessors + //! \{ + + //! Returns the type of the offset. + inline OffsetType type() const noexcept { return _type; } //! Returns flags. inline uint32_t flags() const noexcept { return _flags; } - //! Returns the size of the region/instruction where the displacement is encoded. + //! Returns the size of the region/instruction where the offset is encoded. inline uint32_t regionSize() const noexcept { return _regionSize; } - //! Returns the the offset of the word relative to the start of the region - //! where the displacement is. + //! Returns the the offset of the word relative to the start of the region where the offset is. inline uint32_t valueOffset() const noexcept { return _valueOffset; } - //! Returns the size of the data-type (word) that contains the displacement, in bytes. + //! Returns the size of the data-type (word) that contains the offset, in bytes. inline uint32_t valueSize() const noexcept { return _valueSize; } - //! Returns the count of bits of the displacement value in the data it's stored in. + //! Returns the count of bits of the offset value in the data it's stored in. inline uint32_t immBitCount() const noexcept { return _immBitCount; } - //! Returns the bit-shift of the displacement value in the data it's stored in. + //! Returns the bit-shift of the offset value in the data it's stored in. inline uint32_t immBitShift() const noexcept { return _immBitShift; } - //! Returns the number of least significant bits of the displacement value, - //! that must be zero and that are not part of the encoded data. + //! Returns the number of least significant bits of the offset value, that must be zero and that are not part of + //! the encoded data. inline uint32_t immDiscardLsb() const noexcept { return _immDiscardLsb; } //! Resets this offset format to a simple data value of `dataSize` bytes. //! - //! The region will be the same size as data and immediate bits would correspond - //! to `dataSize * 8`. There will be no immediate bit shift or discarded bits. + //! The region will be the same size as data and immediate bits would correspond to `dataSize * 8`. There will be + //! no immediate bit shift or discarded bits. inline void resetToDataValue(size_t dataSize) noexcept { ASMJIT_ASSERT(dataSize <= 8u); - _type = uint8_t(kTypeCommon); + _type = OffsetType::kCommon; _flags = uint8_t(0); _regionSize = uint8_t(dataSize); _valueSize = uint8_t(dataSize); @@ -354,13 +383,13 @@ struct OffsetFormat { _immDiscardLsb = uint8_t(0); } - inline void resetToImmValue(uint32_t type, size_t valueSize, uint32_t immBitShift, uint32_t immBitCount, uint32_t immDiscardLsb) noexcept { + inline void resetToImmValue(OffsetType type, size_t valueSize, uint32_t immBitShift, uint32_t immBitCount, uint32_t immDiscardLsb) noexcept { ASMJIT_ASSERT(valueSize <= 8u); ASMJIT_ASSERT(immBitShift < valueSize * 8u); ASMJIT_ASSERT(immBitCount <= 64u); ASMJIT_ASSERT(immDiscardLsb <= 64u); - _type = uint8_t(type); + _type = type; _flags = uint8_t(0); _regionSize = uint8_t(valueSize); _valueSize = uint8_t(valueSize); @@ -379,18 +408,35 @@ struct OffsetFormat { _regionSize = uint8_t(leadingSize + trailingSize + _valueSize); _valueOffset = uint8_t(leadingSize); } + + //! \} }; -// ============================================================================ -// [asmjit::RelocEntry] -// ============================================================================ +//! Relocation type. +enum class RelocType : uint32_t { + //! None/deleted (no relocation). + kNone = 0, + //! Expression evaluation, `_payload` is pointer to `Expression`. + kExpression = 1, + //! Relocate absolute to absolute. + kAbsToAbs = 2, + //! Relocate relative to absolute. + kRelToAbs = 3, + //! Relocate absolute to relative. + kAbsToRel = 4, + //! Relocate absolute to relative or use trampoline. + kX64AddressEntry = 5 +}; //! Relocation entry. struct RelocEntry { + //! \name Members + //! \{ + //! Relocation id. uint32_t _id; //! Type of the relocation. - uint32_t _relocType; + RelocType _relocType; //! Format of the relocated value. OffsetFormat _format; //! Source section id. @@ -402,28 +448,14 @@ struct RelocEntry { //! Payload (target offset, target address, expression, etc). uint64_t _payload; - //! Relocation type. - enum RelocType : uint32_t { - //! None/deleted (no relocation). - kTypeNone = 0, - //! Expression evaluation, `_payload` is pointer to `Expression`. - kTypeExpression = 1, - //! Relocate absolute to absolute. - kTypeAbsToAbs = 2, - //! Relocate relative to absolute. - kTypeRelToAbs = 3, - //! Relocate absolute to relative. - kTypeAbsToRel = 4, - //! Relocate absolute to relative or use trampoline. - kTypeX64AddressEntry = 5 - }; + //! \} //! \name Accessors //! \{ inline uint32_t id() const noexcept { return _id; } - inline uint32_t relocType() const noexcept { return _relocType; } + inline RelocType relocType() const noexcept { return _relocType; } inline const OffsetFormat& format() const noexcept { return _format; } inline uint32_t sourceSectionId() const noexcept { return _sourceSectionId; } @@ -439,9 +471,20 @@ struct RelocEntry { //! \} }; -// ============================================================================ -// [asmjit::LabelLink] -// ============================================================================ +//! Type of the \ref Label. +enum class LabelType : uint8_t { + //! Anonymous label that can optionally have a name, which is only used for debugging purposes. + kAnonymous = 0, + //! Local label (always has parentId). + kLocal = 1, + //! Global label (never has parentId). + kGlobal = 2, + //! External label (references an external symbol). + kExternal = 3, + + //! Maximum value of `LabelType`. + kMaxValue = kExternal +}; //! Data structure used to link either unbound labels or cross-section links. struct LabelLink { @@ -459,41 +502,43 @@ struct LabelLink { OffsetFormat format; }; -// ============================================================================ -// [asmjit::LabelEntry] -// ============================================================================ - //! Label entry. //! //! Contains the following properties: -//! * Label id - This is the only thing that is set to the `Label` operand. -//! * Label name - Optional, used mostly to create executables and libraries. -//! * Label type - Type of the label, default `Label::kTypeAnonymous`. -//! * Label parent id - Derived from many assemblers that allow to define a -//! local label that falls under a global label. This allows to define -//! many labels of the same name that have different parent (global) label. -//! * Offset - offset of the label bound by `Assembler`. -//! * Links - single-linked list that contains locations of code that has -//! to be patched when the label gets bound. Every use of unbound label -//! adds one link to `_links` list. -//! * HVal - Hash value of label's name and optionally parentId. -//! * HashNext - Hash-table implementation detail. +//! - Label id - This is the only thing that is set to the `Label` operand. +//! - Label name - Optional, used mostly to create executables and libraries. +//! - Label type - Type of the label, default `LabelType::kAnonymous`. +//! - Label parent id - Derived from many assemblers that allow to define a local label that falls under a global +//! label. This allows to define many labels of the same name that have different parent (global) label. +//! - Offset - offset of the label bound by `Assembler`. +//! - Links - single-linked list that contains locations of code that has to be patched when the label gets bound. +//! Every use of unbound label adds one link to `_links` list. +//! - HVal - Hash value of label's name and optionally parentId. +//! - HashNext - Hash-table implementation detail. class LabelEntry : public ZoneHashNode { public: - // Let's round the size of `LabelEntry` to 64 bytes (as `ZoneAllocator` has - // granularity of 32 bytes anyway). This gives `_name` the remaining space, - // which is should be 16 bytes on 64-bit and 28 bytes on 32-bit architectures. + //! \name Constants + //! \{ + enum : uint32_t { - kStaticNameSize = - 64 - (sizeof(ZoneHashNode) + 8 + sizeof(Section*) + sizeof(size_t) + sizeof(LabelLink*)) + //! SSO size of \ref _name. + //! + //! \cond INTERNAL + //! Let's round the size of `LabelEntry` to 64 bytes (as `ZoneAllocator` has granularity of 32 bytes anyway). This + //! gives `_name` the remaining space, which is should be 16 bytes on 64-bit and 28 bytes on 32-bit architectures. + //! \endcond + kStaticNameSize = 64 - (sizeof(ZoneHashNode) + 8 + sizeof(Section*) + sizeof(size_t) + sizeof(LabelLink*)) }; - //! Label type, see `Label::LabelType`. - uint8_t _type; + //! \} + + //! \name Members + //! \{ + + //! Type of the label. + LabelType _type; //! Must be zero. - uint8_t _flags; - //! Reserved. - uint16_t _reserved16; + uint8_t _reserved[3]; //! Label parent id or zero. uint32_t _parentId; //! Label offset relative to the start of the `_section`. @@ -505,22 +550,21 @@ public: //! Label name. ZoneString<kStaticNameSize> _name; + //! \} + //! \name Accessors //! \{ - // NOTE: Label id is stored in `_customData`, which is provided by ZoneHashNode - // to fill a padding that a C++ compiler targeting 64-bit CPU will add to align - // the structure to 64-bits. + // NOTE: Label id is stored in `_customData`, which is provided by ZoneHashNode to fill a padding that a C++ + // compiler targeting 64-bit CPU will add to align the structure to 64-bits. //! Returns label id. inline uint32_t id() const noexcept { return _customData; } //! Sets label id (internal, used only by `CodeHolder`). inline void _setId(uint32_t id) noexcept { _customData = id; } - //! Returns label type, see `Label::LabelType`. - inline uint32_t type() const noexcept { return _type; } - //! Returns label flags, returns 0 at the moment. - inline uint32_t flags() const noexcept { return _flags; } + //! Returns label type. + inline LabelType type() const noexcept { return _type; } //! Tests whether the label has a parent label. inline bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; } @@ -537,15 +581,13 @@ public: //! Returns the label's name. //! - //! \note Local labels will return their local name without their parent - //! part, for example ".L1". + //! \note Local labels will return their local name without their parent part, for example ".L1". inline const char* name() const noexcept { return _name.data(); } //! Returns size of label's name. //! - //! \note Label name is always null terminated, so you can use `strlen()` to - //! get it, however, it's also cached in `LabelEntry` itself, so if you want - //! to know the size the fastest way is to call `LabelEntry::nameSize()`. + //! \note Label name is always null terminated, so you can use `strlen()` to get it, however, it's also cached in + //! `LabelEntry` itself, so if you want to know the size the fastest way is to call `LabelEntry::nameSize()`. inline uint32_t nameSize() const noexcept { return _name.size(); } //! Returns links associated with this label. @@ -561,71 +603,38 @@ public: //! Returns the hash-value of label's name and its parent label (if any). //! - //! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function - //! is implemented in `Support::hashString()` and `Support::hashRound()`. + //! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function is implemented in `Support::hashString()` + //! and `Support::hashRound()`. inline uint32_t hashCode() const noexcept { return _hashCode; } //! \} }; -// ============================================================================ -// [asmjit::AddressTableEntry] -// ============================================================================ - -//! Entry in an address table. -class AddressTableEntry : public ZoneTreeNodeT<AddressTableEntry> { -public: - ASMJIT_NONCOPYABLE(AddressTableEntry) - - //! Address. - uint64_t _address; - //! Slot. - uint32_t _slot; - - //! \name Construction & Destruction - //! \{ - - inline explicit AddressTableEntry(uint64_t address) noexcept - : _address(address), - _slot(0xFFFFFFFFu) {} - - //! \} - - //! \name Accessors - //! \{ - - inline uint64_t address() const noexcept { return _address; } - inline uint32_t slot() const noexcept { return _slot; } - - inline bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; } - - inline bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; } - inline bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; } - - inline bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; } - inline bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; } - - //! \} -}; - -// ============================================================================ -// [asmjit::CodeHolder] -// ============================================================================ - -//! Contains basic information about the target architecture and its options. +//! Holds assembled code and data (including sections, labels, and relocation information). +//! +//! CodeHolder connects emitters with their targets. It provides them interface that can be used to query information +//! about the target environment (architecture, etc...) and API to create labels, sections, relocations, and to write +//! data to a \ref CodeBuffer, which is always part of \ref Section. More than one emitter can be attached to a single +//! CodeHolder instance at a time, which is used in practice +//! +//! CodeHolder provides interface for all emitter types. Assemblers use CodeHolder to write into \ref CodeBuffer, and +//! higher level emitters like Builder and Compiler use CodeHolder to manage labels and sections so higher level code +//! can be serialized to Assembler by \ref BaseEmitter::finalize() and \ref BaseBuilder::serializeTo(). //! -//! In addition, it holds assembled code & data (including sections, labels, and -//! relocation information). `CodeHolder` can store both binary and intermediate -//! representation of assembly, which can be generated by \ref BaseAssembler, -//! \ref BaseBuilder, and \ref BaseCompiler +//! In order to use CodeHolder, it must be first initialized by \ref init(). After the CodeHolder has been successfully +//! initialized it can be used to hold assembled code, sections, labels, relocations, and to attach / detach code +//! emitters. After the end of code generation it can be used to query physical locations of labels and to relocate +//! the assembled code into the right address. //! -//! \note `CodeHolder` has an ability to attach an \ref ErrorHandler, however, -//! the error handler is not triggered by `CodeHolder` itself, it's instead -//! propagated to all emitters that attach to it. +//! \note \ref CodeHolder has an ability to attach an \ref ErrorHandler, however, the error handler is not triggered +//! by \ref CodeHolder itself, it's instead propagated to all emitters that attach to it. class CodeHolder { public: ASMJIT_NONCOPYABLE(CodeHolder) + //! \name Members + //! \{ + //! Environment information. Environment _environment; //! Base address or \ref Globals::kNoBaseAddress. @@ -661,31 +670,22 @@ public: //! Address table entries. ZoneTree<AddressTableEntry> _addressTableEntries; - //! Options that can be used with \ref copySectionData() and \ref copyFlattenedData(). - enum CopyOptions : uint32_t { - //! If virtual size of a section is greater than the size of its \ref CodeBuffer - //! then all bytes between the buffer size and virtual size will be zeroed. - //! If this option is not set then those bytes would be left as is, which - //! means that if the user didn't initialize them they would have a previous - //! content, which may be unwanted. - kCopyPadSectionBuffer = 0x00000001u, - -#ifndef ASMJIT_NO_DEPRECATED - kCopyWithPadding = kCopyPadSectionBuffer, -#endif // !ASMJIT_NO_DEPRECATED - - //! Zeroes the target buffer if the flattened data is less than the destination - //! size. This option works only with \ref copyFlattenedData() as it processes - //! multiple sections. It is ignored by \ref copySectionData(). - kCopyPadTargetBuffer = 0x00000002u - }; + //! \} //! \name Construction & Destruction //! \{ //! Creates an uninitialized CodeHolder (you must init() it before it can be used). - ASMJIT_API CodeHolder() noexcept; - //! Destroys the CodeHolder. + //! + //! An optional `temporary` argument can be used to initialize the first block of \ref Zone that the CodeHolder + //! uses into a temporary memory provided by the user. + ASMJIT_API explicit CodeHolder(const Support::Temporary* temporary = nullptr) noexcept; + + //! \overload + inline explicit CodeHolder(const Support::Temporary& temporary) noexcept + : CodeHolder(&temporary) {} + + //! Destroys the CodeHolder and frees all resources it has allocated. ASMJIT_API ~CodeHolder() noexcept; //! Tests whether the `CodeHolder` has been initialized. @@ -693,10 +693,10 @@ public: //! Emitters can be only attached to initialized `CodeHolder` instances. inline bool isInitialized() const noexcept { return _environment.isInitialized(); } - //! Initializes CodeHolder to hold code described by code `info`. + //! Initializes CodeHolder to hold code described by the given `environment` and `baseAddress`. ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; //! Detaches all code-generators attached and resets the `CodeHolder`. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; + ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept; //! \} @@ -715,10 +715,9 @@ public: //! Returns the allocator that the `CodeHolder` uses. //! - //! \note This should be only used for AsmJit's purposes. Code holder uses - //! arena allocator to allocate everything, so anything allocated through - //! this allocator will be invalidated by \ref CodeHolder::reset() or by - //! CodeHolder's destructor. + //! \note This should be only used for AsmJit's purposes. Code holder uses arena allocator to allocate everything, + //! so anything allocated through this allocator will be invalidated by \ref CodeHolder::reset() or by CodeHolder's + //! destructor. inline ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); } //! \} @@ -726,13 +725,13 @@ public: //! \name Code & Architecture //! \{ - //! Returns the target environment information, see \ref Environment. + //! Returns the target environment information. inline const Environment& environment() const noexcept { return _environment; } //! Returns the target architecture. - inline uint32_t arch() const noexcept { return environment().arch(); } + inline Arch arch() const noexcept { return environment().arch(); } //! Returns the target sub-architecture. - inline uint32_t subArch() const noexcept { return environment().subArch(); } + inline SubArch subArch() const noexcept { return environment().subArch(); } //! Tests whether a static base-address is set. inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } @@ -752,7 +751,7 @@ public: //! \name Logging //! \{ - //! Returns the attached logger, see \ref Logger. + //! Returns the attached logger. inline Logger* logger() const noexcept { return _logger; } //! Attaches a `logger` to CodeHolder and propagates it to all attached emitters. ASMJIT_API void setLogger(Logger* logger) noexcept; @@ -778,14 +777,12 @@ public: //! Makes sure that at least `n` bytes can be added to CodeHolder's buffer `cb`. //! - //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the - //! behavior of the function is undefined. + //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the behavior of the function is undefined. ASMJIT_API Error growBuffer(CodeBuffer* cb, size_t n) noexcept; //! Reserves the size of `cb` to at least `n` bytes. //! - //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the - //! behavior of the function is undefined. + //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the behavior of the function is undefined. ASMJIT_API Error reserveBuffer(CodeBuffer* cb, size_t n) noexcept; //! \} @@ -806,7 +803,7 @@ public: //! Creates a new section and return its pointer in `sectionOut`. //! //! Returns `Error`, does not report a possible error to `ErrorHandler`. - ASMJIT_API Error newSection(Section** sectionOut, const char* name, size_t nameSize = SIZE_MAX, uint32_t flags = 0, uint32_t alignment = 1, int32_t order = 0) noexcept; + ASMJIT_API Error newSection(Section** sectionOut, const char* name, size_t nameSize = SIZE_MAX, SectionFlags flags = SectionFlags::kNone, uint32_t alignment = 1, int32_t order = 0) noexcept; //! Returns a section entry of the given index. inline Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; } @@ -838,14 +835,12 @@ public: //! Used to add an address to an address table. //! - //! This implicitly calls `ensureAddressTableSection()` and then creates - //! `AddressTableEntry` that is inserted to `_addressTableEntries`. If the - //! address already exists this operation does nothing as the same addresses + //! This implicitly calls `ensureAddressTableSection()` and then creates `AddressTableEntry` that is inserted + //! to `_addressTableEntries`. If the address already exists this operation does nothing as the same addresses //! use the same slot. //! - //! This function should be considered internal as it's used by assemblers to - //! insert an absolute address into the address table. Inserting address into - //! address table without creating a particula relocation entry makes no sense. + //! This function should be considered internal as it's used by assemblers to insert an absolute address into the + //! address table. Inserting address into address table without creating a particula relocation entry makes no sense. ASMJIT_API Error addAddressToAddressTable(uint64_t address) noexcept; //! \} @@ -893,8 +888,8 @@ public: //! Returns offset of a `Label` by its `labelId`. //! - //! The offset returned is relative to the start of the section. Zero offset - //! is returned for unbound labels, which is their initial offset value. + //! The offset returned is relative to the start of the section. Zero offset is returned for unbound labels, + //! which is their initial offset value. inline uint64_t labelOffset(uint32_t labelId) const noexcept { ASMJIT_ASSERT(isLabelValid(labelId)); return _labelEntries[labelId]->offset(); @@ -907,9 +902,8 @@ public: //! Returns offset of a label by it's `labelId` relative to the base offset. //! - //! \remarks The offset of the section where the label is bound must be valid - //! in order to use this function, otherwise the value returned will not be - //! reliable. + //! \remarks The offset of the section where the label is bound must be valid in order to use this function, + //! otherwise the value returned will not be reliable. inline uint64_t labelOffsetFromBase(uint32_t labelId) const noexcept { ASMJIT_ASSERT(isLabelValid(labelId)); const LabelEntry* le = _labelEntries[labelId]; @@ -930,20 +924,18 @@ public: //! //! \param entryOut Where to store the created \ref LabelEntry. //! \param name The name of the label. - //! \param nameSize The length of `name` argument, or `SIZE_MAX` if `name` is - //! a null terminated string, which means that the `CodeHolder` will - //! use `strlen()` to determine the length. - //! \param type The type of the label to create, see \ref Label::LabelType. - //! \param parentId Parent id of a local label, otherwise it must be - //! \ref Globals::kInvalidId. + //! \param nameSize The length of `name` argument, or `SIZE_MAX` if `name` is a null terminated string, which + //! means that the `CodeHolder` will use `strlen()` to determine the length. + //! \param type The type of the label to create, see \ref LabelType. + //! \param parentId Parent id of a local label, otherwise it must be \ref Globals::kInvalidId. + //! \retval Always returns \ref Error, does not report a possible error to the attached \ref ErrorHandler. //! - //! \retval Always returns \ref Error, does not report a possible error to - //! the attached \ref ErrorHandler. - //! - //! AsmJit has a support for local labels (\ref Label::kTypeLocal) which - //! require a parent label id (parentId). The names of local labels can - //! conflict with names of other local labels that have a different parent. - ASMJIT_API Error newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId = Globals::kInvalidId) noexcept; + //! AsmJit has a support for local labels (\ref LabelType::kLocal) which require a parent label id (parentId). + //! The names of local labels can conflict with names of other local labels that have a different parent. In + //! addition, AsmJit supports named anonymous labels, which are useful only for debugging purposes as the + //! anonymous name will have a name, which will be formatted, but the label itself cannot be queried by such + //! name. + ASMJIT_API Error newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, LabelType type, uint32_t parentId = Globals::kInvalidId) noexcept; //! Returns a label by name. //! @@ -968,10 +960,9 @@ public: //! Returns `null` if the allocation failed. ASMJIT_API LabelLink* newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel, const OffsetFormat& format) noexcept; - //! Resolves cross-section links (`LabelLink`) associated with each label that - //! was used as a destination in code of a different section. It's only useful - //! to people that use multiple sections as it will do nothing if the code only - //! contains a single section in which cross-section links are not possible. + //! Resolves cross-section links (`LabelLink`) associated with each label that was used as a destination in code + //! of a different section. It's only useful to people that use multiple sections as it will do nothing if the code + //! only contains a single section in which cross-section links are not possible. ASMJIT_API Error resolveUnresolvedLinks() noexcept; //! Binds a label to a given `sectionId` and `offset` (relative to start of the section). @@ -995,7 +986,7 @@ public: //! Creates a new relocation entry of type `relocType`. //! //! Additional fields can be set after the relocation entry was created. - ASMJIT_API Error newRelocEntry(RelocEntry** dst, uint32_t relocType) noexcept; + ASMJIT_API Error newRelocEntry(RelocEntry** dst, RelocType relocType) noexcept; //! \} @@ -1009,49 +1000,29 @@ public: //! Returns computed the size of code & data of all sections. //! - //! \note All sections will be iterated over and the code size returned - //! would represent the minimum code size of all combined sections after - //! applying minimum alignment. Code size may decrease after calling - //! `flatten()` and `relocateToBase()`. + //! \note All sections will be iterated over and the code size returned would represent the minimum code size of + //! all combined sections after applying minimum alignment. Code size may decrease after calling `flatten()` and + //! `relocateToBase()`. ASMJIT_API size_t codeSize() const noexcept; //! Relocates the code to the given `baseAddress`. //! - //! \param baseAddress Absolute base address where the code will be relocated - //! to. Please note that nothing is copied to such base address, it's just an - //! absolute value used by the relocator to resolve all stored relocations. + //! \param baseAddress Absolute base address where the code will be relocated to. Please note that nothing is + //! copied to such base address, it's just an absolute value used by the relocator to resolve all stored relocations. //! //! \note This should never be called more than once. ASMJIT_API Error relocateToBase(uint64_t baseAddress) noexcept; //! Copies a single section into `dst`. - ASMJIT_API Error copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions = 0) noexcept; + ASMJIT_API Error copySectionData(void* dst, size_t dstSize, uint32_t sectionId, CopySectionFlags copyFlags = CopySectionFlags::kNone) noexcept; //! Copies all sections into `dst`. //! - //! This should only be used if the data was flattened and there are no gaps - //! between the sections. The `dstSize` is always checked and the copy will - //! never write anything outside the provided buffer. - ASMJIT_API Error copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions = 0) noexcept; + //! This should only be used if the data was flattened and there are no gaps between the sections. The `dstSize` + //! is always checked and the copy will never write anything outside the provided buffer. + ASMJIT_API Error copyFlattenedData(void* dst, size_t dstSize, CopySectionFlags copyFlags = CopySectionFlags::kNone) noexcept; //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use 'CodeHolder::init(const Environment& environment, uint64_t baseAddress)' instead") - inline Error init(const CodeInfo& codeInfo) noexcept { return init(codeInfo._environment, codeInfo._baseAddress); } - - ASMJIT_DEPRECATED("Use nevironment() instead") - inline CodeInfo codeInfo() const noexcept { return CodeInfo(_environment, _baseAddress); } - - ASMJIT_DEPRECATED("Use BaseEmitter::encodingOptions() - this function always returns zero") - inline uint32_t emitterOptions() const noexcept { return 0; } - - ASMJIT_DEPRECATED("Use BaseEmitter::addEncodingOptions() - this function does nothing") - inline void addEmitterOptions(uint32_t options) noexcept { DebugUtils::unused(options); } - - ASMJIT_DEPRECATED("Use BaseEmitter::clearEncodingOptions() - this function does nothing") - inline void clearEmitterOptions(uint32_t options) noexcept { DebugUtils::unused(options); } -#endif // !ASMJIT_NO_DEPRECATED }; //! \} diff --git a/src/asmjit/core/codewriter.cpp b/src/asmjit/core/codewriter.cpp index 6097c0e..772146e 100644 --- a/src/asmjit/core/codewriter.cpp +++ b/src/asmjit/core/codewriter.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/codeholder.h" @@ -50,13 +32,13 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs return false; switch (format.type()) { - case OffsetFormat::kTypeCommon: { + case OffsetType::kCommon: { *dst = (uint32_t(offset32) & Support::lsbMask<uint32_t>(bitCount)) << bitShift; return true; } - case OffsetFormat::kTypeAArch64_ADR: - case OffsetFormat::kTypeAArch64_ADRP: { + case OffsetType::kAArch64_ADR: + case OffsetType::kAArch64_ADRP: { // Sanity checks. if (format.valueSize() != 4 || bitCount != 21 || bitShift != 5) return false; @@ -91,7 +73,7 @@ bool CodeWriterUtils::encodeOffset64(uint64_t* dst, int64_t offset64, const Offs return false; switch (format.type()) { - case OffsetFormat::kTypeCommon: { + case OffsetType::kCommon: { *dst = (uint64_t(offset64) & Support::lsbMask<uint64_t>(bitCount)) << format.immBitShift(); return true; } diff --git a/src/asmjit/core/codewriter_p.h b/src/asmjit/core/codewriter_p.h index 61c9101..8b120bd 100644 --- a/src/asmjit/core/codewriter_p.h +++ b/src/asmjit/core/codewriter_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED #define ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED @@ -34,25 +16,17 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_assembler //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - struct OffsetFormat; -// ============================================================================ -// [asmjit::CodeWriter] -// ============================================================================ - //! Helper that is used to write into a \ref CodeBuffer held by \ref BaseAssembler. class CodeWriter { public: uint8_t* _cursor; - ASMJIT_INLINE explicit CodeWriter(BaseAssembler* a) noexcept + ASMJIT_FORCE_INLINE explicit CodeWriter(BaseAssembler* a) noexcept : _cursor(a->_bufferPtr) {} - ASMJIT_INLINE Error ensureSpace(BaseAssembler* a, size_t n) noexcept { + ASMJIT_FORCE_INLINE Error ensureSpace(BaseAssembler* a, size_t n) noexcept { size_t remainingSpace = (size_t)(a->_bufferEnd - _cursor); if (ASMJIT_UNLIKELY(remainingSpace < n)) { CodeBuffer& buffer = a->_section->_buffer; @@ -64,24 +38,24 @@ public: return kErrorOk; } - ASMJIT_INLINE uint8_t* cursor() const noexcept { return _cursor; } - ASMJIT_INLINE void setCursor(uint8_t* cursor) noexcept { _cursor = cursor; } - ASMJIT_INLINE void advance(size_t n) noexcept { _cursor += n; } + ASMJIT_FORCE_INLINE uint8_t* cursor() const noexcept { return _cursor; } + ASMJIT_FORCE_INLINE void setCursor(uint8_t* cursor) noexcept { _cursor = cursor; } + ASMJIT_FORCE_INLINE void advance(size_t n) noexcept { _cursor += n; } - ASMJIT_INLINE size_t offsetFrom(uint8_t* from) const noexcept { + ASMJIT_FORCE_INLINE size_t offsetFrom(uint8_t* from) const noexcept { ASMJIT_ASSERT(_cursor >= from); return (size_t)(_cursor - from); } template<typename T> - ASMJIT_INLINE void emit8(T val) noexcept { + ASMJIT_FORCE_INLINE void emit8(T val) noexcept { typedef typename std::make_unsigned<T>::type U; _cursor[0] = uint8_t(U(val) & U(0xFF)); _cursor++; } template<typename T, typename Y> - ASMJIT_INLINE void emit8If(T val, Y cond) noexcept { + ASMJIT_FORCE_INLINE void emit8If(T val, Y cond) noexcept { typedef typename std::make_unsigned<T>::type U; ASMJIT_ASSERT(size_t(cond) <= 1u); @@ -90,41 +64,41 @@ public: } template<typename T> - ASMJIT_INLINE void emit16uLE(T val) noexcept { + ASMJIT_FORCE_INLINE void emit16uLE(T val) noexcept { typedef typename std::make_unsigned<T>::type U; Support::writeU16uLE(_cursor, uint32_t(U(val) & 0xFFFFu)); _cursor += 2; } template<typename T> - ASMJIT_INLINE void emit16uBE(T val) noexcept { + ASMJIT_FORCE_INLINE void emit16uBE(T val) noexcept { typedef typename std::make_unsigned<T>::type U; Support::writeU16uBE(_cursor, uint32_t(U(val) & 0xFFFFu)); _cursor += 2; } template<typename T> - ASMJIT_INLINE void emit32uLE(T val) noexcept { + ASMJIT_FORCE_INLINE void emit32uLE(T val) noexcept { typedef typename std::make_unsigned<T>::type U; Support::writeU32uLE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu)); _cursor += 4; } template<typename T> - ASMJIT_INLINE void emit32uBE(T val) noexcept { + ASMJIT_FORCE_INLINE void emit32uBE(T val) noexcept { typedef typename std::make_unsigned<T>::type U; Support::writeU32uBE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu)); _cursor += 4; } - ASMJIT_INLINE void emitData(const void* data, size_t size) noexcept { + ASMJIT_FORCE_INLINE void emitData(const void* data, size_t size) noexcept { ASMJIT_ASSERT(size != 0); memcpy(_cursor, data, size); _cursor += size; } template<typename T> - ASMJIT_INLINE void emitValueLE(const T& value, size_t size) noexcept { + ASMJIT_FORCE_INLINE void emitValueLE(const T& value, size_t size) noexcept { typedef typename std::make_unsigned<T>::type U; ASMJIT_ASSERT(size <= sizeof(T)); @@ -137,7 +111,7 @@ public: } template<typename T> - ASMJIT_INLINE void emitValueBE(const T& value, size_t size) noexcept { + ASMJIT_FORCE_INLINE void emitValueBE(const T& value, size_t size) noexcept { typedef typename std::make_unsigned<T>::type U; ASMJIT_ASSERT(size <= sizeof(T)); @@ -149,13 +123,13 @@ public: _cursor += size; } - ASMJIT_INLINE void emitZeros(size_t size) noexcept { + ASMJIT_FORCE_INLINE void emitZeros(size_t size) noexcept { ASMJIT_ASSERT(size != 0); memset(_cursor, 0, size); _cursor += size; } - ASMJIT_INLINE void remove8(uint8_t* where) noexcept { + ASMJIT_FORCE_INLINE void remove8(uint8_t* where) noexcept { ASMJIT_ASSERT(where < _cursor); uint8_t* p = where; @@ -165,7 +139,7 @@ public: } template<typename T> - ASMJIT_INLINE void insert8(uint8_t* where, T val) noexcept { + ASMJIT_FORCE_INLINE void insert8(uint8_t* where, T val) noexcept { uint8_t* p = _cursor; while (p != where) { @@ -177,7 +151,7 @@ public: _cursor++; } - ASMJIT_INLINE void done(BaseAssembler* a) noexcept { + ASMJIT_FORCE_INLINE void done(BaseAssembler* a) noexcept { CodeBuffer& buffer = a->_section->_buffer; size_t newSize = (size_t)(_cursor - a->_bufferData); ASMJIT_ASSERT(newSize <= buffer.capacity()); @@ -187,10 +161,7 @@ public: } }; -// ============================================================================ -// [asmjit::CodeWriterUtils] -// ============================================================================ - +//! Code writer utilities. namespace CodeWriterUtils { bool encodeOffset32(uint32_t* dst, int64_t offset64, const OffsetFormat& format) noexcept; diff --git a/src/asmjit/core/compiler.cpp b/src/asmjit/core/compiler.cpp index 6bd889f..bfa84f3 100644 --- a/src/asmjit/core/compiler.cpp +++ b/src/asmjit/core/compiler.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_COMPILER @@ -35,11 +17,11 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::GlobalConstPoolPass] -// ============================================================================ +// GlobalConstPoolPass +// =================== class GlobalConstPoolPass : public Pass { +public: typedef Pass Base; public: ASMJIT_NONCOPYABLE(GlobalConstPoolPass) @@ -51,53 +33,50 @@ public: // Flush the global constant pool. BaseCompiler* compiler = static_cast<BaseCompiler*>(_cb); - if (compiler->_globalConstPool) { - compiler->addAfter(compiler->_globalConstPool, compiler->lastNode()); - compiler->_globalConstPool = nullptr; + ConstPoolNode* globalConstPool = compiler->_constPools[uint32_t(ConstPoolScope::kGlobal)]; + + if (globalConstPool) { + compiler->addAfter(globalConstPool, compiler->lastNode()); + compiler->_constPools[uint32_t(ConstPoolScope::kGlobal)] = nullptr; } return kErrorOk; } }; -// ============================================================================ -// [asmjit::BaseCompiler - Construction / Destruction] -// ============================================================================ +// BaseCompiler - Construction & Destruction +// ========================================= BaseCompiler::BaseCompiler() noexcept : BaseBuilder(), _func(nullptr), _vRegZone(4096 - Zone::kBlockOverhead), _vRegArray(), - _localConstPool(nullptr), - _globalConstPool(nullptr) { - - _emitterType = uint8_t(kTypeCompiler); - _validationFlags = uint8_t(InstAPI::kValidationFlagVirtRegs); + _constPools { nullptr, nullptr } { + _emitterType = EmitterType::kCompiler; + _validationFlags = ValidationFlags::kEnableVirtRegs; } BaseCompiler::~BaseCompiler() noexcept {} -// ============================================================================ -// [asmjit::BaseCompiler - Function Management] -// ============================================================================ +// BaseCompiler - Function Management +// ================================== -Error BaseCompiler::_newFuncNode(FuncNode** out, const FuncSignature& signature) { +Error BaseCompiler::newFuncNode(FuncNode** out, const FuncSignature& signature) { *out = nullptr; // Create FuncNode together with all the required surrounding nodes. FuncNode* funcNode; ASMJIT_PROPAGATE(_newNodeT<FuncNode>(&funcNode)); - ASMJIT_PROPAGATE(_newLabelNode(&funcNode->_exitNode)); - ASMJIT_PROPAGATE(_newNodeT<SentinelNode>(&funcNode->_end, SentinelNode::kSentinelFuncEnd)); + ASMJIT_PROPAGATE(newLabelNode(&funcNode->_exitNode)); + ASMJIT_PROPAGATE(_newNodeT<SentinelNode>(&funcNode->_end, SentinelType::kFuncEnd)); // Initialize the function's detail info. Error err = funcNode->detail().init(signature, environment()); if (ASMJIT_UNLIKELY(err)) return reportError(err); - // If the Target guarantees greater stack alignment than required by the - // calling convention then override it as we can prevent having to perform - // dynamic stack alignment + // If the Target guarantees greater stack alignment than required by the calling convention + // then override it as we can prevent having to perform dynamic stack alignment uint32_t environmentStackAlignment = _environment.stackAlignment(); if (funcNode->_funcDetail._callConv.naturalStackAlignment() < environmentStackAlignment) @@ -123,13 +102,13 @@ Error BaseCompiler::_newFuncNode(FuncNode** out, const FuncSignature& signature) return kErrorOk; } -Error BaseCompiler::_addFuncNode(FuncNode** out, const FuncSignature& signature) { - ASMJIT_PROPAGATE(_newFuncNode(out, signature)); +Error BaseCompiler::addFuncNode(FuncNode** out, const FuncSignature& signature) { + ASMJIT_PROPAGATE(newFuncNode(out, signature)); addFunc(*out); return kErrorOk; } -Error BaseCompiler::_newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { +Error BaseCompiler::newFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { uint32_t opCount = !o1.isNone() ? 2u : !o0.isNone() ? 1u : 0u; FuncRetNode* node; @@ -143,8 +122,8 @@ Error BaseCompiler::_newRetNode(FuncRetNode** out, const Operand_& o0, const Ope return kErrorOk; } -Error BaseCompiler::_addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { - ASMJIT_PROPAGATE(_newRetNode(out, o0, o1)); +Error BaseCompiler::addFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { + ASMJIT_PROPAGATE(newFuncRetNode(out, o0, o1)); addNode(*out); return kErrorOk; } @@ -169,10 +148,11 @@ Error BaseCompiler::endFunc() { return reportError(DebugUtils::errored(kErrorInvalidState)); // Add the local constant pool at the end of the function (if exists). - if (_localConstPool) { + ConstPoolNode* localConstPool = _constPools[uint32_t(ConstPoolScope::kLocal)]; + if (localConstPool) { setCursor(func->endNode()->prev()); - addNode(_localConstPool); - _localConstPool = nullptr; + addNode(localConstPool); + _constPools[uint32_t(ConstPoolScope::kLocal)] = nullptr; } // Mark as finished. @@ -184,28 +164,12 @@ Error BaseCompiler::endFunc() { return kErrorOk; } -Error BaseCompiler::_setArg(size_t argIndex, size_t valueIndex, const BaseReg& r) { - FuncNode* func = _func; - - if (ASMJIT_UNLIKELY(!func)) - return reportError(DebugUtils::errored(kErrorInvalidState)); - - if (ASMJIT_UNLIKELY(!isVirtRegValid(r))) - return reportError(DebugUtils::errored(kErrorInvalidVirtId)); - - VirtReg* vReg = virtRegByReg(r); - func->setArg(argIndex, valueIndex, vReg); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Function Invocation] -// ============================================================================ +// BaseCompiler - Function Invocation +// ================================== -Error BaseCompiler::_newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) { +Error BaseCompiler::newInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature) { InvokeNode* node; - ASMJIT_PROPAGATE(_newNodeT<InvokeNode>(&node, instId, 0u)); + ASMJIT_PROPAGATE(_newNodeT<InvokeNode>(&node, instId, InstOptions::kNone)); node->setOpCount(1); node->setOp(0, o0); @@ -228,15 +192,14 @@ Error BaseCompiler::_newInvokeNode(InvokeNode** out, uint32_t instId, const Oper return kErrorOk; } -Error BaseCompiler::_addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - ASMJIT_PROPAGATE(_newInvokeNode(out, instId, o0, signature)); +Error BaseCompiler::addInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature) { + ASMJIT_PROPAGATE(newInvokeNode(out, instId, o0, signature)); addNode(*out); return kErrorOk; } -// ============================================================================ -// [asmjit::BaseCompiler - Virtual Registers] -// ============================================================================ +// BaseCompiler - Virtual Registers +// ================================ static void BaseCompiler_assignGenericName(BaseCompiler* self, VirtReg* vReg) { uint32_t index = unsigned(Operand::virtIdToIndex(vReg->_id)); @@ -248,7 +211,7 @@ static void BaseCompiler_assignGenericName(BaseCompiler* self, VirtReg* vReg) { vReg->_name.setData(&self->_dataZone, buf, unsigned(size)); } -Error BaseCompiler::newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name) { +Error BaseCompiler::newVirtReg(VirtReg** out, TypeId typeId, OperandSignature signature, const char* name) { *out = nullptr; uint32_t index = _vRegArray.size(); @@ -262,10 +225,10 @@ Error BaseCompiler::newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signatur if (ASMJIT_UNLIKELY(!vReg)) return reportError(DebugUtils::errored(kErrorOutOfMemory)); - uint32_t size = Type::sizeOf(typeId); + uint32_t size = TypeUtils::sizeOf(typeId); uint32_t alignment = Support::min<uint32_t>(size, 64); - vReg = new(vReg) VirtReg(Operand::indexToVirtId(index), signature, size, alignment, typeId); + vReg = new(vReg) VirtReg(signature, Operand::indexToVirtId(index), size, alignment, typeId); #ifndef ASMJIT_NO_LOGGING if (name && name[0] != '\0') @@ -282,22 +245,22 @@ Error BaseCompiler::newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signatur return kErrorOk; } -Error BaseCompiler::_newReg(BaseReg* out, uint32_t typeId, const char* name) { - RegInfo regInfo; +Error BaseCompiler::_newReg(BaseReg* out, TypeId typeId, const char* name) { + OperandSignature regSignature; out->reset(); - Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info); + Error err = ArchUtils::typeIdToRegSignature(arch(), typeId, &typeId, ®Signature); if (ASMJIT_UNLIKELY(err)) return reportError(err); VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name)); + ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regSignature, name)); - out->_initReg(regInfo.signature(), vReg->id()); + out->_initReg(regSignature, vReg->id()); return kErrorOk; } -Error BaseCompiler::_newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...) { +Error BaseCompiler::_newRegFmt(BaseReg* out, TypeId typeId, const char* fmt, ...) { va_list ap; StringTmp<256> sb; @@ -311,75 +274,72 @@ Error BaseCompiler::_newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, . Error BaseCompiler::_newReg(BaseReg* out, const BaseReg& ref, const char* name) { out->reset(); - RegInfo regInfo; - uint32_t typeId; + OperandSignature regSignature; + TypeId typeId; if (isVirtRegValid(ref)) { VirtReg* vRef = virtRegByReg(ref); typeId = vRef->typeId(); - // NOTE: It's possible to cast one register type to another if it's the - // same register group. However, VirtReg always contains the TypeId that - // was used to create the register. This means that in some cases we may - // end up having different size of `ref` and `vRef`. In such case we - // adjust the TypeId to match the `ref` register type instead of the - // original register type, which should be the expected behavior. - uint32_t typeSize = Type::sizeOf(typeId); + // NOTE: It's possible to cast one register type to another if it's the same register group. However, VirtReg + // always contains the TypeId that was used to create the register. This means that in some cases we may end + // up having different size of `ref` and `vRef`. In such case we adjust the TypeId to match the `ref` register + // type instead of the original register type, which should be the expected behavior. + uint32_t typeSize = TypeUtils::sizeOf(typeId); uint32_t refSize = ref.size(); if (typeSize != refSize) { - if (Type::isInt(typeId)) { + if (TypeUtils::isInt(typeId)) { // GP register - change TypeId to match `ref`, but keep sign of `vRef`. switch (refSize) { - case 1: typeId = Type::kIdI8 | (typeId & 1); break; - case 2: typeId = Type::kIdI16 | (typeId & 1); break; - case 4: typeId = Type::kIdI32 | (typeId & 1); break; - case 8: typeId = Type::kIdI64 | (typeId & 1); break; - default: typeId = Type::kIdVoid; break; + case 1: typeId = TypeId(uint32_t(TypeId::kInt8 ) | (uint32_t(typeId) & 1)); break; + case 2: typeId = TypeId(uint32_t(TypeId::kInt16) | (uint32_t(typeId) & 1)); break; + case 4: typeId = TypeId(uint32_t(TypeId::kInt32) | (uint32_t(typeId) & 1)); break; + case 8: typeId = TypeId(uint32_t(TypeId::kInt64) | (uint32_t(typeId) & 1)); break; + default: typeId = TypeId::kVoid; break; } } - else if (Type::isMmx(typeId)) { + else if (TypeUtils::isMmx(typeId)) { // MMX register - always use 64-bit. - typeId = Type::kIdMmx64; + typeId = TypeId::kMmx64; } - else if (Type::isMask(typeId)) { + else if (TypeUtils::isMask(typeId)) { // Mask register - change TypeId to match `ref` size. switch (refSize) { - case 1: typeId = Type::kIdMask8; break; - case 2: typeId = Type::kIdMask16; break; - case 4: typeId = Type::kIdMask32; break; - case 8: typeId = Type::kIdMask64; break; - default: typeId = Type::kIdVoid; break; + case 1: typeId = TypeId::kMask8; break; + case 2: typeId = TypeId::kMask16; break; + case 4: typeId = TypeId::kMask32; break; + case 8: typeId = TypeId::kMask64; break; + default: typeId = TypeId::kVoid; break; } } else { - // VEC register - change TypeId to match `ref` size, keep vector metadata. - uint32_t elementTypeId = Type::baseOf(typeId); - + // Vector register - change TypeId to match `ref` size, keep vector metadata. + TypeId scalarTypeId = TypeUtils::scalarOf(typeId); switch (refSize) { - case 16: typeId = Type::_kIdVec128Start + (elementTypeId - Type::kIdI8); break; - case 32: typeId = Type::_kIdVec256Start + (elementTypeId - Type::kIdI8); break; - case 64: typeId = Type::_kIdVec512Start + (elementTypeId - Type::kIdI8); break; - default: typeId = Type::kIdVoid; break; + case 16: typeId = TypeUtils::scalarToVector(scalarTypeId, TypeId::_kVec128Start); break; + case 32: typeId = TypeUtils::scalarToVector(scalarTypeId, TypeId::_kVec256Start); break; + case 64: typeId = TypeUtils::scalarToVector(scalarTypeId, TypeId::_kVec512Start); break; + default: typeId = TypeId::kVoid; break; } } - if (typeId == Type::kIdVoid) + if (typeId == TypeId::kVoid) return reportError(DebugUtils::errored(kErrorInvalidState)); } } else { - typeId = ref.type(); + typeId = ArchTraits::byArch(arch()).regTypeToTypeId(ref.type()); } - Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info); + Error err = ArchUtils::typeIdToRegSignature(arch(), typeId, &typeId, ®Signature); if (ASMJIT_UNLIKELY(err)) return reportError(err); VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name)); + ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regSignature, name)); - out->_initReg(regInfo.signature(), vReg->id()); + out->_initReg(regSignature, vReg->id()); return kErrorOk; } @@ -410,14 +370,17 @@ Error BaseCompiler::_newStack(BaseMem* out, uint32_t size, uint32_t alignment, c alignment = 64; VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, 0, 0, name)); + ASMJIT_PROPAGATE(newVirtReg(&vReg, TypeId::kVoid, OperandSignature(0), name)); vReg->_virtSize = size; vReg->_isStack = true; vReg->_alignment = uint8_t(alignment); // Set the memory operand to GPD/GPQ and its id to VirtReg. - *out = BaseMem(BaseMem::Decomposed { _gpRegInfo.type(), vReg->id(), BaseReg::kTypeNone, 0, 0, 0, BaseMem::kSignatureMemRegHomeFlag }); + *out = BaseMem(OperandSignature::fromOpType(OperandType::kMem) | + OperandSignature::fromMemBaseType(_gpSignature.regType()) | + OperandSignature::fromBits(OperandSignature::kMemRegHomeFlag), + vReg->id(), 0, 0); return kErrorOk; } @@ -438,9 +401,8 @@ Error BaseCompiler::setStackSize(uint32_t virtId, uint32_t newSize, uint32_t new if (newAlignment) vReg->_alignment = uint8_t(newAlignment); - // This is required if the RAPass is already running. There is a chance that - // a stack-slot has been already allocated and in that case it has to be - // updated as well, otherwise we would allocate wrong amount of memory. + // This is required if the RAPass is already running. There is a chance that a stack-slot has been already + // allocated and in that case it has to be updated as well, otherwise we would allocate wrong amount of memory. RAWorkReg* workReg = vReg->_workReg; if (workReg && workReg->_stackSlot) { workReg->_stackSlot->_size = vReg->_virtSize; @@ -450,37 +412,26 @@ Error BaseCompiler::setStackSize(uint32_t virtId, uint32_t newSize, uint32_t new return kErrorOk; } -Error BaseCompiler::_newConst(BaseMem* out, uint32_t scope, const void* data, size_t size) { +Error BaseCompiler::_newConst(BaseMem* out, ConstPoolScope scope, const void* data, size_t size) { out->reset(); - ConstPoolNode** pPool; - if (scope == ConstPool::kScopeLocal) - pPool = &_localConstPool; - else if (scope == ConstPool::kScopeGlobal) - pPool = &_globalConstPool; - else + if (uint32_t(scope) > 1) return reportError(DebugUtils::errored(kErrorInvalidArgument)); - if (!*pPool) - ASMJIT_PROPAGATE(_newConstPoolNode(pPool)); + if (!_constPools[uint32_t(scope)]) + ASMJIT_PROPAGATE(newConstPoolNode(&_constPools[uint32_t(scope)])); - ConstPoolNode* pool = *pPool; + ConstPoolNode* pool = _constPools[uint32_t(scope)]; size_t off; Error err = pool->add(data, size, off); if (ASMJIT_UNLIKELY(err)) return reportError(err); - *out = BaseMem(BaseMem::Decomposed { - Label::kLabelTag, // Base type. - pool->labelId(), // Base id. - 0, // Index type. - 0, // Index id. - int32_t(off), // Offset. - uint32_t(size), // Size. - 0 // Flags. - }); - + *out = BaseMem(OperandSignature::fromOpType(OperandType::kMem) | + OperandSignature::fromMemBaseType(RegType::kLabelTag) | + OperandSignature::fromSize(uint32_t(size)), + pool->labelId(), 0, int32_t(off)); return kErrorOk; } @@ -505,11 +456,10 @@ void BaseCompiler::rename(const BaseReg& reg, const char* fmt, ...) { } } -// ============================================================================ -// [asmjit::BaseCompiler - Jump Annotations] -// ============================================================================ +// BaseCompiler - Jump Annotations +// =============================== -Error BaseCompiler::newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation) { +Error BaseCompiler::newJumpNode(JumpNode** out, InstId instId, InstOptions instOptions, const Operand_& o0, JumpAnnotation* annotation) { JumpNode* node = _allocator.allocT<JumpNode>(); uint32_t opCount = 1; @@ -524,8 +474,8 @@ Error BaseCompiler::newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOp return kErrorOk; } -Error BaseCompiler::emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation) { - uint32_t options = instOptions() | forcedInstOptions(); +Error BaseCompiler::emitAnnotatedJump(InstId instId, const Operand_& o0, JumpAnnotation* annotation) { + InstOptions options = instOptions() | forcedInstOptions(); RegOnly extra = extraReg(); const char* comment = inlineComment(); @@ -562,16 +512,15 @@ JumpAnnotation* BaseCompiler::newJumpAnnotation() { return jumpAnnotation; } -// ============================================================================ -// [asmjit::BaseCompiler - Events] -// ============================================================================ +// BaseCompiler - Events +// ===================== Error BaseCompiler::onAttach(CodeHolder* code) noexcept { ASMJIT_PROPAGATE(Base::onAttach(code)); const ArchTraits& archTraits = ArchTraits::byArch(code->arch()); - uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; - _gpRegInfo.setSignature(archTraits.regTypeToSignature(nativeRegType)); + RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64; + _gpSignature = archTraits.regTypeToSignature(nativeRegType); Error err = addPassT<GlobalConstPoolPass>(); if (ASMJIT_UNLIKELY(err)) { @@ -584,8 +533,8 @@ Error BaseCompiler::onAttach(CodeHolder* code) noexcept { Error BaseCompiler::onDetach(CodeHolder* code) noexcept { _func = nullptr; - _localConstPool = nullptr; - _globalConstPool = nullptr; + _constPools[uint32_t(ConstPoolScope::kLocal)] = nullptr; + _constPools[uint32_t(ConstPoolScope::kGlobal)] = nullptr; _vRegArray.reset(); _vRegZone.reset(); @@ -593,32 +542,30 @@ Error BaseCompiler::onDetach(CodeHolder* code) noexcept { return Base::onDetach(code); } -// ============================================================================ -// [asmjit::FuncPass - Construction / Destruction] -// ============================================================================ +// FuncPass - Construction & Destruction +// ===================================== FuncPass::FuncPass(const char* name) noexcept : Pass(name) {} -// ============================================================================ -// [asmjit::FuncPass - Run] -// ============================================================================ +// FuncPass - Run +// ============== Error FuncPass::run(Zone* zone, Logger* logger) { BaseNode* node = cb()->firstNode(); if (!node) return kErrorOk; do { - if (node->type() == BaseNode::kNodeFunc) { + if (node->type() == NodeType::kFunc) { FuncNode* func = node->as<FuncNode>(); node = func->endNode(); ASMJIT_PROPAGATE(runOnFunction(zone, logger, func)); } - // Find a function by skipping all nodes that are not `kNodeFunc`. + // Find a function by skipping all nodes that are not `NodeType::kFunc`. do { node = node->next(); - } while (node && node->type() != BaseNode::kNodeFunc); + } while (node && node->type() != NodeType::kFunc); } while (node); return kErrorOk; diff --git a/src/asmjit/core/compiler.h b/src/asmjit/core/compiler.h index 4c4cd33..1331e62 100644 --- a/src/asmjit/core/compiler.h +++ b/src/asmjit/core/compiler.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_COMPILER_H_INCLUDED #define ASMJIT_CORE_COMPILER_H_INCLUDED @@ -40,10 +22,6 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class JumpAnnotation; class JumpNode; class FuncNode; @@ -53,25 +31,18 @@ class InvokeNode; //! \addtogroup asmjit_compiler //! \{ -// ============================================================================ -// [asmjit::BaseCompiler] -// ============================================================================ - //! Code emitter that uses virtual registers and performs register allocation. //! -//! Compiler is a high-level code-generation tool that provides register -//! allocation and automatic handling of function calling conventions. It was -//! primarily designed for merging multiple parts of code into a function -//! without worrying about registers and function calling conventions. +//! Compiler is a high-level code-generation tool that provides register allocation and automatic handling of function +//! calling conventions. It was primarily designed for merging multiple parts of code into a function without worrying +//! about registers and function calling conventions. //! -//! BaseCompiler can be used, with a minimum effort, to handle 32-bit and -//! 64-bit code generation within a single code base. +//! BaseCompiler can be used, with a minimum effort, to handle 32-bit and 64-bit code generation within a single code +//! base. //! -//! BaseCompiler is based on BaseBuilder and contains all the features it -//! provides. It means that the code it stores can be modified (removed, added, -//! injected) and analyzed. When the code is finalized the compiler can emit -//! the code into an Assembler to translate the abstract representation into a -//! machine code. +//! BaseCompiler is based on BaseBuilder and contains all the features it provides. It means that the code it stores +//! can be modified (removed, added, injected) and analyzed. When the code is finalized the compiler can emit the code +//! into an Assembler to translate the abstract representation into a machine code. //! //! Check out architecture specific compilers for more details and examples: //! @@ -81,6 +52,9 @@ public: ASMJIT_NONCOPYABLE(BaseCompiler) typedef BaseBuilder Base; + //! \name Members + //! \{ + //! Current function. FuncNode* _func; //! Allocates `VirtReg` objects. @@ -90,10 +64,12 @@ public: //! Stores jump annotations. ZoneVector<JumpAnnotation*> _jumpAnnotations; - //! Local constant pool, flushed at the end of each function. - ConstPoolNode* _localConstPool; - //! Global constant pool, flushed by `finalize()`. - ConstPoolNode* _globalConstPool; + //! Local and global constant pools. + //! + //! Local constant pool is flushed with each function, global constant pool is flushed only by \ref finalize(). + ConstPoolNode* _constPools[2]; + + //! \} //! \name Construction & Destruction //! \{ @@ -108,31 +84,31 @@ public: //! \name Function Management //! \{ - //! Returns the current function. - inline FuncNode* func() const noexcept { return _func; } - //! Creates a new \ref FuncNode. - ASMJIT_API Error _newFuncNode(FuncNode** out, const FuncSignature& signature); - //! Creates a new \ref FuncNode adds it to the compiler. - ASMJIT_API Error _addFuncNode(FuncNode** out, const FuncSignature& signature); + ASMJIT_API Error newFuncNode(FuncNode** out, const FuncSignature& signature); + //! Creates a new \ref FuncNode adds it to the instruction stream. + ASMJIT_API Error addFuncNode(FuncNode** out, const FuncSignature& signature); //! Creates a new \ref FuncRetNode. - ASMJIT_API Error _newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); - //! Creates a new \ref FuncRetNode and adds it to the compiler. - ASMJIT_API Error _addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); + ASMJIT_API Error newFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); + //! Creates a new \ref FuncRetNode and adds it to the instruction stream. + ASMJIT_API Error addFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); + + //! Returns the current function. + inline FuncNode* func() const noexcept { return _func; } //! Creates a new \ref FuncNode with the given `signature` and returns it. inline FuncNode* newFunc(const FuncSignature& signature) { FuncNode* node; - _newFuncNode(&node, signature); + newFuncNode(&node, signature); return node; } - //! Creates a new \ref FuncNode with the given `signature`, adds it to the - //! compiler by using the \ref addFunc(FuncNode*) overload, and returns it. + //! Creates a new \ref FuncNode with the given `signature`, adds it to the instruction stream by using + //! the \ref addFunc(FuncNode*) overload, and returns it. inline FuncNode* addFunc(const FuncSignature& signature) { FuncNode* node; - _addFuncNode(&node, signature); + addFuncNode(&node, signature); return node; } @@ -141,23 +117,21 @@ public: //! Emits a sentinel that marks the end of the current function. ASMJIT_API Error endFunc(); - ASMJIT_API Error _setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg); +#if !defined(ASMJIT_NO_DEPRECATED) + inline Error _setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg); //! Sets a function argument at `argIndex` to `reg`. + ASMJIT_DEPRECATED("Setting arguments through Compiler is deprecated, use FuncNode->setArg() instead") inline Error setArg(size_t argIndex, const BaseReg& reg) { return _setArg(argIndex, 0, reg); } + //! Sets a function argument at `argIndex` at `valueIndex` to `reg`. + ASMJIT_DEPRECATED("Setting arguments through Compiler is deprecated, use FuncNode->setArg() instead") inline Error setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) { return _setArg(argIndex, valueIndex, reg); } +#endif - inline FuncRetNode* newRet(const Operand_& o0, const Operand_& o1) { + inline Error addRet(const Operand_& o0, const Operand_& o1) { FuncRetNode* node; - _newRetNode(&node, o0, o1); - return node; - } - - inline FuncRetNode* addRet(const Operand_& o0, const Operand_& o1) { - FuncRetNode* node; - _addRetNode(&node, o0, o1); - return node; + return addFuncRetNode(&node, o0, o1); } //! \} @@ -166,23 +140,9 @@ public: //! \{ //! Creates a new \ref InvokeNode. - ASMJIT_API Error _newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature); - //! Creates a new \ref InvokeNode and adds it to Compiler. - ASMJIT_API Error _addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature); - - //! Creates a new `InvokeNode`. - inline InvokeNode* newCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - _newInvokeNode(&node, instId, o0, signature); - return node; - } - - //! Adds a new `InvokeNode`. - inline InvokeNode* addCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - _addInvokeNode(&node, instId, o0, signature); - return node; - } + ASMJIT_API Error newInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature); + //! Creates a new \ref InvokeNode and adds it to the instruction stream. + ASMJIT_API Error addInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature); //! \} @@ -191,18 +151,17 @@ public: //! Creates a new virtual register representing the given `typeId` and `signature`. //! - //! \note This function is public, but it's not generally recommended to be used - //! by AsmJit users, use architecture-specific `newReg()` functionality instead - //! or functions like \ref _newReg() and \ref _newRegFmt(). - ASMJIT_API Error newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name); + //! \note This function is public, but it's not generally recommended to be used by AsmJit users, use architecture + //! specific `newReg()` functionality instead or functions like \ref _newReg() and \ref _newRegFmt(). + ASMJIT_API Error newVirtReg(VirtReg** out, TypeId typeId, OperandSignature signature, const char* name); //! Creates a new virtual register of the given `typeId` and stores it to `out` operand. - ASMJIT_API Error _newReg(BaseReg* out, uint32_t typeId, const char* name = nullptr); + ASMJIT_API Error _newReg(BaseReg* out, TypeId typeId, const char* name = nullptr); //! Creates a new virtual register of the given `typeId` and stores it to `out` operand. //! //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. - ASMJIT_API Error _newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...); + ASMJIT_API Error _newRegFmt(BaseReg* out, TypeId typeId, const char* fmt, ...); //! Creates a new virtual register compatible with the provided reference register `ref`. ASMJIT_API Error _newReg(BaseReg* out, const BaseReg& ref, const char* name = nullptr); @@ -233,9 +192,8 @@ public: //! Returns \ref VirtReg associated with the given virtual register `index`. //! - //! \note This is not the same as virtual register id. The conversion between - //! id and its index is implemented by \ref Operand_::virtIdToIndex() and \ref - //! Operand_::indexToVirtId() functions. + //! \note This is not the same as virtual register id. The conversion between id and its index is implemented + //! by \ref Operand_::virtIdToIndex() and \ref Operand_::indexToVirtId() functions. inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; } //! Returns an array of all virtual registers managed by the Compiler. @@ -262,11 +220,11 @@ public: //! \name Constants //! \{ - //! Creates a new constant of the given `scope` (see \ref ConstPool::Scope). + //! Creates a new constant of the given `scope` (see \ref ConstPoolScope). //! - //! This function adds a constant of the given `size` to the built-in \ref - //! ConstPool and stores the reference to that constant to the `out` operand. - ASMJIT_API Error _newConst(BaseMem* out, uint32_t scope, const void* data, size_t size); + //! This function adds a constant of the given `size` to the built-in \ref ConstPool and stores the reference to that + //! constant to the `out` operand. + ASMJIT_API Error _newConst(BaseMem* out, ConstPoolScope scope, const void* data, size_t size); //! \} @@ -285,23 +243,15 @@ public: return _jumpAnnotations; } - ASMJIT_API Error newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation); - ASMJIT_API Error emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation); + ASMJIT_API Error newJumpNode(JumpNode** out, InstId instId, InstOptions instOptions, const Operand_& o0, JumpAnnotation* annotation); + ASMJIT_API Error emitAnnotatedJump(InstId instId, const Operand_& o0, JumpAnnotation* annotation); - //! Returns a new `JumpAnnotation` instance, which can be used to aggregate - //! possible targets of a jump where the target is not a label, for example - //! to implement jump tables. + //! Returns a new `JumpAnnotation` instance, which can be used to aggregate possible targets of a jump where the + //! target is not a label, for example to implement jump tables. ASMJIT_API JumpAnnotation* newJumpAnnotation(); //! \} -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("alloc() has no effect, it will be removed in the future") - inline void alloc(BaseReg&) {} - ASMJIT_DEPRECATED("spill() has no effect, it will be removed in the future") - inline void spill(BaseReg&) {} -#endif // !ASMJIT_NO_DEPRECATED - //! \name Events //! \{ @@ -311,22 +261,19 @@ public: //! \} }; -// ============================================================================ -// [asmjit::JumpAnnotation] -// ============================================================================ - //! Jump annotation used to annotate jumps. //! -//! \ref BaseCompiler allows to emit jumps where the target is either register -//! or memory operand. Such jumps cannot be trivially inspected, so instead of -//! doing heuristics AsmJit allows to annotate such jumps with possible targets. -//! Register allocator then use the annotation to construct control-flow, which -//! is then used by liveness analysis and other tools to prepare ground for -//! register allocation. +//! \ref BaseCompiler allows to emit jumps where the target is either register or memory operand. Such jumps cannot be +//! trivially inspected, so instead of doing heuristics AsmJit allows to annotate such jumps with possible targets. +//! Register allocator then uses the annotation to construct control-flow, which is then used by liveness analysis and +//! other tools to prepare ground for register allocation. class JumpAnnotation { public: ASMJIT_NONCOPYABLE(JumpAnnotation) + //! \name Members + //! \{ + //! Compiler that owns this JumpAnnotation. BaseCompiler* _compiler; //! Annotation identifier. @@ -334,10 +281,20 @@ public: //! Vector of label identifiers, see \ref labelIds(). ZoneVector<uint32_t> _labelIds; + //! \} + + //! \name Construction & Destruction + //! \{ + inline JumpAnnotation(BaseCompiler* compiler, uint32_t annotationId) noexcept : _compiler(compiler), _annotationId(annotationId) {} + //! \} + + //! \name Accessors + //! \{ + //! Returns the compiler that owns this JumpAnnotation. inline BaseCompiler* compiler() const noexcept { return _compiler; } //! Returns the annotation id. @@ -350,35 +307,42 @@ public: //! Tests whether the given `labelId` is a target of this JumpAnnotation. inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); } + //! \} + + //! \name Annotation Building API + //! \{ + //! Adds the `label` to the list of targets of this JumpAnnotation. inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); } //! Adds the `labelId` to the list of targets of this JumpAnnotation. inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); } -}; -// ============================================================================ -// [asmjit::JumpNode] -// ============================================================================ + //! \} +}; //! Jump instruction with \ref JumpAnnotation. //! -//! \note This node should be only used to represent jump where the jump target -//! cannot be deduced by examining instruction operands. For example if the jump -//! target is register or memory location. This pattern is often used to perform -//! indirect jumps that use jump table, e.g. to implement `switch{}` statement. +//! \note This node should be only used to represent jump where the jump target cannot be deduced by examining +//! instruction operands. For example if the jump target is register or memory location. This pattern is often +//! used to perform indirect jumps that use jump table, e.g. to implement `switch{}` statement. class JumpNode : public InstNode { public: ASMJIT_NONCOPYABLE(JumpNode) + //! \name Members + //! \{ + JumpAnnotation* _annotation; + //! \} + //! \name Construction & Destruction //! \{ - ASMJIT_INLINE JumpNode(BaseCompiler* cc, uint32_t instId, uint32_t options, uint32_t opCount, JumpAnnotation* annotation) noexcept + inline JumpNode(BaseCompiler* cc, InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept : InstNode(cc, instId, options, opCount, kBaseOpCapacity), _annotation(annotation) { - setType(kNodeJump); + setType(NodeType::kJump); } //! \} @@ -396,31 +360,24 @@ public: //! \} }; -// ============================================================================ -// [asmjit::FuncNode] -// ============================================================================ - //! Function node represents a function used by \ref BaseCompiler. //! //! A function is composed of the following: //! -//! - Function entry, \ref FuncNode acts as a label, so the entry is implicit. -//! To get the entry, simply use \ref FuncNode::label(), which is the same -//! as \ref LabelNode::label(). +//! - Function entry, \ref FuncNode acts as a label, so the entry is implicit. To get the entry, simply use +//! \ref FuncNode::label(), which is the same as \ref LabelNode::label(). //! -//! - Function exit, which is represented by \ref FuncNode::exitNode(). A -//! helper function \ref FuncNode::exitLabel() exists and returns an exit -//! label instead of node. +//! - Function exit, which is represented by \ref FuncNode::exitNode(). A helper function +//! \ref FuncNode::exitLabel() exists and returns an exit label instead of node. //! -//! - Function \ref FuncNode::endNode() sentinel. This node marks the end of -//! a function - there should be no code that belongs to the function after -//! this node, but the Compiler doesn't enforce that at the moment. +//! - Function \ref FuncNode::endNode() sentinel. This node marks the end of a function - there should be no +//! code that belongs to the function after this node, but the Compiler doesn't enforce that at the moment. //! //! - Function detail, see \ref FuncNode::detail(). //! //! - Function frame, see \ref FuncNode::frame(). //! -//! - Function arguments mapped to virtual registers, see \ref FuncNode::args(). +//! - Function arguments mapped to virtual registers, see \ref FuncNode::argPacks(). //! //! In a node list, the function and its body looks like the following: //! @@ -439,29 +396,30 @@ public: //! [...] - Anything after the function. //! \endcode //! -//! When a function is added to the compiler by \ref BaseCompiler::addFunc() it -//! actually inserts 3 nodes (FuncNode, ExitLabel, and FuncEnd) and sets the -//! current cursor to be FuncNode. When \ref BaseCompiler::endFunc() is called -//! the cursor is set to FuncEnd. This guarantees that user can use ExitLabel -//! as a marker after additional code or data can be placed, and it's a common -//! practice. +//! When a function is added to the instruction stream by \ref BaseCompiler::addFunc() it actually inserts 3 nodes +//! (FuncNode, ExitLabel, and FuncEnd) and sets the current cursor to be FuncNode. When \ref BaseCompiler::endFunc() +//! is called the cursor is set to FuncEnd. This guarantees that user can use ExitLabel as a marker after additional +//! code or data can be placed, which is a common practice. class FuncNode : public LabelNode { public: ASMJIT_NONCOPYABLE(FuncNode) //! Arguments pack. struct ArgPack { - VirtReg* _data[Globals::kMaxValuePack]; + RegOnly _data[Globals::kMaxValuePack]; inline void reset() noexcept { for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) - _data[valueIndex] = nullptr; + _data[valueIndex].reset(); } - inline VirtReg*& operator[](size_t valueIndex) noexcept { return _data[valueIndex]; } - inline VirtReg* const& operator[](size_t valueIndex) const noexcept { return _data[valueIndex]; } + inline RegOnly& operator[](size_t valueIndex) noexcept { return _data[valueIndex]; } + inline const RegOnly& operator[](size_t valueIndex) const noexcept { return _data[valueIndex]; } }; + //! \name Members + //! \{ + //! Function detail. FuncDetail _funcDetail; //! Function frame. @@ -470,24 +428,25 @@ public: LabelNode* _exitNode; //! Function end (sentinel). SentinelNode* _end; - //! Argument packs. ArgPack* _args; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `FuncNode` instance. //! - //! Always use `BaseCompiler::addFunc()` to create `FuncNode`. - ASMJIT_INLINE FuncNode(BaseBuilder* cb) noexcept + //! Always use `BaseCompiler::addFunc()` to create a new `FuncNode`. + inline FuncNode(BaseBuilder* cb) noexcept : LabelNode(cb), _funcDetail(), _frame(), _exitNode(nullptr), _end(nullptr), _args(nullptr) { - setType(kNodeFunc); + setType(NodeType::kFunc); } //! \} @@ -500,12 +459,12 @@ public: //! Returns function exit label. inline Label exitLabel() const noexcept { return _exitNode->label(); } - //! Returns "End of Func" sentinel. + //! Returns "End of Func" sentinel node. inline SentinelNode* endNode() const noexcept { return _end; } - //! Returns function declaration. + //! Returns function detail. inline FuncDetail& detail() noexcept { return _funcDetail; } - //! Returns function declaration. + //! Returns function detail. inline const FuncDetail& detail() const noexcept { return _funcDetail; } //! Returns function frame. @@ -513,14 +472,19 @@ public: //! Returns function frame. inline const FuncFrame& frame() const noexcept { return _frame; } - //! Tests whether the function has a return value. - inline bool hasRet() const noexcept { return _funcDetail.hasRet(); } + //! Returns function attributes. + inline FuncAttributes attributes() const noexcept { return _frame.attributes(); } + //! Adds `attrs` to the function attributes. + inline void addAttributes(FuncAttributes attrs) noexcept { _frame.addAttributes(attrs); } + //! Returns arguments count. inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } - //! Returns argument packs. inline ArgPack* argPacks() const noexcept { return _args; } + //! Tests whether the function has a return value. + inline bool hasRet() const noexcept { return _funcDetail.hasRet(); } + //! Returns argument pack at `argIndex`. inline ArgPack& argPack(size_t argIndex) const noexcept { ASMJIT_ASSERT(argIndex < argCount()); @@ -528,15 +492,27 @@ public: } //! Sets argument at `argIndex`. - inline void setArg(size_t argIndex, VirtReg* vReg) noexcept { + inline void setArg(size_t argIndex, const BaseReg& vReg) noexcept { + ASMJIT_ASSERT(argIndex < argCount()); + _args[argIndex][0].init(vReg); + } + + //! \overload + inline void setArg(size_t argIndex, const RegOnly& vReg) noexcept { ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][0] = vReg; + _args[argIndex][0].init(vReg); } //! Sets argument at `argIndex` and `valueIndex`. - inline void setArg(size_t argIndex, size_t valueIndex, VirtReg* vReg) noexcept { + inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& vReg) noexcept { ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][valueIndex] = vReg; + _args[argIndex][valueIndex].init(vReg); + } + + //! \overload + inline void setArg(size_t argIndex, size_t valueIndex, const RegOnly& vReg) noexcept { + ASMJIT_ASSERT(argIndex < argCount()); + _args[argIndex][valueIndex].init(vReg); } //! Resets argument pack at `argIndex`. @@ -548,21 +524,12 @@ public: //! Resets argument pack at `argIndex`. inline void resetArg(size_t argIndex, size_t valueIndex) noexcept { ASMJIT_ASSERT(argIndex < argCount()); - _args[argIndex][valueIndex] = nullptr; + _args[argIndex][valueIndex].reset(); } - //! Returns function attributes. - inline uint32_t attributes() const noexcept { return _frame.attributes(); } - //! Adds `attrs` to the function attributes. - inline void addAttributes(uint32_t attrs) noexcept { _frame.addAttributes(attrs); } - //! \} }; -// ============================================================================ -// [asmjit::FuncRetNode] -// ============================================================================ - //! Function return, used by \ref BaseCompiler. class FuncRetNode : public InstNode { public: @@ -572,27 +539,21 @@ public: //! \{ //! Creates a new `FuncRetNode` instance. - inline FuncRetNode(BaseBuilder* cb) noexcept : InstNode(cb, BaseInst::kIdAbstract, 0, 0) { - _any._nodeType = kNodeFuncRet; + inline FuncRetNode(BaseBuilder* cb) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { + _any._nodeType = NodeType::kFuncRet; } //! \} }; -// ============================================================================ -// [asmjit::InvokeNode] -// ============================================================================ - //! Function invocation, used by \ref BaseCompiler. class InvokeNode : public InstNode { public: ASMJIT_NONCOPYABLE(InvokeNode) - //! Operand pack provides multiple operands that can be associated with a - //! single return value of function argument. Sometimes this is necessary to - //! express an argument or return value that requires multiple registers, for - //! example 64-bit value in 32-bit mode or passing / returning homogeneous data - //! structures. + //! Operand pack provides multiple operands that can be associated with a single return value of function + //! argument. Sometims this is necessary to express an argument or return value that requires multiple + //! registers, for example 64-bit value in 32-bit mode or passing / returning homogeneous data structures. struct OperandPack { //! Operands. Operand_ _data[Globals::kMaxValuePack]; @@ -616,6 +577,9 @@ public: } }; + //! \name Members + //! \{ + //! Function detail. FuncDetail _funcDetail; //! Function return value(s). @@ -623,18 +587,20 @@ public: //! Function arguments. OperandPack* _args; + //! \} + //! \name Construction & Destruction //! \{ //! Creates a new `InvokeNode` instance. - inline InvokeNode(BaseBuilder* cb, uint32_t instId, uint32_t options) noexcept + inline InvokeNode(BaseBuilder* cb, InstId instId, InstOptions options) noexcept : InstNode(cb, instId, options, kBaseOpCapacity), _funcDetail(), _args(nullptr) { - setType(kNodeInvoke); + setType(NodeType::kInvoke); _resetOps(); _rets.reset(); - addFlags(kFlagIsRemovable); + addFlags(NodeFlags::kIsRemovable); } //! \} @@ -718,10 +684,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::FuncPass] -// ============================================================================ - //! Function pass extends \ref Pass with \ref FuncPass::runOnFunction(). class ASMJIT_VIRTAPI FuncPass : public Pass { public: @@ -743,7 +705,7 @@ public: //! \} - //! \name Run + //! \name Pass Interface //! \{ //! Calls `runOnFunction()` on each `FuncNode` node found. @@ -755,6 +717,18 @@ public: //! \} }; +#if !defined(ASMJIT_NO_DEPRECATED) +inline Error BaseCompiler::_setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) { + FuncNode* func = _func; + + if (ASMJIT_UNLIKELY(!func)) + return reportError(DebugUtils::errored(kErrorInvalidState)); + + func->setArg(argIndex, valueIndex, reg); + return kErrorOk; +} +#endif + //! \} ASMJIT_END_NAMESPACE diff --git a/src/asmjit/core/compilerdefs.h b/src/asmjit/core/compilerdefs.h index 32f0757..f2e7a4e 100644 --- a/src/asmjit/core/compilerdefs.h +++ b/src/asmjit/core/compilerdefs.h @@ -1,63 +1,41 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_COMPILERDEFS_H_INCLUDED #define ASMJIT_CORE_COMPILERDEFS_H_INCLUDED #include "../core/api-config.h" #include "../core/operand.h" +#include "../core/type.h" #include "../core/zonestring.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class RAWorkReg; //! \addtogroup asmjit_compiler //! \{ -// ============================================================================ -// [asmjit::VirtReg] -// ============================================================================ - //! Virtual register data, managed by \ref BaseCompiler. class VirtReg { public: ASMJIT_NONCOPYABLE(VirtReg) + //! \name Members + //! \{ + + //! Virtual register signature. + OperandSignature _signature {}; //! Virtual register id. uint32_t _id = 0; - //! Virtual register info (signature). - RegInfo _info = {}; - //! Virtual register size (can be smaller than `regInfo._size`). + //! Virtual register size (can be smaller than `_signature._size`). uint32_t _virtSize = 0; //! Virtual register alignment (for spilling). uint8_t _alignment = 0; //! Type-id. - uint8_t _typeId = 0; + TypeId _typeId = TypeId::kVoid; //! Virtual register weight for alloc/spill decisions. uint8_t _weight = 1; //! True if this is a fixed register, never reallocated. @@ -69,24 +47,23 @@ public: //! Virtual register name (user provided or automatically generated). ZoneString<16> _name {}; - // ------------------------------------------------------------------------- - // The following members are used exclusively by RAPass. They are initialized - // when the VirtReg is created to NULL pointers and then changed during RAPass - // execution. RAPass sets them back to NULL before it returns. - // ------------------------------------------------------------------------- + // The following members are used exclusively by RAPass. They are initialized when the VirtReg is created to + // null pointers and then changed during RAPass execution. RAPass sets them back to NULL before it returns. //! Reference to `RAWorkReg`, used during register allocation. RAWorkReg* _workReg = nullptr; + //! \} + //! \name Construction & Destruction //! \{ - inline VirtReg(uint32_t id, uint32_t signature, uint32_t virtSize, uint32_t alignment, uint32_t typeId) noexcept - : _id(id), - _info { signature }, + inline VirtReg(const OperandSignature& signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept + : _signature(signature), + _id(id), _virtSize(virtSize), _alignment(uint8_t(alignment)), - _typeId(uint8_t(typeId)), + _typeId(typeId), _isFixed(false), _isStack(false), _reserved(0) {} @@ -104,56 +81,50 @@ public: //! Returns the size of the virtual register name. inline uint32_t nameSize() const noexcept { return _name.size(); } - //! Returns a register information that wraps the register signature. - inline const RegInfo& info() const noexcept { return _info; } + //! Returns a register signature of this virtual register. + inline OperandSignature signature() const noexcept { return _signature; } //! Returns a virtual register type (maps to the physical register type as well). - inline uint32_t type() const noexcept { return _info.type(); } + inline RegType type() const noexcept { return _signature.regType(); } //! Returns a virtual register group (maps to the physical register group as well). - inline uint32_t group() const noexcept { return _info.group(); } + inline RegGroup group() const noexcept { return _signature.regGroup(); } //! Returns a real size of the register this virtual register maps to. //! - //! For example if this is a 128-bit SIMD register used for a scalar single - //! precision floating point value then its virtSize would be 4, however, the - //! `regSize` would still say 16 (128-bits), because it's the smallest size + //! For example if this is a 128-bit SIMD register used for a scalar single precision floating point value then + //! its virtSize would be 4, however, the `regSize` would still say 16 (128-bits), because it's the smallest size //! of that register type. - inline uint32_t regSize() const noexcept { return _info.size(); } - - //! Returns a register signature of this virtual register. - inline uint32_t signature() const noexcept { return _info.signature(); } + inline uint32_t regSize() const noexcept { return _signature.size(); } //! Returns the virtual register size. //! - //! The virtual register size describes how many bytes the virtual register - //! needs to store its content. It can be smaller than the physical register - //! size, see `regSize()`. + //! The virtual register size describes how many bytes the virtual register needs to store its content. It can be + //! smaller than the physical register size, see `regSize()`. inline uint32_t virtSize() const noexcept { return _virtSize; } //! Returns the virtual register alignment. inline uint32_t alignment() const noexcept { return _alignment; } - //! Returns the virtual register type id, see `Type::Id`. - inline uint32_t typeId() const noexcept { return _typeId; } + //! Returns the virtual register type id. + inline TypeId typeId() const noexcept { return _typeId; } - //! Returns the virtual register weight - the register allocator can use it - //! as explicit hint for alloc/spill decisions. + //! Returns the virtual register weight - the register allocator can use it as explicit hint for alloc/spill + //! decisions. inline uint32_t weight() const noexcept { return _weight; } - //! Sets the virtual register weight (0 to 255) - the register allocator can - //! use it as explicit hint for alloc/spill decisions and initial bin-packing. + //! Sets the virtual register weight (0 to 255) - the register allocator can use it as explicit hint for + //! alloc/spill decisions and initial bin-packing. inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } - //! Returns whether the virtual register is always allocated to a fixed - //! physical register (and never reallocated). + //! Returns whether the virtual register is always allocated to a fixed physical register (and never reallocated). //! //! \note This is only used for special purposes and it's mostly internal. inline bool isFixed() const noexcept { return bool(_isFixed); } - //! Returns whether the virtual register is indeed a stack that only uses - //! the virtual register id for making it accessible. + //! Tests whether the virtual register is in fact a stack that only uses the virtual register id. //! //! \note It's an error if a stack is accessed as a register. inline bool isStack() const noexcept { return bool(_isStack); } + //! Tests whether the virtual register has an associated `RAWorkReg` at the moment. inline bool hasWorkReg() const noexcept { return _workReg != nullptr; } inline RAWorkReg* workReg() const noexcept { return _workReg; } inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } diff --git a/src/asmjit/core/constpool.cpp b/src/asmjit/core/constpool.cpp index 84d7cd3..ad5fe4f 100644 --- a/src/asmjit/core/constpool.cpp +++ b/src/asmjit/core/constpool.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/constpool.h" @@ -27,16 +9,14 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ConstPool - Construction / Destruction] -// ============================================================================ +// ConstPool - Construction & Destruction +// ====================================== ConstPool::ConstPool(Zone* zone) noexcept { reset(zone); } ConstPool::~ConstPool() noexcept {} -// ============================================================================ -// [asmjit::ConstPool - Reset] -// ============================================================================ +// ConstPool - Reset +// ================= void ConstPool::reset(Zone* zone) noexcept { _zone = zone; @@ -55,11 +35,10 @@ void ConstPool::reset(Zone* zone) noexcept { _minItemSize = 0; } -// ============================================================================ -// [asmjit::ConstPool - Ops] -// ============================================================================ +// ConstPool - Operations +// ====================== -static ASMJIT_INLINE ConstPool::Gap* ConstPool_allocGap(ConstPool* self) noexcept { +static inline ConstPool::Gap* ConstPool_allocGap(ConstPool* self) noexcept { ConstPool::Gap* gap = self->_gapPool; if (!gap) return self->_zone->allocT<ConstPool::Gap>(); @@ -68,7 +47,7 @@ static ASMJIT_INLINE ConstPool::Gap* ConstPool_allocGap(ConstPool* self) noexcep return gap; } -static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPool::Gap* gap) noexcept { +static inline void ConstPool_freeGap(ConstPool* self, ConstPool::Gap* gap) noexcept { gap->_next = self->_gapPool; self->_gapPool = gap; } @@ -80,7 +59,11 @@ static void ConstPool_addGap(ConstPool* self, size_t offset, size_t size) noexce size_t gapIndex; size_t gapSize; - if (size >= 16 && Support::isAligned<size_t>(offset, 16)) { + if (size >= 32 && Support::isAligned<size_t>(offset, 32)) { + gapIndex = ConstPool::kIndex32; + gapSize = 32; + } + else if (size >= 16 && Support::isAligned<size_t>(offset, 16)) { gapIndex = ConstPool::kIndex16; gapSize = 16; } @@ -101,9 +84,8 @@ static void ConstPool_addGap(ConstPool* self, size_t offset, size_t size) noexce gapSize = 1; } - // We don't have to check for errors here, if this failed nothing really - // happened (just the gap won't be visible) and it will fail again at - // place where the same check would generate `kErrorOutOfMemory` error. + // We don't have to check for errors here, if this failed nothing really happened (just the gap won't be + // visible) and it will fail again at place where the same check would generate `kErrorOutOfMemory` error. ConstPool::Gap* gap = ConstPool_allocGap(self); if (!gap) return; @@ -122,7 +104,9 @@ static void ConstPool_addGap(ConstPool* self, size_t offset, size_t size) noexce Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept { size_t treeIndex; - if (size == 32) + if (size == 64) + treeIndex = kIndex64; + else if (size == 32) treeIndex = kIndex32; else if (size == 16) treeIndex = kIndex16; @@ -143,8 +127,7 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept return kErrorOk; } - // Before incrementing the current offset try if there is a gap that can - // be used for the requested data. + // Before incrementing the current offset try if there is a gap that can be used for the requested data. size_t offset = ~size_t(0); size_t gapIndex = treeIndex; @@ -172,8 +155,7 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept } if (offset == ~size_t(0)) { - // Get how many bytes have to be skipped so the address is aligned accordingly - // to the 'size'. + // Get how many bytes have to be skipped so the address is aligned accordingly to the 'size'. size_t diff = Support::alignUpDiff<size_t>(_size, size); if (diff != 0) { @@ -195,9 +177,8 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept dstOffset = offset; - // Now create a bunch of shared constants that are based on the data pattern. - // We stop at size 4, it probably doesn't make sense to split constants down - // to 1 byte. + // Now create a bunch of shared constants that are based on the data pattern. We stop at size 4, + // it probably doesn't make sense to split constants down to 1 byte. size_t pCount = 1; size_t smallerSize = size; @@ -226,9 +207,8 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept return kErrorOk; } -// ============================================================================ -// [asmjit::ConstPool - Reset] -// ============================================================================ +// ConstPool - Reset +// ================= struct ConstPoolFill { inline ConstPoolFill(uint8_t* dst, size_t dataSize) noexcept : @@ -255,9 +235,8 @@ void ConstPool::fill(void* dst) const noexcept { } } -// ============================================================================ -// [asmjit::ConstPool - Unit] -// ============================================================================ +// ConstPool - Tests +// ================= #if defined(ASMJIT_TEST) UNIT(const_pool) { diff --git a/src/asmjit/core/constpool.h b/src/asmjit/core/constpool.h index fc0e0bc..32b84b1 100644 --- a/src/asmjit/core/constpool.h +++ b/src/asmjit/core/constpool.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_CONSTPOOL_H_INCLUDED #define ASMJIT_CORE_CONSTPOOL_H_INCLUDED @@ -33,23 +15,22 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_utilities //! \{ -// ============================================================================ -// [asmjit::ConstPool] -// ============================================================================ +//! Constant pool scope. +enum class ConstPoolScope : uint32_t { + //! Local constant, always embedded right after the current function. + kLocal = 0, + //! Global constant, embedded at the end of the currently compiled code. + kGlobal = 1, + + //! Maximum value of `ConstPoolScope`. + kMaxValue = kGlobal +}; //! Constant pool. class ConstPool { public: ASMJIT_NONCOPYABLE(ConstPool) - //! Constant pool scope. - enum Scope : uint32_t { - //! Local constant, always embedded right after the current function. - kScopeLocal = 0, - //! Global constant, embedded at the end of the currently compiled code. - kScopeGlobal = 1 - }; - //! \cond INTERNAL //! Index of a given size in const-pool table. @@ -60,7 +41,8 @@ public: kIndex8 = 3, kIndex16 = 4, kIndex32 = 5, - kIndexCount = 6 + kIndex64 = 6, + kIndexCount = 7 }; //! Zone-allocated const-pool gap created by two differently aligned constants. @@ -193,6 +175,9 @@ public: //! \endcond + //! \name Members + //! \{ + //! Zone allocator. Zone* _zone; //! Tree per size. @@ -209,6 +194,8 @@ public: //! Minimum item size in the pool. size_t _minItemSize; + //! \} + //! \name Construction & Destruction //! \{ @@ -238,21 +225,18 @@ public: //! Adds a constant to the constant pool. //! - //! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes. - //! The constant is added to the pool only if it doesn't not exist, otherwise - //! cached value is returned. + //! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes. The constant is added to the pool only + //! if it doesn't not exist, otherwise cached value is returned. //! - //! AsmJit is able to subdivide added constants, so for example if you add - //! 8-byte constant 0x1122334455667788 it will create the following slots: + //! AsmJit is able to subdivide added constants, so for example if you add 8-byte constant 0x1122334455667788 it + //! will create the following slots: //! //! 8-byte: 0x1122334455667788 //! 4-byte: 0x11223344, 0x55667788 //! - //! The reason is that when combining MMX/SSE/AVX code some patterns are used - //! frequently. However, AsmJit is not able to reallocate a constant that has - //! been already added. For example if you try to add 4-byte constant and then - //! 8-byte constant having the same 4-byte pattern as the previous one, two - //! independent slots will be generated by the pool. + //! The reason is that when combining MMX/SSE/AVX code some patterns are used frequently. However, AsmJit is not + //! able to reallocate a constant that has been already added. For example if you try to add 4-byte constant and + //! then 8-byte constant having the same 4-byte pattern as the previous one, two independent slots will be used. ASMJIT_API Error add(const void* data, size_t size, size_t& dstOffset) noexcept; //! Fills the destination with the content of this constant pool. diff --git a/src/asmjit/core/cpuinfo.cpp b/src/asmjit/core/cpuinfo.cpp index a281a4a..ef152cd 100644 --- a/src/asmjit/core/cpuinfo.cpp +++ b/src/asmjit/core/cpuinfo.cpp @@ -1,28 +1,11 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/cpuinfo.h" +#include "../core/support.h" #if !defined(_WIN32) #include <errno.h> @@ -30,11 +13,27 @@ #include <unistd.h> #endif +// Required by `getauxval()` on Linux. +#if defined(__linux__) + #include <sys/auxv.h> +#endif + +//! Required to detect CPU and features on Apple platforms. +#if defined(__APPLE__) + #include <mach/machine.h> + #include <sys/types.h> + #include <sys/sysctl.h> +#endif + +// Required by `__cpuidex()` and `_xgetbv()`. +#if defined(_MSC_VER) + #include <intrin.h> +#endif + ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::CpuInfo - Detect - CPU NumThreads] -// ============================================================================ +// CpuInfo - Detect - HW-Thread Count +// ================================== #if defined(_WIN32) static inline uint32_t detectHWThreadCount() noexcept { @@ -53,37 +52,1103 @@ static inline uint32_t detectHWThreadCount() noexcept { } #endif -// ============================================================================ -// [asmjit::CpuInfo - Detect - CPU Features] -// ============================================================================ +// CpuInfo - Detect - X86 +// ====================== + +#if ASMJIT_ARCH_X86 + +struct cpuid_t { uint32_t eax, ebx, ecx, edx; }; +struct xgetbv_t { uint32_t eax, edx; }; -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 -namespace x86 { void detectCpu(CpuInfo& cpu) noexcept; } +// Executes `cpuid` instruction. +static inline void cpuidQuery(cpuid_t* out, uint32_t inEax, uint32_t inEcx = 0) noexcept { +#if defined(_MSC_VER) + __cpuidex(reinterpret_cast<int*>(out), inEax, inEcx); +#elif defined(__GNUC__) && ASMJIT_ARCH_X86 == 32 + __asm__ __volatile__( + "mov %%ebx, %%edi\n" + "cpuid\n" + "xchg %%edi, %%ebx\n" : "=a"(out->eax), "=D"(out->ebx), "=c"(out->ecx), "=d"(out->edx) : "a"(inEax), "c"(inEcx)); +#elif defined(__GNUC__) && ASMJIT_ARCH_X86 == 64 + __asm__ __volatile__( + "mov %%rbx, %%rdi\n" + "cpuid\n" + "xchg %%rdi, %%rbx\n" : "=a"(out->eax), "=D"(out->ebx), "=c"(out->ecx), "=d"(out->edx) : "a"(inEax), "c"(inEcx)); +#else + #error "[asmjit] x86::cpuidQuery() - Unsupported compiler." #endif +} -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM -namespace arm { void detectCpu(CpuInfo& cpu) noexcept; } +// Executes 'xgetbv' instruction. +static inline void xgetbvQuery(xgetbv_t* out, uint32_t inEcx) noexcept { +#if defined(_MSC_VER) + uint64_t value = _xgetbv(inEcx); + out->eax = uint32_t(value & 0xFFFFFFFFu); + out->edx = uint32_t(value >> 32); +#elif defined(__GNUC__) + uint32_t outEax; + uint32_t outEdx; + + // Replaced, because the world is not perfect: + // __asm__ __volatile__("xgetbv" : "=a"(outEax), "=d"(outEdx) : "c"(inEcx)); + __asm__ __volatile__(".byte 0x0F, 0x01, 0xD0" : "=a"(outEax), "=d"(outEdx) : "c"(inEcx)); + + out->eax = outEax; + out->edx = outEdx; +#else + out->eax = 0; + out->edx = 0; #endif +} + +// Map a 12-byte vendor string returned by `cpuid` into a `CpuInfo::Vendor` ID. +static inline void simplifyCpuVendor(CpuInfo& cpu, uint32_t d0, uint32_t d1, uint32_t d2) noexcept { + struct Vendor { + char normalized[8]; + union { char text[12]; uint32_t d[3]; }; + }; + + static const Vendor table[] = { + { { 'A', 'M', 'D' }, {{ 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' }} }, + { { 'I', 'N', 'T', 'E', 'L' }, {{ 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' }} }, + { { 'V', 'I', 'A' }, {{ 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' }} }, + { { 'V', 'I', 'A' }, {{ 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 }} }, + { { 'U', 'N', 'K', 'N', 'O', 'W', 'N' }, {{ 0 }} } + }; + + uint32_t i; + for (i = 0; i < ASMJIT_ARRAY_SIZE(table) - 1; i++) + if (table[i].d[0] == d0 && table[i].d[1] == d1 && table[i].d[2] == d2) + break; + memcpy(cpu._vendor.str, table[i].normalized, 8); +} + +static ASMJIT_FAVOR_SIZE void simplifyCpuBrand(char* s) noexcept { + char* d = s; + + char c = s[0]; + char prev = 0; + + // Used to always clear the current character to ensure that the result + // doesn't contain garbage after a new null terminator is placed at the end. + s[0] = '\0'; + + for (;;) { + if (!c) + break; + + if (!(c == ' ' && (prev == '@' || s[1] == ' ' || s[1] == '@'))) { + *d++ = c; + prev = c; + } + + c = *++s; + s[0] = '\0'; + } + + d[0] = '\0'; +} + +static ASMJIT_FAVOR_SIZE void detectX86Cpu(CpuInfo& cpu) noexcept { + using Support::bitTest; + + cpuid_t regs; + xgetbv_t xcr0 { 0, 0 }; + CpuFeatures::X86& features = cpu.features().x86(); + + cpu._wasDetected = true; + cpu._maxLogicalProcessors = 1; + + // We are gonna execute CPUID, which was introduced by I486, so it's the requirement. + features.add(CpuFeatures::X86::kI486); + + // CPUID EAX=0 + // ----------- + + // Get vendor string/id. + cpuidQuery(®s, 0x0); + + uint32_t maxId = regs.eax; + uint32_t maxSubLeafId_0x7 = 0; + + simplifyCpuVendor(cpu, regs.ebx, regs.edx, regs.ecx); + + // CPUID EAX=1 + // ----------- + + if (maxId >= 0x1) { + // Get feature flags in ECX/EDX and family/model in EAX. + cpuidQuery(®s, 0x1); + + // Fill family and model fields. + uint32_t modelId = (regs.eax >> 4) & 0x0F; + uint32_t familyId = (regs.eax >> 8) & 0x0F; + + // Use extended family and model fields. + if (familyId == 0x06u || familyId == 0x0Fu) + modelId += (((regs.eax >> 16) & 0x0Fu) << 4); + + if (familyId == 0x0Fu) + familyId += ((regs.eax >> 20) & 0xFFu); + + cpu._modelId = modelId; + cpu._familyId = familyId; + cpu._brandId = ((regs.ebx ) & 0xFF); + cpu._processorType = ((regs.eax >> 12) & 0x03); + cpu._maxLogicalProcessors = ((regs.ebx >> 16) & 0xFF); + cpu._stepping = ((regs.eax ) & 0x0F); + cpu._cacheLineSize = ((regs.ebx >> 8) & 0xFF) * 8; + + features.addIf(bitTest(regs.ecx, 0), CpuFeatures::X86::kSSE3); + features.addIf(bitTest(regs.ecx, 1), CpuFeatures::X86::kPCLMULQDQ); + features.addIf(bitTest(regs.ecx, 3), CpuFeatures::X86::kMONITOR); + features.addIf(bitTest(regs.ecx, 5), CpuFeatures::X86::kVMX); + features.addIf(bitTest(regs.ecx, 6), CpuFeatures::X86::kSMX); + features.addIf(bitTest(regs.ecx, 9), CpuFeatures::X86::kSSSE3); + features.addIf(bitTest(regs.ecx, 13), CpuFeatures::X86::kCMPXCHG16B); + features.addIf(bitTest(regs.ecx, 19), CpuFeatures::X86::kSSE4_1); + features.addIf(bitTest(regs.ecx, 20), CpuFeatures::X86::kSSE4_2); + features.addIf(bitTest(regs.ecx, 22), CpuFeatures::X86::kMOVBE); + features.addIf(bitTest(regs.ecx, 23), CpuFeatures::X86::kPOPCNT); + features.addIf(bitTest(regs.ecx, 25), CpuFeatures::X86::kAESNI); + features.addIf(bitTest(regs.ecx, 26), CpuFeatures::X86::kXSAVE); + features.addIf(bitTest(regs.ecx, 27), CpuFeatures::X86::kOSXSAVE); + features.addIf(bitTest(regs.ecx, 30), CpuFeatures::X86::kRDRAND); + features.addIf(bitTest(regs.edx, 0), CpuFeatures::X86::kFPU); + features.addIf(bitTest(regs.edx, 4), CpuFeatures::X86::kRDTSC); + features.addIf(bitTest(regs.edx, 5), CpuFeatures::X86::kMSR); + features.addIf(bitTest(regs.edx, 8), CpuFeatures::X86::kCMPXCHG8B); + features.addIf(bitTest(regs.edx, 15), CpuFeatures::X86::kCMOV); + features.addIf(bitTest(regs.edx, 19), CpuFeatures::X86::kCLFLUSH); + features.addIf(bitTest(regs.edx, 23), CpuFeatures::X86::kMMX); + features.addIf(bitTest(regs.edx, 24), CpuFeatures::X86::kFXSR); + features.addIf(bitTest(regs.edx, 25), CpuFeatures::X86::kSSE); + features.addIf(bitTest(regs.edx, 25), CpuFeatures::X86::kSSE, CpuFeatures::X86::kSSE2); + features.addIf(bitTest(regs.edx, 28), CpuFeatures::X86::kMT); + + // Get the content of XCR0 if supported by the CPU and enabled by the OS. + if (features.hasXSAVE() && features.hasOSXSAVE()) { + xgetbvQuery(&xcr0, 0); + } + + // Detect AVX+. + if (bitTest(regs.ecx, 28)) { + // - XCR0[2:1] == 11b + // XMM & YMM states need to be enabled by OS. + if ((xcr0.eax & 0x00000006u) == 0x00000006u) { + features.add(CpuFeatures::X86::kAVX); + features.addIf(bitTest(regs.ecx, 12), CpuFeatures::X86::kFMA); + features.addIf(bitTest(regs.ecx, 29), CpuFeatures::X86::kF16C); + } + } + } + + constexpr uint32_t kXCR0_AMX_Bits = 0x3u << 17; + bool amxEnabledByOS = (xcr0.eax & kXCR0_AMX_Bits) == kXCR0_AMX_Bits; + +#if defined(__APPLE__) + // Apple platform provides on-demand AVX512 support. When an AVX512 instruction is used the first time it results + // in #UD, which would cause the thread being promoted to use AVX512 support by the OS in addition to enabling the + // necessary bits in XCR0 register. + bool avx512EnabledByOS = true; +#else + // - XCR0[2:1] == 11b - XMM/YMM states need to be enabled by OS. + // - XCR0[7:5] == 111b - Upper 256-bit of ZMM0-XMM15 and ZMM16-ZMM31 need to be enabled by OS. + constexpr uint32_t kXCR0_AVX512_Bits = (0x3u << 1) | (0x7u << 5); + bool avx512EnabledByOS = (xcr0.eax & kXCR0_AVX512_Bits) == kXCR0_AVX512_Bits; +#endif + + // CPUID EAX=7 ECX=0 + // ----------------- + + // Detect new features if the processor supports CPUID-07. + bool maybeMPX = false; + + if (maxId >= 0x7) { + cpuidQuery(®s, 0x7); + + maybeMPX = bitTest(regs.ebx, 14); + maxSubLeafId_0x7 = regs.eax; + + features.addIf(bitTest(regs.ebx, 0), CpuFeatures::X86::kFSGSBASE); + features.addIf(bitTest(regs.ebx, 3), CpuFeatures::X86::kBMI); + features.addIf(bitTest(regs.ebx, 4), CpuFeatures::X86::kHLE); + features.addIf(bitTest(regs.ebx, 7), CpuFeatures::X86::kSMEP); + features.addIf(bitTest(regs.ebx, 8), CpuFeatures::X86::kBMI2); + features.addIf(bitTest(regs.ebx, 9), CpuFeatures::X86::kERMS); + features.addIf(bitTest(regs.ebx, 11), CpuFeatures::X86::kRTM); + features.addIf(bitTest(regs.ebx, 18), CpuFeatures::X86::kRDSEED); + features.addIf(bitTest(regs.ebx, 19), CpuFeatures::X86::kADX); + features.addIf(bitTest(regs.ebx, 20), CpuFeatures::X86::kSMAP); + features.addIf(bitTest(regs.ebx, 23), CpuFeatures::X86::kCLFLUSHOPT); + features.addIf(bitTest(regs.ebx, 24), CpuFeatures::X86::kCLWB); + features.addIf(bitTest(regs.ebx, 29), CpuFeatures::X86::kSHA); + features.addIf(bitTest(regs.ecx, 0), CpuFeatures::X86::kPREFETCHWT1); + features.addIf(bitTest(regs.ecx, 4), CpuFeatures::X86::kOSPKE); + features.addIf(bitTest(regs.ecx, 5), CpuFeatures::X86::kWAITPKG); + features.addIf(bitTest(regs.ecx, 7), CpuFeatures::X86::kCET_SS); + features.addIf(bitTest(regs.ecx, 8), CpuFeatures::X86::kGFNI); + features.addIf(bitTest(regs.ecx, 9), CpuFeatures::X86::kVAES); + features.addIf(bitTest(regs.ecx, 10), CpuFeatures::X86::kVPCLMULQDQ); + features.addIf(bitTest(regs.ecx, 22), CpuFeatures::X86::kRDPID); + features.addIf(bitTest(regs.ecx, 25), CpuFeatures::X86::kCLDEMOTE); + features.addIf(bitTest(regs.ecx, 27), CpuFeatures::X86::kMOVDIRI); + features.addIf(bitTest(regs.ecx, 28), CpuFeatures::X86::kMOVDIR64B); + features.addIf(bitTest(regs.ecx, 29), CpuFeatures::X86::kENQCMD); + features.addIf(bitTest(regs.edx, 5), CpuFeatures::X86::kUINTR); + features.addIf(bitTest(regs.edx, 14), CpuFeatures::X86::kSERIALIZE); + features.addIf(bitTest(regs.edx, 16), CpuFeatures::X86::kTSXLDTRK); + features.addIf(bitTest(regs.edx, 18), CpuFeatures::X86::kPCONFIG); + features.addIf(bitTest(regs.edx, 20), CpuFeatures::X86::kCET_IBT); + + // Detect 'TSX' - Requires at least one of `HLE` and `RTM` features. + if (features.hasHLE() || features.hasRTM()) + features.add(CpuFeatures::X86::kTSX); + + // Detect 'AVX2' - Requires AVX as well. + if (bitTest(regs.ebx, 5) && features.hasAVX()) + features.add(CpuFeatures::X86::kAVX2); + + // Detect 'AVX512'. + if (avx512EnabledByOS && bitTest(regs.ebx, 16)) { + features.add(CpuFeatures::X86::kAVX512_F); + + features.addIf(bitTest(regs.ebx, 17), CpuFeatures::X86::kAVX512_DQ); + features.addIf(bitTest(regs.ebx, 21), CpuFeatures::X86::kAVX512_IFMA); + features.addIf(bitTest(regs.ebx, 26), CpuFeatures::X86::kAVX512_PFI); + features.addIf(bitTest(regs.ebx, 27), CpuFeatures::X86::kAVX512_ERI); + features.addIf(bitTest(regs.ebx, 28), CpuFeatures::X86::kAVX512_CDI); + features.addIf(bitTest(regs.ebx, 30), CpuFeatures::X86::kAVX512_BW); + features.addIf(bitTest(regs.ebx, 31), CpuFeatures::X86::kAVX512_VL); + features.addIf(bitTest(regs.ecx, 1), CpuFeatures::X86::kAVX512_VBMI); + features.addIf(bitTest(regs.ecx, 6), CpuFeatures::X86::kAVX512_VBMI2); + features.addIf(bitTest(regs.ecx, 11), CpuFeatures::X86::kAVX512_VNNI); + features.addIf(bitTest(regs.ecx, 12), CpuFeatures::X86::kAVX512_BITALG); + features.addIf(bitTest(regs.ecx, 14), CpuFeatures::X86::kAVX512_VPOPCNTDQ); + features.addIf(bitTest(regs.edx, 2), CpuFeatures::X86::kAVX512_4VNNIW); + features.addIf(bitTest(regs.edx, 3), CpuFeatures::X86::kAVX512_4FMAPS); + features.addIf(bitTest(regs.edx, 8), CpuFeatures::X86::kAVX512_VP2INTERSECT); + features.addIf(bitTest(regs.edx, 23), CpuFeatures::X86::kAVX512_FP16); + } + + // Detect 'AMX'. + if (amxEnabledByOS) { + features.addIf(bitTest(regs.edx, 22), CpuFeatures::X86::kAMX_BF16); + features.addIf(bitTest(regs.edx, 24), CpuFeatures::X86::kAMX_TILE); + features.addIf(bitTest(regs.edx, 25), CpuFeatures::X86::kAMX_INT8); + } + } + + // CPUID EAX=7 ECX=1 + // ----------------- + + if (features.hasAVX512_F() && maxSubLeafId_0x7 >= 1) { + cpuidQuery(®s, 0x7, 1); + + features.addIf(bitTest(regs.eax, 3), CpuFeatures::X86::kAVX_VNNI); + features.addIf(bitTest(regs.eax, 5), CpuFeatures::X86::kAVX512_BF16); + features.addIf(bitTest(regs.eax, 22), CpuFeatures::X86::kHRESET); + } + + // CPUID EAX=13 ECX=0 + // ------------------ + + if (maxId >= 0xD) { + cpuidQuery(®s, 0xD, 0); + + // Both CPUID result and XCR0 has to be enabled to have support for MPX. + if (((regs.eax & xcr0.eax) & 0x00000018u) == 0x00000018u && maybeMPX) + features.add(CpuFeatures::X86::kMPX); -// ============================================================================ -// [asmjit::CpuInfo - Detect - Static Initializer] -// ============================================================================ + cpuidQuery(®s, 0xD, 1); + + features.addIf(bitTest(regs.eax, 0), CpuFeatures::X86::kXSAVEOPT); + features.addIf(bitTest(regs.eax, 1), CpuFeatures::X86::kXSAVEC); + features.addIf(bitTest(regs.eax, 3), CpuFeatures::X86::kXSAVES); + } + + // CPUID EAX=14 ECX=0 + // ------------------ + + if (maxId >= 0xE) { + cpuidQuery(®s, 0xE, 0); + + features.addIf(bitTest(regs.ebx, 4), CpuFeatures::X86::kPTWRITE); + } + + // CPUID EAX=0x80000000...maxId + // ---------------------------- + + maxId = 0x80000000u; + uint32_t i = maxId; + + // The highest EAX that we understand. + constexpr uint32_t kHighestProcessedEAX = 0x8000001Fu; + + // Several CPUID calls are required to get the whole branc string. It's easier + // to copy one DWORD at a time instead of copying the string a byte by byte. + uint32_t* brand = cpu._brand.u32; + do { + cpuidQuery(®s, i); + switch (i) { + case 0x80000000u: + maxId = Support::min<uint32_t>(regs.eax, kHighestProcessedEAX); + break; + + case 0x80000001u: + features.addIf(bitTest(regs.ecx, 0), CpuFeatures::X86::kLAHFSAHF); + features.addIf(bitTest(regs.ecx, 2), CpuFeatures::X86::kSVM); + features.addIf(bitTest(regs.ecx, 5), CpuFeatures::X86::kLZCNT); + features.addIf(bitTest(regs.ecx, 6), CpuFeatures::X86::kSSE4A); + features.addIf(bitTest(regs.ecx, 7), CpuFeatures::X86::kMSSE); + features.addIf(bitTest(regs.ecx, 8), CpuFeatures::X86::kPREFETCHW); + features.addIf(bitTest(regs.ecx, 12), CpuFeatures::X86::kSKINIT); + features.addIf(bitTest(regs.ecx, 15), CpuFeatures::X86::kLWP); + features.addIf(bitTest(regs.ecx, 21), CpuFeatures::X86::kTBM); + features.addIf(bitTest(regs.ecx, 29), CpuFeatures::X86::kMONITORX); + features.addIf(bitTest(regs.edx, 20), CpuFeatures::X86::kNX); + features.addIf(bitTest(regs.edx, 21), CpuFeatures::X86::kFXSROPT); + features.addIf(bitTest(regs.edx, 22), CpuFeatures::X86::kMMX2); + features.addIf(bitTest(regs.edx, 27), CpuFeatures::X86::kRDTSCP); + features.addIf(bitTest(regs.edx, 29), CpuFeatures::X86::kPREFETCHW); + features.addIf(bitTest(regs.edx, 30), CpuFeatures::X86::k3DNOW2, CpuFeatures::X86::kMMX2); + features.addIf(bitTest(regs.edx, 31), CpuFeatures::X86::kPREFETCHW); + + if (features.hasAVX()) { + features.addIf(bitTest(regs.ecx, 11), CpuFeatures::X86::kXOP); + features.addIf(bitTest(regs.ecx, 16), CpuFeatures::X86::kFMA4); + } + + // This feature seems to be only supported by AMD. + if (cpu.isVendor("AMD")) { + features.addIf(bitTest(regs.ecx, 4), CpuFeatures::X86::kALTMOVCR8); + } + break; + + case 0x80000002u: + case 0x80000003u: + case 0x80000004u: + *brand++ = regs.eax; + *brand++ = regs.ebx; + *brand++ = regs.ecx; + *brand++ = regs.edx; + + // Go directly to the next one we are interested in. + if (i == 0x80000004u) + i = 0x80000008u - 1; + break; + + case 0x80000008u: + features.addIf(bitTest(regs.ebx, 0), CpuFeatures::X86::kCLZERO); + features.addIf(bitTest(regs.ebx, 0), CpuFeatures::X86::kRDPRU); + features.addIf(bitTest(regs.ebx, 8), CpuFeatures::X86::kMCOMMIT); + features.addIf(bitTest(regs.ebx, 9), CpuFeatures::X86::kWBNOINVD); + + // Go directly to the next one we are interested in. + i = 0x8000001Fu - 1; + break; + + case 0x8000001Fu: + features.addIf(bitTest(regs.eax, 4), CpuFeatures::X86::kSNP); + break; + } + } while (++i <= maxId); + + // Simplify CPU brand string a bit by removing some unnecessary spaces. + simplifyCpuBrand(cpu._brand.str); +} + +#endif // ASMJIT_ARCH_X86 + +// CpuInfo - Detect - ARM +// ====================== + +// The most relevant and accurate information can be found here: +// https://github.com/llvm-project/llvm/blob/master/lib/Target/AArch64/AArch64.td +// https://github.com/apple/llvm-project/blob/apple/main/llvm/lib/Target/AArch64/AArch64.td (Apple fork) +// +// Other resources: +// https://en.wikipedia.org/wiki/AArch64 +// https://en.wikipedia.org/wiki/Apple_silicon#List_of_Apple_processors +// https://developer.arm.com/architectures/learn-the-architecture/understanding-the-armv8-x-extensions/single-page + +#if ASMJIT_ARCH_ARM + +static inline void populateBaseARMFeatures(CpuInfo& cpu) noexcept { +#if ASMJIT_ARCH_ARM == 32 + // No baseline flags at the moment. + DebugUtils::unused(cpu); +#else + // AArch64 is based on ARMv8-A and later. + cpu.addFeature(CpuFeatures::ARM::kARMv6); + cpu.addFeature(CpuFeatures::ARM::kARMv7); + cpu.addFeature(CpuFeatures::ARM::kARMv8a); + + // AArch64 comes with these features by default. + cpu.addFeature(CpuFeatures::ARM::kVFPv2); + cpu.addFeature(CpuFeatures::ARM::kVFPv3); + cpu.addFeature(CpuFeatures::ARM::kVFPv4); + cpu.addFeature(CpuFeatures::ARM::kASIMD); + cpu.addFeature(CpuFeatures::ARM::kIDIVA); +#endif +} + +// Detects ARM version by macros defined at compile time. This means that AsmJit will report features forced at +// compile time that should always be provided by the target CPU. This also means that if we don't provide any +// means to detect CPU features the features reported by AsmJit will at least not report less features than the +// target it was compiled to. +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void detectARMFeaturesViaCompilerFlags(CpuInfo& cpu) noexcept { + DebugUtils::unused(cpu); + +#if ASMJIT_ARCH_ARM == 32 + + // ARM targets have no baseline at the moment. +# if defined(__ARM_ARCH_7A__) + cpu.addFeature(CpuFeatures::ARM::kARMv7); +# endif +# if defined(__ARM_ARCH_8A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8a); +# endif + +# if defined(__TARGET_ARCH_THUMB) + cpu.addFeature(CpuFeatures::ARM::kTHUMB); +# if __TARGET_ARCH_THUMB >= 4 + cpu.addFeature(CpuFeatures::ARM::kTHUMBv2); +# endif +# endif + +# if defined(__ARM_FEATURE_FMA) + cpu.addFeature(CpuFeatures::ARM::kVFPv3); + cpu.addFeature(CpuFeatures::ARM::kVFPv4); +# endif + +# if defined(__ARM_NEON) + cpu.addFeature(CpuFeatures::ARM::kASIMD); +# endif + +# if defined(__ARM_FEATURE_IDIV) && defined(__TARGET_ARCH_THUMB) + cpu.addFeature(CpuFeatures::ARM::kIDIVT); +#endif +# if defined(__ARM_FEATURE_IDIV) && !defined(__TARGET_ARCH_THUMB) + cpu.addFeature(CpuFeatures::ARM::kIDIVA); +# endif + +#endif + +#if defined(__ARM_ARCH_8_1A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_1a); +#endif +#if defined(__ARM_ARCH_8_2A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_2a); +#endif +#if defined(__ARM_ARCH_8_3A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_3a); +#endif +#if defined(__ARM_ARCH_8_4A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_4a); +#endif +#if defined(__ARM_ARCH_8_5A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_5a); +#endif +#if defined(__ARM_ARCH_8_6A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_6a); +#endif +#if defined(__ARM_ARCH_8_7A__) + cpu.addFeature(CpuFeatures::ARM::kARMv8_7a); +#endif + +#if defined(__ARM_FEATURE_AES) + cpu.addFeature(CpuFeatures::ARM::kAES); +#endif + +#if defined(__ARM_FEATURE_BF16_SCALAR_ARITHMETIC) && defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) + cpu.addFeature(CpuFeatures::ARM::kBF16); +#endif + +#if defined(__ARM_FEATURE_CRC32) + cpu.addFeature(CpuFeatures::ARM::kCRC32); +#endif + +#if defined(__ARM_FEATURE_CRYPTO) + cpu.addFeature(CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); +#endif + +#if defined(__ARM_FEATURE_DOTPROD) + cpu.addFeature(CpuFeatures::ARM::kDOTPROD); +#endif + +#if defined(__ARM_FEATURE_FP16FML) || defined(__ARM_FEATURE_FP16_FML) + cpu.addFeature(CpuFeatures::ARM::kFP16FML); +#endif + +#if defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) + cpu.addFeature(CpuFeatures::ARM::kFP16FULL); +#endif + +#if defined(__ARM_FEATURE_FRINT) + cpu.addFeature(CpuFeatures::ARM::kFRINT); +#endif + +#if defined(__ARM_FEATURE_JCVT) + cpu.addFeature(CpuFeatures::ARM::kFJCVTZS); +#endif + +#if defined(__ARM_FEATURE_MATMUL_INT8) + cpu.addFeature(CpuFeatures::ARM::kI8MM); +#endif + +#if defined(__ARM_FEATURE_ATOMICS) + cpu.addFeature(CpuFeatures::ARM::kLSE); +#endif + +#if defined(__ARM_FEATURE_MEMORY_TAGGING) + cpu.addFeature(CpuFeatures::ARM::kMTE); +#endif + +#if defined(__ARM_FEATURE_QRDMX) + cpu.addFeature(CpuFeatures::ARM::kRDM); +#endif + +#if defined(__ARM_FEATURE_RNG) + cpu.addFeature(CpuFeatures::ARM::kRNG); +#endif + +#if defined(__ARM_FEATURE_SHA2) + cpu.addFeature(CpuFeatures::ARM::kSHA2); +#endif + +#if defined(__ARM_FEATURE_SHA3) + cpu.addFeature(CpuFeatures::ARM::kSHA3); +#endif + +#if defined(__ARM_FEATURE_SHA512) + cpu.addFeature(CpuFeatures::ARM::kSHA512); +#endif + +#if defined(__ARM_FEATURE_SM3) + cpu.addFeature(CpuFeatures::ARM::kSM3); +#endif + +#if defined(__ARM_FEATURE_SM4) + cpu.addFeature(CpuFeatures::ARM::kSM4); +#endif + +#if defined(__ARM_FEATURE_SVE) || defined(__ARM_FEATURE_SVE_VECTOR_OPERATORS) + cpu.addFeature(CpuFeatures::ARM::kSVE); +#endif + +#if defined(__ARM_FEATURE_SVE_MATMUL_INT8) + cpu.addFeature(CpuFeatures::ARM::kSVE_I8MM); +#endif + +#if defined(__ARM_FEATURE_SVE_MATMUL_FP32) + cpu.addFeature(CpuFeatures::ARM::kSVE_F32MM); +#endif + +#if defined(__ARM_FEATURE_SVE_MATMUL_FP64) + cpu.addFeature(CpuFeatures::ARM::kSVE_F64MM); +#endif + +#if defined(__ARM_FEATURE_SVE2) + cpu.addFeature(CpuFeatures::ARM::kSVE2); +#endif + +#if defined(__ARM_FEATURE_SVE2_AES) + cpu.addFeature(CpuFeatures::ARM::kSVE2_AES); +#endif + +#if defined(__ARM_FEATURE_SVE2_BITPERM) + cpu.addFeature(CpuFeatures::ARM::kSVE2_BITPERM); +#endif + +#if defined(__ARM_FEATURE_SVE2_SHA3) + cpu.addFeature(CpuFeatures::ARM::kSVE2_SHA3); +#endif + +#if defined(__ARM_FEATURE_SVE2_SM4) + cpu.addFeature(CpuFeatures::ARM::kSVE2_SM4); +#endif + +#if defined(__ARM_FEATURE_TME) + cpu.addFeature(CpuFeatures::ARM::kTME); +#endif +} + +ASMJIT_MAYBE_UNUSED +static ASMJIT_FAVOR_SIZE void expandARMFeaturesByVersion(CpuInfo& cpu) noexcept { + CpuFeatures::ARM& features = cpu.features().arm(); + + if (features.hasARMv8_7a()) { + features.add(CpuFeatures::ARM::kARMv8_6a); + } + + if (features.hasARMv8_6a()) { + features.add(CpuFeatures::ARM::kARMv8_5a, + CpuFeatures::ARM::kBF16); + + if (features.hasSVE()) + features.add(CpuFeatures::ARM::kSVE_I8MM); + } + + if (features.hasARMv8_5a()) { + features.add(CpuFeatures::ARM::kARMv8_4a, + CpuFeatures::ARM::kALTNZCV, + CpuFeatures::ARM::kBTI, + CpuFeatures::ARM::kFRINT, + CpuFeatures::ARM::kSB, + CpuFeatures::ARM::kSSBS); + } + + if (features.hasARMv8_4a()) { + features.add(CpuFeatures::ARM::kARMv8_3a, + CpuFeatures::ARM::kDIT, + CpuFeatures::ARM::kDOTPROD, + CpuFeatures::ARM::kFLAGM, + CpuFeatures::ARM::kPMU, + CpuFeatures::ARM::kRCPC_IMMO); + } + + if (features.hasARMv8_3a()) { + features.add(CpuFeatures::ARM::kARMv8_2a, + CpuFeatures::ARM::kFCMA, + CpuFeatures::ARM::kFJCVTZS); + } + + if (features.hasARMv8_2a()) { + features.add(CpuFeatures::ARM::kARMv8_1a); + } + + if (features.hasARMv8_1a()) { + features.add(CpuFeatures::ARM::kARMv8a, + CpuFeatures::ARM::kCRC32, + CpuFeatures::ARM::kLSE, + CpuFeatures::ARM::kRDM); + } + + if (features.hasARMv8a()) { + features.add(CpuFeatures::ARM::kARMv7, + CpuFeatures::ARM::kVFPv2, + CpuFeatures::ARM::kVFPv3, + CpuFeatures::ARM::kVFPv4, + CpuFeatures::ARM::kVFP_D32, + CpuFeatures::ARM::kASIMD, + CpuFeatures::ARM::kIDIVA); + } +} + +// CpuInfo - Detect - ARM [Windows] +// ================================ + +#if defined(_WIN32) +struct WinPFPMapping { + uint8_t featureId; + uint8_t pfpFeatureId; +}; + +static ASMJIT_FAVOR_SIZE void detectPFPFeatures(CpuInfo& cpu, const WinPFPMapping* mapping, size_t size) noexcept { + for (size_t i = 0; i < size; i++) + if (::IsProcessorFeaturePresent(mapping[i].pfpFeatureId)) + cpu.addFeature(mapping[i].featureId); +} + +//! Detect ARM CPU features on Windows. +//! +//! The detection is based on `IsProcessorFeaturePresent()` API call. +static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { + cpu._wasDetected = true; + populateBaseARMFeatures(cpu); + + CpuFeatures::ARM& features = cpu.features().arm(); + + // Win32 for ARM requires ARMv7 with DSP extensions, VFPv3, and uses THUMBv2 by default. +#if ASMJIT_ARCH_ARM == 32 + features.add(CpuFeatures::ARM::kTHUMB); + features.add(CpuFeatures::ARM::kTHUMBv2); + features.add(CpuFeatures::ARM::kARMv6); + features.add(CpuFeatures::ARM::kARMv7); + features.add(CpuFeatures::ARM::kEDSP); + features.add(CpuFeatures::ARM::kVFPv2); + features.add(CpuFeatures::ARM::kVFPv3); +#endif + + // Windows for ARM requires ASIMD. + features.add(CpuFeatures::ARM::kASIMD); + + // Detect additional CPU features by calling `IsProcessorFeaturePresent()`. + static const WinPFPMapping mapping[] = { +#if ASMJIT_ARCH_ARM == 32 + { uint8_t(CpuFeatures::ARM::kVFP_D32) , 18 }, // PF_ARM_VFP_32_REGISTERS_AVAILABLE + { uint8_t(CpuFeatures::ARM::kIDIVT) , 24 }, // PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE + { uint8_t(CpuFeatures::ARM::kVFPv4) , 27 }, // PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE + { uint8_t(CpuFeatures::ARM::kARMv8a) , 29 }, // PF_ARM_V8_INSTRUCTIONS_AVAILABLE +#endif + { uint8_t(CpuFeatures::ARM::kAES) , 30 }, // PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE + { uint8_t(CpuFeatures::ARM::kCRC32) , 31 }, // PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE + { uint8_t(CpuFeatures::ARM::kLSE) , 34 } // PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE + + }; + detectPFPFeatures(cpu, mapping, ASMJIT_ARRAY_SIZE(mapping)); + + // Windows provides several instructions under a single flag: + if (features.hasAES()) { + features.add(CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + } + + expandARMFeaturesByVersion(cpu); +} + +// CpuInfo - Detect - ARM [Linux] +// ============================== + +#elif defined(__linux__) + +struct LinuxHWCapMapping { + uint8_t featureId; + uint8_t hwCapBit; +}; + +static ASMJIT_FAVOR_SIZE void detectHWCaps(CpuInfo& cpu, unsigned long type, const LinuxHWCapMapping* mapping, size_t size) noexcept { + unsigned long mask = getauxval(type); + for (size_t i = 0; i < size; i++) + cpu.features().addIf(Support::bitTest(mask, mapping[i].hwCapBit), mapping[i].featureId); +} + +#if ASMJIT_ARCH_ARM == 32 + +// `AT_HWCAP` provides ARMv7 (and less) related flags. +static const LinuxHWCapMapping hwCapMapping[] = { + { uint8_t(CpuFeatures::ARM::kVFPv2) , 6 }, // HWCAP_VFP + { uint8_t(CpuFeatures::ARM::kEDSP) , 7 }, // HWCAP_EDSP + { uint8_t(CpuFeatures::ARM::kASIMD) , 12 }, // HWCAP_NEON + { uint8_t(CpuFeatures::ARM::kVFPv3) , 13 }, // HWCAP_VFPv3 + { uint8_t(CpuFeatures::ARM::kVFPv4) , 16 }, // HWCAP_VFPv4 + { uint8_t(CpuFeatures::ARM::kIDIVA) , 17 }, // HWCAP_IDIVA + { uint8_t(CpuFeatures::ARM::kIDIVT) , 18 }, // HWCAP_IDIVT + { uint8_t(CpuFeatures::ARM::kVFP_D32) , 19 } // HWCAP_VFPD32 +}; + +// `AT_HWCAP2` provides ARMv8+ related flags. +static const LinuxHWCapMapping hwCap2Mapping[] = { + { uint8_t(CpuFeatures::ARM::kAES) , 0 }, // HWCAP2_AES + { uint8_t(CpuFeatures::ARM::kPMULL) , 1 }, // HWCAP2_PMULL + { uint8_t(CpuFeatures::ARM::kSHA1) , 2 }, // HWCAP2_SHA1 + { uint8_t(CpuFeatures::ARM::kSHA2) , 3 }, // HWCAP2_SHA2 + { uint8_t(CpuFeatures::ARM::kCRC32) , 4 } // HWCAP2_CRC32 +}; + +static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { + cpu._wasDetected = true; + + populateBaseARMFeatures(cpu); + + CpuFeatures::ARM& features = cpu.features().arm(); + + detectHWCaps(cpu, AT_HWCAP, hwCapMapping, ASMJIT_ARRAY_SIZE(hwCapMapping)); + detectHWCaps(cpu, AT_HWCAP2, hwCap2Mapping, ASMJIT_ARRAY_SIZE(hwCap2Mapping)); + + // VFPv3 implies VFPv2. + if (features.hasVFPv3()) + features.add(CpuFeatures::ARM::kVFPv2); + + // VFPv2 implies ARMv6. + if (features.hasVFPv2()) + features.add(CpuFeatures::ARM::kARMv6); + + // ARMv7 provides VFPv3|ASIMD. + if (features.hasVFPv3() || features.hasASIMD()) + features.add(CpuFeatures::ARM::kARMv7); + + // ARMv8 provives AES, CRC32, PMULL, SHA1, and SHA2. + if (features.hasAES() || features.hasCRC32() || features.hasPMULL() || features.hasSHA1() || features.hasSHA2()) + features.add(CpuFeatures::ARM::kARMv8a); +} + +#else + +// `AT_HWCAP` provides ARMv8+ related flags. +static const LinuxHWCapMapping hwCapMapping[] = { + /* + { uint8_t(CpuFeatures::ARM::k) , 0 }, // HWCAP_FP + */ + { uint8_t(CpuFeatures::ARM::kASIMD) , 1 }, // HWCAP_ASIMD + /* + { uint8_t(CpuFeatures::ARM::k) , 2 }, // HWCAP_EVTSTRM + */ + { uint8_t(CpuFeatures::ARM::kAES) , 3 }, // HWCAP_AES + { uint8_t(CpuFeatures::ARM::kPMULL) , 4 }, // HWCAP_PMULL + { uint8_t(CpuFeatures::ARM::kSHA1) , 5 }, // HWCAP_SHA1 + { uint8_t(CpuFeatures::ARM::kSHA2) , 6 }, // HWCAP_SHA2 + { uint8_t(CpuFeatures::ARM::kCRC32) , 7 }, // HWCAP_CRC32 + { uint8_t(CpuFeatures::ARM::kLSE) , 8 }, // HWCAP_ATOMICS + { uint8_t(CpuFeatures::ARM::kFP16CONV) , 9 }, // HWCAP_FPHP + { uint8_t(CpuFeatures::ARM::kFP16FULL) , 10 }, // HWCAP_ASIMDHP + { uint8_t(CpuFeatures::ARM::kCPUID) , 11 }, // HWCAP_CPUID + { uint8_t(CpuFeatures::ARM::kRDM) , 12 }, // HWCAP_ASIMDRDM + { uint8_t(CpuFeatures::ARM::kFJCVTZS) , 13 }, // HWCAP_JSCVT + { uint8_t(CpuFeatures::ARM::kFCMA) , 14 }, // HWCAP_FCMA + /* + { uint8_t(CpuFeatures::ARM::k) , 15 }, // HWCAP_LRCPC + { uint8_t(CpuFeatures::ARM::k) , 16 }, // HWCAP_DCPOP + */ + { uint8_t(CpuFeatures::ARM::kSHA3) , 17 }, // HWCAP_SHA3 + { uint8_t(CpuFeatures::ARM::kSM3) , 18 }, // HWCAP_SM3 + { uint8_t(CpuFeatures::ARM::kSM4) , 19 }, // HWCAP_SM4 + { uint8_t(CpuFeatures::ARM::kDOTPROD) , 20 }, // HWCAP_ASIMDDP + { uint8_t(CpuFeatures::ARM::kSHA512) , 21 }, // HWCAP_SHA512 + { uint8_t(CpuFeatures::ARM::kSVE) , 22 }, // HWCAP_SVE + { uint8_t(CpuFeatures::ARM::kFP16FML) , 23 }, // HWCAP_ASIMDFHM + { uint8_t(CpuFeatures::ARM::kDIT) , 24 }, // HWCAP_DIT + /* + { uint8_t(CpuFeatures::ARM::k) , 25 }, // HWCAP_USCAT + { uint8_t(CpuFeatures::ARM::k) , 26 }, // HWCAP_ILRCPC + */ + { uint8_t(CpuFeatures::ARM::kFLAGM) , 27 }, // HWCAP_FLAGM + { uint8_t(CpuFeatures::ARM::kSSBS) , 28 }, // HWCAP_SSBS + { uint8_t(CpuFeatures::ARM::kSB) , 29 } // HWCAP_SB + /* + { uint8_t(CpuFeatures::ARM::k) , 30 }, // HWCAP_PACA + { uint8_t(CpuFeatures::ARM::k) , 31 } // HWCAP_PACG + */ +}; + +// `AT_HWCAP2` provides ARMv8+ related flags. +static const LinuxHWCapMapping hwCapMapping2[] = { + /* + { uint8_t(CpuFeatures::ARM::k) , 0 }, // HWCAP2_DCPODP + */ + { uint8_t(CpuFeatures::ARM::kSVE2) , 1 }, // HWCAP2_SVE2 + { uint8_t(CpuFeatures::ARM::kSVE2_AES) , 2 }, // HWCAP2_SVEAES + { uint8_t(CpuFeatures::ARM::kSVE_PMULL) , 3 }, // HWCAP2_SVEPMULL + { uint8_t(CpuFeatures::ARM::kSVE2_BITPERM), 4 }, // HWCAP2_SVEBITPERM + { uint8_t(CpuFeatures::ARM::kSVE2_SHA3) , 5 }, // HWCAP2_SVESHA3 + { uint8_t(CpuFeatures::ARM::kSVE2_SM4) , 6 }, // HWCAP2_SVESM4 + { uint8_t(CpuFeatures::ARM::kALTNZCV) , 7 }, // HWCAP2_FLAGM2 + { uint8_t(CpuFeatures::ARM::kFRINT) , 8 }, // HWCAP2_FRINT + { uint8_t(CpuFeatures::ARM::kSVE_I8MM) , 9 }, // HWCAP2_SVEI8MM + { uint8_t(CpuFeatures::ARM::kSVE_F32MM) , 10 }, // HWCAP2_SVEF32MM + { uint8_t(CpuFeatures::ARM::kSVE_F64MM) , 11 }, // HWCAP2_SVEF64MM + { uint8_t(CpuFeatures::ARM::kSVE_BF16) , 12 }, // HWCAP2_SVEBF16 + { uint8_t(CpuFeatures::ARM::kI8MM) , 13 }, // HWCAP2_I8MM + { uint8_t(CpuFeatures::ARM::kBF16) , 14 }, // HWCAP2_BF16 + { uint8_t(CpuFeatures::ARM::kDGH) , 15 }, // HWCAP2_DGH + { uint8_t(CpuFeatures::ARM::kRNG) , 16 }, // HWCAP2_RNG + { uint8_t(CpuFeatures::ARM::kBTI) , 17 }, // HWCAP2_BTI + { uint8_t(CpuFeatures::ARM::kMTE) , 18 } // HWCAP2_MTE +}; + +static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { + cpu._wasDetected = true; + populateBaseARMFeatures(cpu); + + detectHWCaps(cpu, AT_HWCAP, hwCapMapping, ASMJIT_ARRAY_SIZE(hwCapMapping)); + detectHWCaps(cpu, AT_HWCAP2, hwCapMapping2, ASMJIT_ARRAY_SIZE(hwCapMapping2)); +} + +#endif + +// CpuInfo - Detect - ARM [Apple] +// ============================== + +#elif defined(__APPLE__) + +namespace AppleHWId { + enum CpuFamily : uint32_t { + // Generic ARM. + kCpuFamily_ARM_9 = 0xE73283AEu, + kCpuFamily_ARM_11 = 0x8FF620D8u, + kCpuFamily_ARM_12 = 0xBD1B0AE9u, + kCpuFamily_ARM_13 = 0x0CC90E64u, + kCpuFamily_ARM_14 = 0x96077EF1u, + kCpuFamily_ARM_15 = 0xA8511BCAu, + + // Apple design. + kCpuFamily_SWIFT = 0x1E2D6381u, + kCpuFamily_CYCLONE = 0x37A09642u, + kCpuFamily_TYPHOON = 0x2C91A47Eu, + kCpuFamily_TWISTER = 0x92FB37C8u, + kCpuFamily_HURRICANE = 0x67CEEE93u, + kCpuFamily_MONSOON_MISTRAL = 0xE81E7EF6u, + kCpuFamily_VORTEX_TEMPEST = 0x07D34B9Fu, + kCpuFamily_LIGHTNING_THUNDER = 0x462504D2u, + kCpuFamily_FIRESTORM_ICESTORM = 0x1B588BB3u + }; +}; + +static ASMJIT_FAVOR_SIZE uint32_t queryARMCpuFamilyId() noexcept { + uint32_t result = 0; + size_t size = sizeof(cpuFamily); + + int res = sysctlbyname("hw.cpufamily", &result, &size, nullptr, 0); + if (res != 0) + return 0; + else + return result; +} + +static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { + cpu._wasDetected = true; + populateBaseARMFeatures(cpu); + + uint32_t cpuFamilyId = queryARMCpuFamilyId(); + CpuFeatures::ARM& features = cpu.features().arm(); + + switch (cpuFamilyId) { + case AppleHWId::kCpuFamily_ARM_9: + case AppleHWId::kCpuFamily_ARM_11: + case AppleHWId::kCpuFamily_ARM_12: + break; + + // ARM Cortex A8. + case AppleHWId::kCpuFamily_ARM_13: + break; + + // ARM Cortex A9. + case AppleHWId::kCpuFamily_ARM_14: + break; + + // ARM Cortex A7 - ARMv7k. + case AppleHWId::kCpuFamily_ARM_15: + features.add(CpuFeatures::ARM::kARMv7); + break; + + // Apple A6/A6X - ARMv7s. + case AppleHWId::kCpuFamily_SWIFT: + features.add(CpuFeatures::ARM::kARMv7); + break; + + // Apple A7 - ARMv8.0-A. + case AppleHWId::kCpuFamily_CYCLONE: + features.add(CpuFeatures::ARM::kARMv8a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + break; + + // Apple A8 - ARMv8.0-A. + case AppleHWId::kCpuFamily_TYPHOON: + features.add(CpuFeatures::ARM::kARMv8a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + break; + + // Apple A9 - ARMv8.0-A. + case AppleHWId::kCpuFamily_TWISTER: + features.add(CpuFeatures::ARM::kARMv8a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + break; + + // Apple A10 - ARMv8.1-A. + case AppleHWId::kCpuFamily_HURRICANE: + features.add(CpuFeatures::ARM::kARMv8_1a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kRDM, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + + break; + + // Apple A11 - ARMv8.2-A. + case AppleHWId::kCpuFamily_MONSOON_MISTRAL: + features.add(CpuFeatures::ARM::kARMv8_2a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kFP16FULL, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + break; + + // Apple A12 - ARMv8.3-A. + case AppleHWId::kCpuFamily_VORTEX_TEMPEST: + features.add(CpuFeatures::ARM::kARMv8_3a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kFP16FULL, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2); + break; + + // Apple A13 - ARMv8.4-A. + case AppleHWId::kCpuFamily_LIGHTNING_THUNDER: + features.add(CpuFeatures::ARM::kARMv8_4a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kFP16FML, + CpuFeatures::ARM::kFP16FULL, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2, + CpuFeatures::ARM::kSHA3, + CpuFeatures::ARM::kSHA512); + break; + + // Apple A14/M1 - ARMv8.5-A. + case AppleHWId::kCpuFamily_FIRESTORM_ICESTORM: + features.add(CpuFeatures::ARM::kARMv8_4a, + CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kALTNZCV, + CpuFeatures::ARM::kFP16FML, + CpuFeatures::ARM::kFP16FULL, + CpuFeatures::ARM::kFRINT, + CpuFeatures::ARM::kSB, + CpuFeatures::ARM::kSHA1, + CpuFeatures::ARM::kSHA2, + CpuFeatures::ARM::kSHA3, + CpuFeatures::ARM::kSHA512, + CpuFeatures::ARM::kSSBS); + break; + + default: + cpu._wasDetected = false; + break; + } + + expandARMFeaturesByVersion(cpu); +} + +// CpuInfo - Detect - ARM [Unknown] +// ================================ + +#else + +#if ASMJIT_ARCH_ARM == 64 + #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with AArch64 CPU)") +#else + #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown OS with ARM CPU)") +#endif + +static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept { + populateBaseARMFeatures(cpu); + detectARMFeaturesViaCompilerFlags(cpu); + expandARMFeaturesByVersion(cpu); +} +#endif + +#endif + +// CpuInfo - Detect - Host +// ======================= static uint32_t cpuInfoInitialized; static CpuInfo cpuInfoGlobal(Globals::NoInit); const CpuInfo& CpuInfo::host() noexcept { - // This should never cause a problem as the resulting information should - // always be the same. + // This should never cause a problem as the resulting information should always be the same. In the worst case we + // would just overwrite it non-atomically. if (!cpuInfoInitialized) { CpuInfo cpuInfoLocal; -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 - x86::detectCpu(cpuInfoLocal); -#endif + cpuInfoLocal._arch = Arch::kHost; + cpuInfoLocal._subArch = SubArch::kHost; -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM - arm::detectCpu(cpuInfoLocal); +#if ASMJIT_ARCH_X86 + detectX86Cpu(cpuInfoLocal); +#elif ASMJIT_ARCH_ARM + detectARMCpu(cpuInfoLocal); +#else + #pragma message("[asmjit] Disabling runtime CPU detection - unsupported OS/CPU combination (Unknown CPU)") #endif cpuInfoLocal._hwThreadCount = detectHWThreadCount(); diff --git a/src/asmjit/core/cpuinfo.h b/src/asmjit/core/cpuinfo.h index 83bb8c1..974fb3e 100644 --- a/src/asmjit/core/cpuinfo.h +++ b/src/asmjit/core/cpuinfo.h @@ -1,52 +1,679 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_CPUINFO_H_INCLUDED #define ASMJIT_CORE_CPUINFO_H_INCLUDED #include "../core/archtraits.h" -#include "../core/features.h" +#include "../core/environment.h" #include "../core/globals.h" #include "../core/string.h" +#include "../core/support.h" ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::CpuInfo] -// ============================================================================ +//! CPU features information. +//! +//! Each feature is represented by a single bit in an embedded bit array. +class CpuFeatures { +public: + //! A word that is used to represents feature bits. + typedef Support::BitWord BitWord; + //! Iterator that can iterate all CPU features set. + typedef Support::BitVectorIterator<BitWord> Iterator; + + //! \name Constants + //! \{ + + //! \cond INTERNAL + enum : uint32_t { + kMaxFeatures = 256, + kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits + }; + //! \endcond + + //! \} + + //! \name Data + //! \{ + + //! CPU features data. + struct Data { + //! \name Members + //! \{ + + //! Data bits. + Support::Array<BitWord, kNumBitWords> _bits; + + //! \} + + //! \name Overloaded Operators + //! \{ + + inline bool operator==(const Data& other) noexcept { return eq(other); } + inline bool operator!=(const Data& other) noexcept { return !eq(other); } + + //! \} + + //! \name Accessors + //! \{ + + //! Returns true if there are no features set. + inline bool empty() const noexcept { return _bits.aggregate<Support::Or>(0) == 0; } + + //! Returns all features as array of bitwords (see \ref Support::BitWord). + inline BitWord* bits() noexcept { return _bits.data(); } + //! Returns all features as array of bitwords (const). + inline const BitWord* bits() const noexcept { return _bits.data(); } + + //! Returns the number of BitWords returned by \ref bits(). + inline size_t bitWordCount() const noexcept { return kNumBitWords; } + + //! Returns \ref Support::BitVectorIterator, that can be used to iterate over all features efficiently. + inline Iterator iterator() const noexcept { return Iterator(_bits.data(), kNumBitWords); } + + //! Tests whether the feature `featureId` is present. + template<typename FeatureId> + ASMJIT_FORCE_INLINE bool has(const FeatureId& featureId) const noexcept { + ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); + + uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; + uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits; + + return bool((_bits[idx] >> bit) & 0x1); + } + + //! Tests whether all features as defined by `other` are present. + ASMJIT_FORCE_INLINE bool hasAll(const Data& other) const noexcept { + for (uint32_t i = 0; i < kNumBitWords; i++) + if ((_bits[i] & other._bits[i]) != other._bits[i]) + return false; + return true; + } + + //! \} + + //! \name Manipulation + //! \{ + + inline void reset() noexcept { _bits.fill(0); } + + //! Adds the given CPU `featureId` to the list of features. + template<typename FeatureId> + ASMJIT_FORCE_INLINE void add(const FeatureId& featureId) noexcept { + ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); + + uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; + uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits; + + _bits[idx] |= BitWord(1) << bit; + } + + template<typename FeatureId, typename... Args> + ASMJIT_FORCE_INLINE void add(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept { + add(featureId); + add(std::forward<Args>(otherFeatureIds)...); + } + + template<typename FeatureId> + ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId) noexcept { + ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); + + uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; + uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits; + + _bits[idx] |= BitWord(condition) << bit; + } + + template<typename FeatureId, typename... Args> + ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId, Args&&... otherFeatureIds) noexcept { + addIf(condition, featureId); + addIf(condition, std::forward<Args>(otherFeatureIds)...); + } + + //! Removes the given CPU `featureId` from the list of features. + template<typename FeatureId> + ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId) noexcept { + ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures); + + uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits; + uint32_t bit = uint32_t(featureId) % Support::kBitWordSizeInBits; + + _bits[idx] &= ~(BitWord(1) << bit); + } + + template<typename FeatureId, typename... Args> + ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept { + remove(featureId); + remove(std::forward<Args>(otherFeatureIds)...); + } + + //! Tests whether this CPU features data matches `other`. + ASMJIT_FORCE_INLINE bool eq(const Data& other) const noexcept { return _bits == other._bits; } + + //! \} + + }; + + //! X86 specific features data. + struct X86 : public Data { + //! X86 CPU feature identifiers. + enum Id : uint8_t { + // @EnumValuesBegin{"enum": "CpuFeatures::X86"}@ + kNone, //!< No feature (never set, used internally). + + kMT, //!< CPU has multi-threading capabilities. + kNX, //!< CPU has Not-Execute-Bit aka DEP (data-execution prevention). + k3DNOW, //!< CPU has 3DNOW (3DNOW base instructions) [AMD]. + k3DNOW2, //!< CPU has 3DNOW2 (enhanced 3DNOW) [AMD]. + kADX, //!< CPU has ADX (multi-precision add-carry instruction extensions). + kAESNI, //!< CPU has AESNI (AES encode/decode instructions). + kALTMOVCR8, //!< CPU has LOCK MOV R<->CR0 (supports `MOV R<->CR8` via `LOCK MOV R<->CR0` in 32-bit mode) [AMD]. + kAMX_BF16, //!< CPU has AMX_BF16 (advanced matrix extensions - BF16 instructions). + kAMX_INT8, //!< CPU has AMX_INT8 (advanced matrix extensions - INT8 instructions). + kAMX_TILE, //!< CPU has AMX_TILE (advanced matrix extensions). + kAVX, //!< CPU has AVX (advanced vector extensions). + kAVX2, //!< CPU has AVX2 (advanced vector extensions 2). + kAVX512_4FMAPS, //!< CPU has AVX512_FMAPS (FMA packed single). + kAVX512_4VNNIW, //!< CPU has AVX512_VNNIW (vector NN instructions word variable precision). + kAVX512_BF16, //!< CPU has AVX512_BF16 (BFLOAT16 support instruction). + kAVX512_BITALG, //!< CPU has AVX512_BITALG (VPOPCNT[B|W], VPSHUFBITQMB). + kAVX512_BW, //!< CPU has AVX512_BW (packed BYTE|WORD). + kAVX512_CDI, //!< CPU has AVX512_CDI (conflict detection). + kAVX512_DQ, //!< CPU has AVX512_DQ (packed DWORD|QWORD). + kAVX512_ERI, //!< CPU has AVX512_ERI (exponential and reciprocal). + kAVX512_F, //!< CPU has AVX512_F (AVX512 foundation). + kAVX512_FP16, //!< CPU has AVX512_FP16 (FP16 extensions). + kAVX512_IFMA, //!< CPU has AVX512_IFMA (integer fused-multiply-add using 52-bit precision). + kAVX512_PFI, //!< CPU has AVX512_PFI (prefetch instructions). + kAVX512_VBMI, //!< CPU has AVX512_VBMI (vector byte manipulation). + kAVX512_VBMI2, //!< CPU has AVX512_VBMI2 (vector byte manipulation 2). + kAVX512_VL, //!< CPU has AVX512_VL (vector length extensions). + kAVX512_VNNI, //!< CPU has AVX512_VNNI (vector neural network instructions). + kAVX512_VP2INTERSECT, //!< CPU has AVX512_VP2INTERSECT + kAVX512_VPOPCNTDQ, //!< CPU has AVX512_VPOPCNTDQ (VPOPCNT[D|Q] instructions). + kAVX_VNNI, //!< CPU has AVX_VNNI (VEX encoding of vpdpbusd/vpdpbusds/vpdpwssd/vpdpwssds). + kBMI, //!< CPU has BMI (bit manipulation instructions #1). + kBMI2, //!< CPU has BMI2 (bit manipulation instructions #2). + kCET_IBT, //!< CPU has CET-IBT (indirect branch tracking). + kCET_SS, //!< CPU has CET-SS. + kCLDEMOTE, //!< CPU has CLDEMOTE (cache line demote). + kCLFLUSH, //!< CPU has CLFUSH (Cache Line flush). + kCLFLUSHOPT, //!< CPU has CLFUSHOPT (Cache Line flush - optimized). + kCLWB, //!< CPU has CLWB. + kCLZERO, //!< CPU has CLZERO. + kCMOV, //!< CPU has CMOV (CMOV and FCMOV instructions). + kCMPXCHG16B, //!< CPU has CMPXCHG16B (compare-exchange 16 bytes) [X86_64]. + kCMPXCHG8B, //!< CPU has CMPXCHG8B (compare-exchange 8 bytes). + kENCLV, //!< CPU has ENCLV. + kENQCMD, //!< CPU has ENQCMD (enqueue stores). + kERMS, //!< CPU has ERMS (enhanced REP MOVSB/STOSB). + kF16C, //!< CPU has F16C. + kFMA, //!< CPU has FMA (fused-multiply-add 3 operand form). + kFMA4, //!< CPU has FMA4 (fused-multiply-add 4 operand form). + kFPU, //!< CPU has FPU (FPU support). + kFSGSBASE, //!< CPU has FSGSBASE. + kFXSR, //!< CPU has FXSR (FXSAVE/FXRSTOR instructions). + kFXSROPT, //!< CPU has FXSROTP (FXSAVE/FXRSTOR is optimized). + kGEODE, //!< CPU has GEODE extensions (3DNOW additions). + kGFNI, //!< CPU has GFNI (Galois field instructions). + kHLE, //!< CPU has HLE. + kHRESET, //!< CPU has HRESET. + kI486, //!< CPU has I486 features (I486+ support). + kLAHFSAHF, //!< CPU has LAHF/SAHF (LAHF/SAHF in 64-bit mode) [X86_64]. + kLWP, //!< CPU has LWP (lightweight profiling) [AMD]. + kLZCNT, //!< CPU has LZCNT (LZCNT instruction). + kMCOMMIT, //!< CPU has MCOMMIT (MCOMMIT instruction). + kMMX, //!< CPU has MMX (MMX base instructions). + kMMX2, //!< CPU has MMX2 (MMX extensions or MMX2). + kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions). + kMONITORX, //!< CPU has MONITORX (MONITORX/MWAITX instructions). + kMOVBE, //!< CPU has MOVBE (move with byte-order swap). + kMOVDIR64B, //!< CPU has MOVDIR64B (move 64 bytes as direct store). + kMOVDIRI, //!< CPU has MOVDIRI (move dword/qword as direct store). + kMPX, //!< CPU has MPX (memory protection extensions). + kMSR, //!< CPU has MSR (RDMSR/WRMSR instructions). + kMSSE, //!< CPU has MSSE (misaligned SSE support). + kOSXSAVE, //!< CPU has OSXSAVE (XSAVE enabled by OS). + kOSPKE, //!< CPU has OSPKE (PKE enabled by OS). + kPCLMULQDQ, //!< CPU has PCLMULQDQ (packed carry-less multiplication). + kPCONFIG, //!< CPU has PCONFIG (PCONFIG instruction). + kPOPCNT, //!< CPU has POPCNT (POPCNT instruction). + kPREFETCHW, //!< CPU has PREFETCHW. + kPREFETCHWT1, //!< CPU has PREFETCHWT1. + kPTWRITE, //!< CPU has PTWRITE. + kRDPID, //!< CPU has RDPID. + kRDPRU, //!< CPU has RDPRU. + kRDRAND, //!< CPU has RDRAND. + kRDSEED, //!< CPU has RDSEED. + kRDTSC, //!< CPU has RDTSC. + kRDTSCP, //!< CPU has RDTSCP. + kRTM, //!< CPU has RTM. + kSERIALIZE, //!< CPU has SERIALIZE. + kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions). + kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD]. + kSMAP, //!< CPU has SMAP (supervisor-mode access prevention). + kSMEP, //!< CPU has SMEP (supervisor-mode execution prevention). + kSMX, //!< CPU has SMX (safer mode extensions). + kSNP, //!< CPU has SNP. + kSSE, //!< CPU has SSE. + kSSE2, //!< CPU has SSE2. + kSSE3, //!< CPU has SSE3. + kSSE4_1, //!< CPU has SSE4.1. + kSSE4_2, //!< CPU has SSE4.2. + kSSE4A, //!< CPU has SSE4A [AMD]. + kSSSE3, //!< CPU has SSSE3. + kSVM, //!< CPU has SVM (virtualization) [AMD]. + kTBM, //!< CPU has TBM (trailing bit manipulation) [AMD]. + kTSX, //!< CPU has TSX. + kTSXLDTRK, //!< CPU has TSXLDTRK. + kUINTR, //!< CPU has UINTR (user interrupts). + kVAES, //!< CPU has VAES (vector AES 256|512 bit support). + kVMX, //!< CPU has VMX (virtualization) [INTEL]. + kVPCLMULQDQ, //!< CPU has VPCLMULQDQ (vector PCLMULQDQ 256|512-bit support). + kWAITPKG, //!< CPU has WAITPKG (UMONITOR, UMWAIT, TPAUSE). + kWBNOINVD, //!< CPU has WBNOINVD. + kXOP, //!< CPU has XOP (XOP instructions) [AMD]. + kXSAVE, //!< CPU has XSAVE. + kXSAVEC, //!< CPU has XSAVEC. + kXSAVEOPT, //!< CPU has XSAVEOPT. + kXSAVES, //!< CPU has XSAVES. + // @EnumValuesEnd@ + + kMaxValue = kXSAVES + }; + + #define ASMJIT_X86_FEATURE(FEATURE) \ + inline bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); } + + ASMJIT_X86_FEATURE(MT) + ASMJIT_X86_FEATURE(NX) + ASMJIT_X86_FEATURE(3DNOW) + ASMJIT_X86_FEATURE(3DNOW2) + ASMJIT_X86_FEATURE(ADX) + ASMJIT_X86_FEATURE(AESNI) + ASMJIT_X86_FEATURE(ALTMOVCR8) + ASMJIT_X86_FEATURE(AMX_BF16) + ASMJIT_X86_FEATURE(AMX_INT8) + ASMJIT_X86_FEATURE(AMX_TILE) + ASMJIT_X86_FEATURE(AVX) + ASMJIT_X86_FEATURE(AVX2) + ASMJIT_X86_FEATURE(AVX512_4FMAPS) + ASMJIT_X86_FEATURE(AVX512_4VNNIW) + ASMJIT_X86_FEATURE(AVX512_BF16) + ASMJIT_X86_FEATURE(AVX512_BITALG) + ASMJIT_X86_FEATURE(AVX512_BW) + ASMJIT_X86_FEATURE(AVX512_CDI) + ASMJIT_X86_FEATURE(AVX512_DQ) + ASMJIT_X86_FEATURE(AVX512_ERI) + ASMJIT_X86_FEATURE(AVX512_F) + ASMJIT_X86_FEATURE(AVX512_FP16) + ASMJIT_X86_FEATURE(AVX512_IFMA) + ASMJIT_X86_FEATURE(AVX512_PFI) + ASMJIT_X86_FEATURE(AVX512_VBMI) + ASMJIT_X86_FEATURE(AVX512_VBMI2) + ASMJIT_X86_FEATURE(AVX512_VL) + ASMJIT_X86_FEATURE(AVX512_VNNI) + ASMJIT_X86_FEATURE(AVX512_VP2INTERSECT) + ASMJIT_X86_FEATURE(AVX512_VPOPCNTDQ) + ASMJIT_X86_FEATURE(AVX_VNNI) + ASMJIT_X86_FEATURE(BMI) + ASMJIT_X86_FEATURE(BMI2) + ASMJIT_X86_FEATURE(CET_IBT) + ASMJIT_X86_FEATURE(CET_SS) + ASMJIT_X86_FEATURE(CLDEMOTE) + ASMJIT_X86_FEATURE(CLFLUSH) + ASMJIT_X86_FEATURE(CLFLUSHOPT) + ASMJIT_X86_FEATURE(CLWB) + ASMJIT_X86_FEATURE(CLZERO) + ASMJIT_X86_FEATURE(CMOV) + ASMJIT_X86_FEATURE(CMPXCHG16B) + ASMJIT_X86_FEATURE(CMPXCHG8B) + ASMJIT_X86_FEATURE(ENCLV) + ASMJIT_X86_FEATURE(ENQCMD) + ASMJIT_X86_FEATURE(ERMS) + ASMJIT_X86_FEATURE(F16C) + ASMJIT_X86_FEATURE(FMA) + ASMJIT_X86_FEATURE(FMA4) + ASMJIT_X86_FEATURE(FPU) + ASMJIT_X86_FEATURE(FSGSBASE) + ASMJIT_X86_FEATURE(FXSR) + ASMJIT_X86_FEATURE(FXSROPT) + ASMJIT_X86_FEATURE(GEODE) + ASMJIT_X86_FEATURE(GFNI) + ASMJIT_X86_FEATURE(HLE) + ASMJIT_X86_FEATURE(HRESET) + ASMJIT_X86_FEATURE(I486) + ASMJIT_X86_FEATURE(LAHFSAHF) + ASMJIT_X86_FEATURE(LWP) + ASMJIT_X86_FEATURE(LZCNT) + ASMJIT_X86_FEATURE(MCOMMIT) + ASMJIT_X86_FEATURE(MMX) + ASMJIT_X86_FEATURE(MMX2) + ASMJIT_X86_FEATURE(MONITOR) + ASMJIT_X86_FEATURE(MONITORX) + ASMJIT_X86_FEATURE(MOVBE) + ASMJIT_X86_FEATURE(MOVDIR64B) + ASMJIT_X86_FEATURE(MOVDIRI) + ASMJIT_X86_FEATURE(MPX) + ASMJIT_X86_FEATURE(MSR) + ASMJIT_X86_FEATURE(MSSE) + ASMJIT_X86_FEATURE(OSXSAVE) + ASMJIT_X86_FEATURE(OSPKE) + ASMJIT_X86_FEATURE(PCLMULQDQ) + ASMJIT_X86_FEATURE(PCONFIG) + ASMJIT_X86_FEATURE(POPCNT) + ASMJIT_X86_FEATURE(PREFETCHW) + ASMJIT_X86_FEATURE(PREFETCHWT1) + ASMJIT_X86_FEATURE(PTWRITE) + ASMJIT_X86_FEATURE(RDPID) + ASMJIT_X86_FEATURE(RDPRU) + ASMJIT_X86_FEATURE(RDRAND) + ASMJIT_X86_FEATURE(RDSEED) + ASMJIT_X86_FEATURE(RDTSC) + ASMJIT_X86_FEATURE(RDTSCP) + ASMJIT_X86_FEATURE(RTM) + ASMJIT_X86_FEATURE(SERIALIZE) + ASMJIT_X86_FEATURE(SHA) + ASMJIT_X86_FEATURE(SKINIT) + ASMJIT_X86_FEATURE(SMAP) + ASMJIT_X86_FEATURE(SMEP) + ASMJIT_X86_FEATURE(SMX) + ASMJIT_X86_FEATURE(SNP) + ASMJIT_X86_FEATURE(SSE) + ASMJIT_X86_FEATURE(SSE2) + ASMJIT_X86_FEATURE(SSE3) + ASMJIT_X86_FEATURE(SSE4_1) + ASMJIT_X86_FEATURE(SSE4_2) + ASMJIT_X86_FEATURE(SSE4A) + ASMJIT_X86_FEATURE(SSSE3) + ASMJIT_X86_FEATURE(SVM) + ASMJIT_X86_FEATURE(TBM) + ASMJIT_X86_FEATURE(TSX) + ASMJIT_X86_FEATURE(TSXLDTRK) + ASMJIT_X86_FEATURE(UINTR) + ASMJIT_X86_FEATURE(VAES) + ASMJIT_X86_FEATURE(VMX) + ASMJIT_X86_FEATURE(VPCLMULQDQ) + ASMJIT_X86_FEATURE(WAITPKG) + ASMJIT_X86_FEATURE(WBNOINVD) + ASMJIT_X86_FEATURE(XOP) + ASMJIT_X86_FEATURE(XSAVE) + ASMJIT_X86_FEATURE(XSAVEC) + ASMJIT_X86_FEATURE(XSAVEOPT) + ASMJIT_X86_FEATURE(XSAVES) + + #undef ASMJIT_X86_FEATURE + }; + + //! ARM specific features data. + struct ARM : public Data { + //! ARM CPU feature identifiers. + enum Id : uint8_t { + // @EnumValuesBegin{"enum": "CpuFeatures::ARM"}@ + kNone = 0, //!< No feature (never set, used internally). + kTHUMB, //!< THUMB v1 ISA. + kTHUMBv2, //!< THUMB v2 ISA. + + kARMv6, //!< ARMv6 ISA. + kARMv7, //!< ARMv7 ISA. + kARMv8a, //!< ARMv8-A ISA. + kARMv8_1a, //!< ARMv8.1-A ISA. + kARMv8_2a, //!< ARMv8.2-A ISA. + kARMv8_3a, //!< ARMv8.3-A ISA. + kARMv8_4a, //!< ARMv8.4-A ISA. + kARMv8_5a, //!< ARMv8.5-A ISA. + kARMv8_6a, //!< ARMv8.6-A ISA. + kARMv8_7a, //!< ARMv8.6-A ISA. + + kVFPv2, //!< CPU has VFPv2 instruction set. + kVFPv3, //!< CPU has VFPv3 instruction set. + kVFPv4, //!< CPU has VFPv4 instruction set. + kVFP_D32, //!< CPU has 32 VFP-D (64-bit) registers. + + kAES, //!< CPU has AES (AArch64 only). + kALTNZCV, //!< CPU has ALTNZCV (AArch64 only). + kASIMD, //!< CPU has Advanced SIMD (NEON on ARM/THUMB). + kBF16, //!< CPU has BF16 (AArch64 only). + kBTI, //!< CPU has BTI (branch target identification). + kCPUID, //!< CPU has accessible CPUID register (ID_AA64ZFR0_EL1). + kCRC32, //!< CPU has CRC32 . + kDGH, //!< CPU has DGH (AArch64 only). + kDIT, //!< CPU has data independent timing instructions (DIT). + kDOTPROD, //!< CPU has DOTPROD (SDOT/UDOT). + kEDSP, //!< CPU has EDSP (ARM/THUMB only). + kFCMA, //!< CPU has FCMA (FCADD/FCMLA). + kFJCVTZS, //!< CPU has FJCVTZS (AArch64 only). + kFLAGM, //!< CPU has FLAGM (AArch64 only). + kFP16CONV, //!< CPU has FP16 (half-float) conversion. + kFP16FML, //!< CPU has FMLAL{2}/FMLSL{2} + kFP16FULL, //!< CPU has full support for FP16. + kFRINT, //!< CPU has FRINT[32|64][X|Z] (AArch64 only). + kI8MM, //!< CPU has I8MM (AArch64 only). + kIDIVA, //!< CPU has hardware SDIV and UDIV (ARM mode). + kIDIVT, //!< CPU has hardware SDIV and UDIV (THUMB mode). + kLSE, //!< CPU has large system extensions (LSE) (AArch64 only). + kMTE, //!< CPU has MTE (AArch64 only). + kRCPC_IMMO, //!< CPU has RCPC_IMMO (AArch64 only). + kRDM, //!< CPU has RDM (AArch64 only). + kPMU, //!< CPU has PMU (AArch64 only). + kPMULL, //!< CPU has PMULL (AArch64 only). + kRNG, //!< CPU has random number generation (RNG). + kSB, //!< CPU has speculative barrier SB (AArch64 only). + kSHA1, //!< CPU has SHA1. + kSHA2, //!< CPU has SHA2. + kSHA3, //!< CPU has SHA3. + kSHA512, //!< CPU has SHA512. + kSM3, //!< CPU has SM3. + kSM4, //!< CPU has SM4. + kSSBS, //!< CPU has SSBS. + kSVE, //!< CPU has SVE (AArch64 only). + kSVE_BF16, //!< CPU has SVE-BF16 (AArch64 only). + kSVE_F32MM, //!< CPU has SVE-F32MM (AArch64 only). + kSVE_F64MM, //!< CPU has SVE-F64MM (AArch64 only). + kSVE_I8MM, //!< CPU has SVE-I8MM (AArch64 only). + kSVE_PMULL, //!< CPU has SVE-PMULL (AArch64 only). + kSVE2, //!< CPU has SVE2 (AArch64 only). + kSVE2_AES, //!< CPU has SVE2-AES (AArch64 only). + kSVE2_BITPERM, //!< CPU has SVE2-BITPERM (AArch64 only). + kSVE2_SHA3, //!< CPU has SVE2-SHA3 (AArch64 only). + kSVE2_SM4, //!< CPU has SVE2-SM4 (AArch64 only). + kTME, //!< CPU has transactional memory extensions (TME). + // @EnumValuesEnd@ + + kMaxValue = kTME + }; + + #define ASMJIT_ARM_FEATURE(FEATURE) \ + inline bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); } + + ASMJIT_ARM_FEATURE(THUMB) + ASMJIT_ARM_FEATURE(THUMBv2) + + ASMJIT_ARM_FEATURE(ARMv6) + ASMJIT_ARM_FEATURE(ARMv7) + ASMJIT_ARM_FEATURE(ARMv8a) + ASMJIT_ARM_FEATURE(ARMv8_1a) + ASMJIT_ARM_FEATURE(ARMv8_2a) + ASMJIT_ARM_FEATURE(ARMv8_3a) + ASMJIT_ARM_FEATURE(ARMv8_4a) + ASMJIT_ARM_FEATURE(ARMv8_5a) + ASMJIT_ARM_FEATURE(ARMv8_6a) + ASMJIT_ARM_FEATURE(ARMv8_7a) + + ASMJIT_ARM_FEATURE(VFPv2) + ASMJIT_ARM_FEATURE(VFPv3) + ASMJIT_ARM_FEATURE(VFPv4) + ASMJIT_ARM_FEATURE(VFP_D32) + + ASMJIT_ARM_FEATURE(AES) + ASMJIT_ARM_FEATURE(ALTNZCV) + ASMJIT_ARM_FEATURE(ASIMD) + ASMJIT_ARM_FEATURE(BF16) + ASMJIT_ARM_FEATURE(BTI) + ASMJIT_ARM_FEATURE(CPUID) + ASMJIT_ARM_FEATURE(CRC32) + ASMJIT_ARM_FEATURE(DGH) + ASMJIT_ARM_FEATURE(DIT) + ASMJIT_ARM_FEATURE(DOTPROD) + ASMJIT_ARM_FEATURE(EDSP) + ASMJIT_ARM_FEATURE(FCMA) + ASMJIT_ARM_FEATURE(FLAGM) + ASMJIT_ARM_FEATURE(FP16CONV) + ASMJIT_ARM_FEATURE(FP16FML) + ASMJIT_ARM_FEATURE(FP16FULL) + ASMJIT_ARM_FEATURE(FRINT) + ASMJIT_ARM_FEATURE(IDIVA) + ASMJIT_ARM_FEATURE(IDIVT) + ASMJIT_ARM_FEATURE(LSE) + ASMJIT_ARM_FEATURE(MTE) + ASMJIT_ARM_FEATURE(FJCVTZS) + ASMJIT_ARM_FEATURE(I8MM) + ASMJIT_ARM_FEATURE(RCPC_IMMO) + ASMJIT_ARM_FEATURE(RDM) + ASMJIT_ARM_FEATURE(PMU) + ASMJIT_ARM_FEATURE(PMULL) + ASMJIT_ARM_FEATURE(RNG) + ASMJIT_ARM_FEATURE(SB) + ASMJIT_ARM_FEATURE(SHA1) + ASMJIT_ARM_FEATURE(SHA2) + ASMJIT_ARM_FEATURE(SHA3) + ASMJIT_ARM_FEATURE(SHA512) + ASMJIT_ARM_FEATURE(SM3) + ASMJIT_ARM_FEATURE(SM4) + ASMJIT_ARM_FEATURE(SSBS) + ASMJIT_ARM_FEATURE(SVE) + ASMJIT_ARM_FEATURE(SVE_BF16) + ASMJIT_ARM_FEATURE(SVE_F32MM) + ASMJIT_ARM_FEATURE(SVE_F64MM) + ASMJIT_ARM_FEATURE(SVE_I8MM) + ASMJIT_ARM_FEATURE(SVE_PMULL) + ASMJIT_ARM_FEATURE(SVE2) + ASMJIT_ARM_FEATURE(SVE2_AES) + ASMJIT_ARM_FEATURE(SVE2_BITPERM) + ASMJIT_ARM_FEATURE(SVE2_SHA3) + ASMJIT_ARM_FEATURE(SVE2_SM4) + ASMJIT_ARM_FEATURE(TME) + + #undef ASMJIT_ARM_FEATURE + }; + + static_assert(uint32_t(X86::kMaxValue) < kMaxFeatures, "The number of X86 CPU features cannot exceed CpuFeatures::kMaxFeatures"); + static_assert(uint32_t(ARM::kMaxValue) < kMaxFeatures, "The number of ARM CPU features cannot exceed CpuFeatures::kMaxFeatures"); + + //! \} + + //! \name Members + //! \{ + + Data _data {}; + + //! \} + + //! \name Construction & Destruction + //! \{ + + inline CpuFeatures() noexcept {} + inline CpuFeatures(const CpuFeatures& other) noexcept = default; + inline explicit CpuFeatures(Globals::NoInit_) noexcept {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + inline CpuFeatures& operator=(const CpuFeatures& other) noexcept = default; + + inline bool operator==(const CpuFeatures& other) noexcept { return eq(other); } + inline bool operator!=(const CpuFeatures& other) noexcept { return !eq(other); } + + //! \} + + //! \name Accessors + //! \{ + + //! Returns true if there are no features set. + inline bool empty() const noexcept { return _data.empty(); } + + //! Casts this base class into a derived type `T`. + template<typename T = Data> + inline T& data() noexcept { return static_cast<T&>(_data); } + + //! Casts this base class into a derived type `T` (const). + template<typename T = Data> + inline const T& data() const noexcept { return static_cast<const T&>(_data); } + + //! Returns CpuFeatures::Data as \ref CpuFeatures::X86. + inline X86& x86() noexcept { return data<X86>(); } + //! Returns CpuFeatures::Data as \ref CpuFeatures::X86 (const). + inline const X86& x86() const noexcept { return data<X86>(); } + + //! Returns CpuFeatures::Data as \ref CpuFeatures::ARM. + inline ARM& arm() noexcept { return data<ARM>(); } + //! Returns CpuFeatures::Data as \ref CpuFeatures::ARM (const). + inline const ARM& arm() const noexcept { return data<ARM>(); } + + //! Returns all features as array of bitwords (see \ref Support::BitWord). + inline BitWord* bits() noexcept { return _data.bits(); } + //! Returns all features as array of bitwords (const). + inline const BitWord* bits() const noexcept { return _data.bits(); } + //! Returns the number of BitWords returned by \ref bits(). + inline size_t bitWordCount() const noexcept { return _data.bitWordCount(); } + + //! Returns \ref Support::BitVectorIterator, that can be used to iterate over all features efficiently. + inline Iterator iterator() const noexcept { return _data.iterator(); } + + //! Tests whether the feature `featureId` is present. + template<typename FeatureId> + inline bool has(const FeatureId& featureId) const noexcept { return _data.has(featureId); } + + //! Tests whether all features as defined by `other` are present. + inline bool hasAll(const CpuFeatures& other) const noexcept { return _data.hasAll(other._data); } + + //! \} + + //! \name Manipulation + //! \{ + + inline void reset() noexcept { _data.reset(); } + + //! Adds the given CPU `featureId` to the list of features. + template<typename... Args> + inline void add(Args&&... args) noexcept { return _data.add(std::forward<Args>(args)...); } + + //! Adds the given CPU `featureId` to the list of features if `condition` is true. + template<typename... Args> + inline void addIf(bool condition, Args&&... args) noexcept { return _data.addIf(condition, std::forward<Args>(args)...); } + + //! Removes the given CPU `featureId` from the list of features. + template<typename... Args> + inline void remove(Args&&... args) noexcept { return _data.remove(std::forward<Args>(args)...); } + + //! Tests whether this CPU features matches `other`. + inline bool eq(const CpuFeatures& other) const noexcept { return _data.eq(other._data); } + + //! \} +}; //! CPU information. class CpuInfo { public: + //! \name Members + //! \{ + //! Architecture. - uint8_t _arch; + Arch _arch; //! Sub-architecture. - uint8_t _subArch; + SubArch _subArch; + //! True if the CPU was detected, false if the detection failed or it's not available. + bool _wasDetected; //! Reserved for future use. - uint16_t _reserved; + uint8_t _reserved; //! CPU family ID. uint32_t _familyId; //! CPU model ID. @@ -69,7 +696,9 @@ public: //! CPU brand string. FixedString<64> _brand; //! CPU features. - BaseFeatures _features; + CpuFeatures _features; + + //! \} //! \name Construction & Destruction //! \{ @@ -83,10 +712,10 @@ public: //! Returns the host CPU information. ASMJIT_API static const CpuInfo& host() noexcept; - //! Initializes CpuInfo to the given architecture, see \ref Environment. - inline void initArch(uint32_t arch, uint32_t subArch = 0u) noexcept { - _arch = uint8_t(arch); - _subArch = uint8_t(subArch); + //! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively. + inline void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept { + _arch = arch; + _subArch = subArch; } inline void reset() noexcept { memset(this, 0, sizeof(*this)); } @@ -103,46 +732,76 @@ public: //! \name Accessors //! \{ - //! Returns the CPU architecture id, see \ref Environment::Arch. - inline uint32_t arch() const noexcept { return _arch; } - //! Returns the CPU architecture sub-id, see \ref Environment::SubArch. - inline uint32_t subArch() const noexcept { return _subArch; } + //! Returns the CPU architecture this information relates to. + inline Arch arch() const noexcept { return _arch; } + + //! Returns the CPU sub-architecture this information relates to. + inline SubArch subArch() const noexcept { return _subArch; } + + //! Returns whether the CPU was detected successfully. + //! + //! If the returned value is false it means that AsmJit either failed to detect the CPU or it doesn't have + //! implementation targeting the host architecture and operating system. + inline bool wasDetected() const noexcept { return _wasDetected; } //! Returns the CPU family ID. + //! + //! Family identifier matches the FamilyId read by using CPUID on X86 architecture. inline uint32_t familyId() const noexcept { return _familyId; } + //! Returns the CPU model ID. + //! + //! Family identifier matches the ModelId read by using CPUID on X86 architecture. + inline uint32_t modelId() const noexcept { return _modelId; } //! Returns the CPU brand id. + //! + //! Family identifier matches the BrandId read by using CPUID on X86 architecture. inline uint32_t brandId() const noexcept { return _brandId; } + //! Returns the CPU stepping. + //! + //! Family identifier matches the Stepping information read by using CPUID on X86 architecture. inline uint32_t stepping() const noexcept { return _stepping; } + //! Returns the processor type. + //! + //! Family identifier matches the ProcessorType read by using CPUID on X86 architecture. inline uint32_t processorType() const noexcept { return _processorType; } - //! Returns the number of maximum logical processors. + + //! Returns the maximum number of logical processors. inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; } //! Returns the size of a cache line flush. inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; } + //! Returns number of hardware threads available. inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; } - //! Returns the CPU vendor. + //! Returns a CPU vendor string. inline const char* vendor() const noexcept { return _vendor.str; } - //! Tests whether the CPU vendor is equal to `s`. + //! Tests whether the CPU vendor string is equal to `s`. inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); } - //! Returns the CPU brand string. + //! Returns a CPU brand string. inline const char* brand() const noexcept { return _brand.str; } - //! Returns all CPU features as `BaseFeatures`, cast to your arch-specific class - //! if needed. - template<typename T = BaseFeatures> - inline const T& features() const noexcept { return _features.as<T>(); } + //! Returns CPU features. + inline CpuFeatures& features() noexcept { return _features; } + //! Returns CPU features (const). + inline const CpuFeatures& features() const noexcept { return _features; } //! Tests whether the CPU has the given `feature`. - inline bool hasFeature(uint32_t featureId) const noexcept { return _features.has(featureId); } - //! Adds the given CPU `feature` to the list of this CpuInfo features. - inline CpuInfo& addFeature(uint32_t featureId) noexcept { _features.add(featureId); return *this; } + template<typename FeatureId> + inline bool hasFeature(const FeatureId& featureId) const noexcept { return _features.has(featureId); } + + //! Adds the given CPU `featureId` to the list of features. + template<typename... Args> + inline void addFeature(Args&&... args) noexcept { return _features.add(std::forward<Args>(args)...); } + + //! Removes the given CPU `featureId` from the list of features. + template<typename... Args> + inline void removeFeature(Args&&... args) noexcept { return _features.remove(std::forward<Args>(args)...); } //! \} }; diff --git a/src/asmjit/core/datatypes.h b/src/asmjit/core/datatypes.h deleted file mode 100644 index 2f6cc1e..0000000 --- a/src/asmjit/core/datatypes.h +++ /dev/null @@ -1,1071 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_DATATYPES_H_INCLUDED -#define ASMJIT_CORE_DATATYPES_H_INCLUDED - -#include "../core/globals.h" - -#ifndef ASMJIT_NO_DEPRECATED - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Data64] -// ============================================================================ - -//! 64-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data64 is deprecated and will be removed in the future") Data64 { - //! Array of eight 8-bit signed integers. - int8_t sb[8]; - //! Array of eight 8-bit unsigned integers. - uint8_t ub[8]; - //! Array of four 16-bit signed integers. - int16_t sw[4]; - //! Array of four 16-bit unsigned integers. - uint16_t uw[4]; - //! Array of two 32-bit signed integers. - int32_t sd[2]; - //! Array of two 32-bit unsigned integers. - uint32_t ud[2]; - //! Array of one 64-bit signed integer. - int64_t sq[1]; - //! Array of one 64-bit unsigned integer. - uint64_t uq[1]; - - //! Array of two SP-FP values. - float sf[2]; - //! Array of one DP-FP value. - double df[1]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all eight 8-bit signed integers. - static inline Data64 fromI8(int8_t x0) noexcept { - Data64 self; - self.setI8(x0); - return self; - } - - //! Sets all eight 8-bit unsigned integers. - static inline Data64 fromU8(uint8_t x0) noexcept { - Data64 self; - self.setU8(x0); - return self; - } - - //! Sets all eight 8-bit signed integers. - static inline Data64 fromI8( - int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) noexcept { - - Data64 self; - self.setI8(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 8-bit unsigned integers. - static inline Data64 fromU8( - uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) noexcept { - - Data64 self; - self.setU8(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 16-bit signed integers. - static inline Data64 fromI16(int16_t x0) noexcept { - Data64 self; - self.setI16(x0); - return self; - } - - //! Sets all four 16-bit unsigned integers. - static inline Data64 fromU16(uint16_t x0) noexcept { - Data64 self; - self.setU16(x0); - return self; - } - - //! Sets all four 16-bit signed integers. - static inline Data64 fromI16(int16_t x0, int16_t x1, int16_t x2, int16_t x3) noexcept { - Data64 self; - self.setI16(x0, x1, x2, x3); - return self; - } - - //! Sets all four 16-bit unsigned integers. - static inline Data64 fromU16(uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) noexcept { - Data64 self; - self.setU16(x0, x1, x2, x3); - return self; - } - - //! Sets all two 32-bit signed integers. - static inline Data64 fromI32(int32_t x0) noexcept { - Data64 self; - self.setI32(x0); - return self; - } - - //! Sets all two 32-bit unsigned integers. - static inline Data64 fromU32(uint32_t x0) noexcept { - Data64 self; - self.setU32(x0); - return self; - } - - //! Sets all two 32-bit signed integers. - static inline Data64 fromI32(int32_t x0, int32_t x1) noexcept { - Data64 self; - self.setI32(x0, x1); - return self; - } - - //! Sets all two 32-bit unsigned integers. - static inline Data64 fromU32(uint32_t x0, uint32_t x1) noexcept { - Data64 self; - self.setU32(x0, x1); - return self; - } - - //! Sets 64-bit signed integer. - static inline Data64 fromI64(int64_t x0) noexcept { - Data64 self; - self.setI64(x0); - return self; - } - - //! Sets 64-bit unsigned integer. - static inline Data64 fromU64(uint64_t x0) noexcept { - Data64 self; - self.setU64(x0); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF32(float x0) noexcept { - Data64 self; - self.setF32(x0); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF32(float x0, float x1) noexcept { - Data64 self; - self.setF32(x0, x1); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF64(double x0) noexcept { - Data64 self; - self.setF64(x0); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all eight 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all eight 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - } - } - - //! Sets all eight 8-bit signed integers. - inline void setI8( - int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) noexcept { - - sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; - sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7; - } - - //! Sets all eight 8-bit unsigned integers. - inline void setU8( - uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) noexcept { - - ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; - ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7; - } - - //! Sets all four 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all four 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - } - } - - //! Sets all four 16-bit signed integers. - inline void setI16(int16_t x0, int16_t x1, int16_t x2, int16_t x3) noexcept { - sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; - } - - //! Sets all four 16-bit unsigned integers. - inline void setU16(uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) noexcept { - uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; - } - - //! Sets all two 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - sd[0] = x0; sd[1] = x0; - } - - //! Sets all two 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - ud[0] = x0; ud[1] = x0; - } - - //! Sets all two 32-bit signed integers. - inline void setI32(int32_t x0, int32_t x1) noexcept { - sd[0] = x0; sd[1] = x1; - } - - //! Sets all two 32-bit unsigned integers. - inline void setU32(uint32_t x0, uint32_t x1) noexcept { - ud[0] = x0; ud[1] = x1; - } - - //! Sets 64-bit signed integer. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; - } - - //! Sets 64-bit unsigned integer. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; - } - - //! Sets all two SP-FP values. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; - } - - //! Sets all two SP-FP values. - inline void setF32(float x0, float x1) noexcept { - sf[0] = x0; sf[1] = x1; - } - - //! Sets all two SP-FP values. - inline void setF64(double x0) noexcept { - df[0] = x0; - } -}; - -// ============================================================================ -// [asmjit::Data128] -// ============================================================================ - -//! 128-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data128 is deprecated and will be removed in the future") Data128 { - //! Array of sixteen 8-bit signed integers. - int8_t sb[16]; - //! Array of sixteen 8-bit unsigned integers. - uint8_t ub[16]; - //! Array of eight 16-bit signed integers. - int16_t sw[8]; - //! Array of eight 16-bit unsigned integers. - uint16_t uw[8]; - //! Array of four 32-bit signed integers. - int32_t sd[4]; - //! Array of four 32-bit unsigned integers. - uint32_t ud[4]; - //! Array of two 64-bit signed integers. - int64_t sq[2]; - //! Array of two 64-bit unsigned integers. - uint64_t uq[2]; - - //! Array of four 32-bit single precision floating points. - float sf[4]; - //! Array of two 64-bit double precision floating points. - double df[2]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all sixteen 8-bit signed integers. - static inline Data128 fromI8(int8_t x0) noexcept { - Data128 self; - self.setI8(x0); - return self; - } - - //! Sets all sixteen 8-bit unsigned integers. - static inline Data128 fromU8(uint8_t x0) noexcept { - Data128 self; - self.setU8(x0); - return self; - } - - //! Sets all sixteen 8-bit signed integers. - static inline Data128 fromI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15) noexcept { - - Data128 self; - self.setI8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all sixteen 8-bit unsigned integers. - static inline Data128 fromU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) noexcept { - - Data128 self; - self.setU8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all eight 16-bit signed integers. - static inline Data128 fromI16(int16_t x0) noexcept { - Data128 self; - self.setI16(x0); - return self; - } - - //! Sets all eight 16-bit unsigned integers. - static inline Data128 fromU16(uint16_t x0) noexcept { - Data128 self; - self.setU16(x0); - return self; - } - - //! Sets all eight 16-bit signed integers. - static inline Data128 fromI16( - int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) noexcept { - - Data128 self; - self.setI16(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 16-bit unsigned integers. - static inline Data128 fromU16( - uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) noexcept { - - Data128 self; - self.setU16(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 32-bit signed integers. - static inline Data128 fromI32(int32_t x0) noexcept { - Data128 self; - self.setI32(x0); - return self; - } - - //! Sets all four 32-bit unsigned integers. - static inline Data128 fromU32(uint32_t x0) noexcept { - Data128 self; - self.setU32(x0); - return self; - } - - //! Sets all four 32-bit signed integers. - static inline Data128 fromI32(int32_t x0, int32_t x1, int32_t x2, int32_t x3) noexcept { - Data128 self; - self.setI32(x0, x1, x2, x3); - return self; - } - - //! Sets all four 32-bit unsigned integers. - static inline Data128 fromU32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept { - Data128 self; - self.setU32(x0, x1, x2, x3); - return self; - } - - //! Sets all two 64-bit signed integers. - static inline Data128 fromI64(int64_t x0) noexcept { - Data128 self; - self.setI64(x0); - return self; - } - - //! Sets all two 64-bit unsigned integers. - static inline Data128 fromU64(uint64_t x0) noexcept { - Data128 self; - self.setU64(x0); - return self; - } - - //! Sets all two 64-bit signed integers. - static inline Data128 fromI64(int64_t x0, int64_t x1) noexcept { - Data128 self; - self.setI64(x0, x1); - return self; - } - - //! Sets all two 64-bit unsigned integers. - static inline Data128 fromU64(uint64_t x0, uint64_t x1) noexcept { - Data128 self; - self.setU64(x0, x1); - return self; - } - - //! Sets all four SP-FP floats. - static inline Data128 fromF32(float x0) noexcept { - Data128 self; - self.setF32(x0); - return self; - } - - //! Sets all four SP-FP floats. - static inline Data128 fromF32(float x0, float x1, float x2, float x3) noexcept { - Data128 self; - self.setF32(x0, x1, x2, x3); - return self; - } - - //! Sets all two DP-FP floats. - static inline Data128 fromF64(double x0) noexcept { - Data128 self; - self.setF64(x0); - return self; - } - - //! Sets all two DP-FP floats. - static inline Data128 fromF64(double x0, double x1) noexcept { - Data128 self; - self.setF64(x0, x1); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all sixteen 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all sixteen 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - uq[1] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - } - } - - //! Sets all sixteen 8-bit signed integers. - inline void setI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15) noexcept { - - sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; - sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; - sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; - sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; - } - - //! Sets all sixteen 8-bit unsigned integers. - inline void setU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) noexcept { - - ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; - ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; - ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; - ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; - } - - //! Sets all eight 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - uq[1] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - } - } - - //! Sets all eight 16-bit signed integers. - inline void setI16( - int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) noexcept { - - sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; - sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7; - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16( - uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) noexcept { - - uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; - uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7; - } - - //! Sets all four 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - setU32(uint32_t(x0)); - } - - //! Sets all four 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t t = (uint64_t(x0) << 32) + x0; - uq[0] = t; - uq[1] = t; - } - else { - ud[0] = x0; - ud[1] = x0; - ud[2] = x0; - ud[3] = x0; - } - } - - //! Sets all four 32-bit signed integers. - inline void setI32(int32_t x0, int32_t x1, int32_t x2, int32_t x3) noexcept { - sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; - } - - //! Sets all four 32-bit unsigned integers. - inline void setU32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept { - ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; - } - - //! Sets all two 64-bit signed integers. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; sq[1] = x0; - } - - //! Sets all two 64-bit unsigned integers. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; uq[1] = x0; - } - - //! Sets all two 64-bit signed integers. - inline void setI64(int64_t x0, int64_t x1) noexcept { - sq[0] = x0; sq[1] = x1; - } - - //! Sets all two 64-bit unsigned integers. - inline void setU64(uint64_t x0, uint64_t x1) noexcept { - uq[0] = x0; uq[1] = x1; - } - - //! Sets all four SP-FP floats. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; - } - - //! Sets all four SP-FP floats. - inline void setF32(float x0, float x1, float x2, float x3) noexcept { - sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; - } - - //! Sets all two DP-FP floats. - inline void setF64(double x0) noexcept { - df[0] = x0; df[1] = x0; - } - - //! Sets all two DP-FP floats. - inline void setF64(double x0, double x1) noexcept { - df[0] = x0; df[1] = x1; - } -}; - -// ============================================================================ -// [asmjit::Data256] -// ============================================================================ - -//! 256-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data256 is deprecated and will be removed in the future") Data256 { - //! Array of thirty two 8-bit signed integers. - int8_t sb[32]; - //! Array of thirty two 8-bit unsigned integers. - uint8_t ub[32]; - //! Array of sixteen 16-bit signed integers. - int16_t sw[16]; - //! Array of sixteen 16-bit unsigned integers. - uint16_t uw[16]; - //! Array of eight 32-bit signed integers. - int32_t sd[8]; - //! Array of eight 32-bit unsigned integers. - uint32_t ud[8]; - //! Array of four 64-bit signed integers. - int64_t sq[4]; - //! Array of four 64-bit unsigned integers. - uint64_t uq[4]; - - //! Array of eight 32-bit single precision floating points. - float sf[8]; - //! Array of four 64-bit double precision floating points. - double df[4]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all thirty two 8-bit signed integers. - static inline Data256 fromI8(int8_t x0) noexcept { - Data256 self; - self.setI8(x0); - return self; - } - - //! Sets all thirty two 8-bit unsigned integers. - static inline Data256 fromU8(uint8_t x0) noexcept { - Data256 self; - self.setU8(x0); - return self; - } - - //! Sets all thirty two 8-bit signed integers. - static inline Data256 fromI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15, - int8_t x16, int8_t x17, int8_t x18, int8_t x19, - int8_t x20, int8_t x21, int8_t x22, int8_t x23, - int8_t x24, int8_t x25, int8_t x26, int8_t x27, - int8_t x28, int8_t x29, int8_t x30, int8_t x31) noexcept { - - Data256 self; - self.setI8( - x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, - x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); - return self; - } - - //! Sets all thirty two 8-bit unsigned integers. - static inline Data256 fromU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, - uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, - uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, - uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, - uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) noexcept { - - Data256 self; - self.setU8( - x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, - x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); - return self; - } - - //! Sets all sixteen 16-bit signed integers. - static inline Data256 fromI16(int16_t x0) noexcept { - Data256 self; - self.setI16(x0); - return self; - } - - //! Sets all sixteen 16-bit unsigned integers. - static inline Data256 fromU16(uint16_t x0) noexcept { - Data256 self; - self.setU16(x0); - return self; - } - - //! Sets all sixteen 16-bit signed integers. - static inline Data256 fromI16( - int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7 , - int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) noexcept { - - Data256 self; - self.setI16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all sixteen 16-bit unsigned integers. - static inline Data256 fromU16( - uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 , - uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) noexcept { - - Data256 self; - self.setU16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all eight 32-bit signed integers. - static inline Data256 fromI32(int32_t x0) noexcept { - Data256 self; - self.setI32(x0); - return self; - } - - //! Sets all eight 32-bit unsigned integers. - static inline Data256 fromU32(uint32_t x0) noexcept { - Data256 self; - self.setU32(x0); - return self; - } - - //! Sets all eight 32-bit signed integers. - static inline Data256 fromI32( - int32_t x0, int32_t x1, int32_t x2, int32_t x3, - int32_t x4, int32_t x5, int32_t x6, int32_t x7) noexcept { - - Data256 self; - self.setI32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 32-bit unsigned integers. - static inline Data256 fromU32( - uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept { - - Data256 self; - self.setU32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 64-bit signed integers. - static inline Data256 fromI64(int64_t x0) noexcept { - Data256 self; - self.setI64(x0); - return self; - } - - //! Sets all four 64-bit unsigned integers. - static inline Data256 fromU64(uint64_t x0) noexcept { - Data256 self; - self.setU64(x0); - return self; - } - - //! Sets all four 64-bit signed integers. - static inline Data256 fromI64(int64_t x0, int64_t x1, int64_t x2, int64_t x3) noexcept { - Data256 self; - self.setI64(x0, x1, x2, x3); - return self; - } - - //! Sets all four 64-bit unsigned integers. - static inline Data256 fromU64(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) noexcept { - Data256 self; - self.setU64(x0, x1, x2, x3); - return self; - } - - //! Sets all eight SP-FP floats. - static inline Data256 fromF32(float x0) noexcept { - Data256 self; - self.setF32(x0); - return self; - } - - //! Sets all eight SP-FP floats. - static inline Data256 fromF32( - float x0, float x1, float x2, float x3, - float x4, float x5, float x6, float x7) noexcept { - - Data256 self; - self.setF32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four DP-FP floats. - static inline Data256 fromF64(double x0) noexcept { - Data256 self; - self.setF64(x0); - return self; - } - - //! Sets all four DP-FP floats. - static inline Data256 fromF64(double x0, double x1, double x2, double x3) noexcept { - Data256 self; - self.setF64(x0, x1, x2, x3); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all thirty two 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all thirty two 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - ud[4] = xd; - ud[5] = xd; - ud[6] = xd; - ud[7] = xd; - } - } - - //! Sets all thirty two 8-bit signed integers. - inline void setI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15, - int8_t x16, int8_t x17, int8_t x18, int8_t x19, - int8_t x20, int8_t x21, int8_t x22, int8_t x23, - int8_t x24, int8_t x25, int8_t x26, int8_t x27, - int8_t x28, int8_t x29, int8_t x30, int8_t x31) noexcept { - - sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; - sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; - sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; - sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; - sb[16] = x16; sb[17] = x17; sb[18] = x18; sb[19] = x19; - sb[20] = x20; sb[21] = x21; sb[22] = x22; sb[23] = x23; - sb[24] = x24; sb[25] = x25; sb[26] = x26; sb[27] = x27; - sb[28] = x28; sb[29] = x29; sb[30] = x30; sb[31] = x31; - } - - //! Sets all thirty two 8-bit unsigned integers. - inline void setU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, - uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, - uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, - uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, - uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) noexcept { - - ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; - ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; - ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; - ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; - ub[16] = x16; ub[17] = x17; ub[18] = x18; ub[19] = x19; - ub[20] = x20; ub[21] = x21; ub[22] = x22; ub[23] = x23; - ub[24] = x24; ub[25] = x25; ub[26] = x26; ub[27] = x27; - ub[28] = x28; ub[29] = x29; ub[30] = x30; ub[31] = x31; - } - - //! Sets all sixteen 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - ud[4] = xd; - ud[5] = xd; - ud[6] = xd; - ud[7] = xd; - } - } - - //! Sets all sixteen 16-bit signed integers. - inline void setI16( - int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7, - int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) noexcept { - - sw[0 ] = x0 ; sw[1 ] = x1 ; sw[2 ] = x2 ; sw[3 ] = x3 ; - sw[4 ] = x4 ; sw[5 ] = x5 ; sw[6 ] = x6 ; sw[7 ] = x7 ; - sw[8 ] = x8 ; sw[9 ] = x9 ; sw[10] = x10; sw[11] = x11; - sw[12] = x12; sw[13] = x13; sw[14] = x14; sw[15] = x15; - } - - //! Sets all sixteen 16-bit unsigned integers. - inline void setU16( - uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7, - uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) noexcept { - - uw[0 ] = x0 ; uw[1 ] = x1 ; uw[2 ] = x2 ; uw[3 ] = x3 ; - uw[4 ] = x4 ; uw[5 ] = x5 ; uw[6 ] = x6 ; uw[7 ] = x7 ; - uw[8 ] = x8 ; uw[9 ] = x9 ; uw[10] = x10; uw[11] = x11; - uw[12] = x12; uw[13] = x13; uw[14] = x14; uw[15] = x15; - } - - //! Sets all eight 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - setU32(uint32_t(x0)); - } - - //! Sets all eight 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = (uint64_t(x0) << 32) + x0; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - ud[0] = x0; - ud[1] = x0; - ud[2] = x0; - ud[3] = x0; - ud[4] = x0; - ud[5] = x0; - ud[6] = x0; - ud[7] = x0; - } - } - - //! Sets all eight 32-bit signed integers. - inline void setI32( - int32_t x0, int32_t x1, int32_t x2, int32_t x3, - int32_t x4, int32_t x5, int32_t x6, int32_t x7) noexcept { - - sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; - sd[4] = x4; sd[5] = x5; sd[6] = x6; sd[7] = x7; - } - - //! Sets all eight 32-bit unsigned integers. - inline void setU32( - uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept { - - ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; - ud[4] = x4; ud[5] = x5; ud[6] = x6; ud[7] = x7; - } - - //! Sets all four 64-bit signed integers. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; sq[1] = x0; sq[2] = x0; sq[3] = x0; - } - - //! Sets all four 64-bit unsigned integers. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; uq[1] = x0; uq[2] = x0; uq[3] = x0; - } - - //! Sets all four 64-bit signed integers. - inline void setI64(int64_t x0, int64_t x1, int64_t x2, int64_t x3) noexcept { - sq[0] = x0; sq[1] = x1; sq[2] = x2; sq[3] = x3; - } - - //! Sets all four 64-bit unsigned integers. - inline void setU64(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) noexcept { - uq[0] = x0; uq[1] = x1; uq[2] = x2; uq[3] = x3; - } - - //! Sets all eight SP-FP floats. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; - sf[4] = x0; sf[5] = x0; sf[6] = x0; sf[7] = x0; - } - - //! Sets all eight SP-FP floats. - inline void setF32( - float x0, float x1, float x2, float x3, - float x4, float x5, float x6, float x7) noexcept { - - sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; - sf[4] = x4; sf[5] = x5; sf[6] = x6; sf[7] = x7; - } - - //! Sets all four DP-FP floats. - inline void setF64(double x0) noexcept { - df[0] = x0; df[1] = x0; df[2] = x0; df[3] = x0; - } - - //! Sets all four DP-FP floats. - inline void setF64(double x0, double x1, double x2, double x3) noexcept { - df[0] = x0; df[1] = x1; df[2] = x2; df[3] = x3; - } - - //! \} -}; - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_DEPRECATED -#endif // ASMJIT_CORE_DATATYPES_H_INCLUDED diff --git a/src/asmjit/core/emithelper.cpp b/src/asmjit/core/emithelper.cpp index a77211e..bcdf098 100644 --- a/src/asmjit/core/emithelper.cpp +++ b/src/asmjit/core/emithelper.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/archtraits.h" @@ -33,12 +15,11 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::BaseEmitHelper - Formatting] -// ============================================================================ +// BaseEmitHelper - Formatting +// =========================== #ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT -static void dumpFuncValue(String& sb, uint32_t arch, const FuncValue& value) noexcept { +static void dumpFuncValue(String& sb, Arch arch, const FuncValue& value) noexcept { Formatter::formatTypeId(sb, value.typeId()); sb.append('@'); @@ -59,7 +40,7 @@ static void dumpFuncValue(String& sb, uint32_t arch, const FuncValue& value) noe static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept { typedef FuncArgsContext::Var Var; - uint32_t arch = ctx.arch(); + Arch arch = ctx.arch(); uint32_t varCount = ctx.varCount(); for (uint32_t i = 0; i < varCount; i++) { @@ -80,9 +61,8 @@ static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept { } #endif -// ============================================================================ -// [asmjit::BaseEmitHelper - EmitArgsAssignment] -// ============================================================================ +// BaseEmitHelper - EmitArgsAssignment +// =================================== ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) { typedef FuncArgsContext::Var Var; @@ -95,7 +75,7 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram kWorkPostponed = 0x04 }; - uint32_t arch = frame.arch(); + Arch arch = frame.arch(); const ArchTraits& archTraits = ArchTraits::byArch(arch); RAConstraints constraints; @@ -112,11 +92,11 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram } #endif + auto& workData = ctx._workData; uint32_t varCount = ctx._varCount; - WorkData* workData = ctx._workData; - uint32_t saVarId = ctx._saVarId; - BaseReg sp = BaseReg::fromSignatureAndId(_emitter->_gpRegInfo.signature(), archTraits.spRegId()); + + BaseReg sp = BaseReg(_emitter->_gpSignature, archTraits.spRegId()); BaseReg sa = sp; if (frame.hasDynamicAlignment()) { @@ -126,10 +106,8 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId()); } - // -------------------------------------------------------------------------- // Register to stack and stack to stack moves must be first as now we have // the biggest chance of having as many as possible unassigned registers. - // -------------------------------------------------------------------------- if (ctx._stackDstMask) { // Base address of all arguments passed by stack. @@ -163,33 +141,32 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram if (cur.isReg() && !cur.isIndirect()) { WorkData& wd = workData[archTraits.regTypeToGroup(cur.regType())]; - uint32_t rId = cur.regId(); + uint32_t regId = cur.regId(); - reg.setSignatureAndId(archTraits.regTypeToSignature(cur.regType()), rId); - wd.unassign(varId, rId); + reg.setSignatureAndId(archTraits.regTypeToSignature(cur.regType()), regId); + wd.unassign(varId, regId); } else { - // Stack to reg move - tricky since we move stack to stack we can decide which - // register to use. In general we follow the rule that IntToInt moves will use - // GP regs with possibility to signature or zero extend, and all other moves will - // either use GP or VEC regs depending on the size of the move. - RegInfo rInfo = getSuitableRegForMemToMemMove(arch, out.typeId(), cur.typeId()); - if (ASMJIT_UNLIKELY(!rInfo.isValid())) + // Stack to reg move - tricky since we move stack to stack we can decide which register to use. In general + // we follow the rule that IntToInt moves will use GP regs with possibility to signature or zero extend, + // and all other moves will either use GP or VEC regs depending on the size of the move. + OperandSignature signature = getSuitableRegForMemToMemMove(arch, out.typeId(), cur.typeId()); + if (ASMJIT_UNLIKELY(!signature.isValid())) return DebugUtils::errored(kErrorInvalidState); - WorkData& wd = workData[rInfo.group()]; - uint32_t availableRegs = wd.availableRegs(); + WorkData& wd = workData[signature.regGroup()]; + RegMask availableRegs = wd.availableRegs(); if (ASMJIT_UNLIKELY(!availableRegs)) return DebugUtils::errored(kErrorInvalidState); - uint32_t rId = Support::ctz(availableRegs); - reg.setSignatureAndId(rInfo.signature(), rId); + uint32_t availableId = Support::ctz(availableRegs); + reg.setSignatureAndId(signature, availableId); ASMJIT_PROPAGATE(emitArgMove(reg, out.typeId(), srcStackPtr, cur.typeId())); } if (cur.isIndirect() && cur.isReg()) - workData[BaseReg::kGroupGp].unassign(varId, cur.regId()); + workData[RegGroup::kGp].unassign(varId, cur.regId()); // Register to stack move. ASMJIT_PROPAGATE(emitRegMove(dstStackPtr, reg, cur.typeId())); @@ -197,10 +174,7 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram } } - // -------------------------------------------------------------------------- - // Shuffle all registers that are currently assigned accordingly to target - // assignment. - // -------------------------------------------------------------------------- + // Shuffle all registers that are currently assigned accordingly to target assignment. uint32_t workFlags = kWorkNone; for (;;) { @@ -212,8 +186,8 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram FuncValue& cur = var.cur; FuncValue& out = var.out; - uint32_t curGroup = archTraits.regTypeToGroup(cur.regType()); - uint32_t outGroup = archTraits.regTypeToGroup(out.regType()); + RegGroup curGroup = archTraits.regTypeToGroup(cur.regType()); + RegGroup outGroup = archTraits.regTypeToGroup(out.regType()); uint32_t curId = cur.regId(); uint32_t outId = out.regId(); @@ -228,8 +202,8 @@ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& fram EmitMove: ASMJIT_PROPAGATE( emitArgMove( - BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(), - BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId())); + BaseReg(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(), + BaseReg(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId())); wd.reassign(varId, outId, curId); cur.initReg(out.regType(), outId, out.typeId()); @@ -244,15 +218,15 @@ EmitMove: if (!altVar.out.isInitialized() || (altVar.out.isReg() && altVar.out.regId() == curId)) { // Only few architectures provide swap operations, and only for few register groups. - if (archTraits.hasSwap(curGroup)) { - uint32_t highestType = Support::max(cur.regType(), altVar.cur.regType()); - if (Support::isBetween<uint32_t>(highestType, BaseReg::kTypeGp8Lo, BaseReg::kTypeGp16)) - highestType = BaseReg::kTypeGp32; + if (archTraits.hasInstRegSwap(curGroup)) { + RegType highestType = Support::max(cur.regType(), altVar.cur.regType()); + if (Support::isBetween(highestType, RegType::kGp8Lo, RegType::kGp16)) + highestType = RegType::kGp32; - uint32_t signature = archTraits.regTypeToSignature(highestType); + OperandSignature signature = archTraits.regTypeToSignature(highestType); ASMJIT_PROPAGATE( - emitRegSwap(BaseReg::fromSignatureAndId(signature, outId), - BaseReg::fromSignatureAndId(signature, curId))); + emitRegSwap(BaseReg(signature, outId), BaseReg(signature, curId))); + wd.swap(varId, curId, altId, outId); cur.setRegId(outId); var.markDone(); @@ -264,9 +238,9 @@ EmitMove: } else { // If there is a scratch register it can be used to perform the swap. - uint32_t availableRegs = wd.availableRegs(); + RegMask availableRegs = wd.availableRegs(); if (availableRegs) { - uint32_t inOutRegs = wd.dstRegs(); + RegMask inOutRegs = wd.dstRegs(); if (availableRegs & ~inOutRegs) availableRegs &= ~inOutRegs; outId = Support::ctz(availableRegs); @@ -294,10 +268,8 @@ EmitMove: workFlags = (workFlags & kWorkDidSome) ? kWorkNone : kWorkPostponed; } - // -------------------------------------------------------------------------- // Load arguments passed by stack into registers. This is pretty simple and // it never requires multiple iterations like the previous phase. - // -------------------------------------------------------------------------- if (ctx._hasStackSrc) { uint32_t iterCount = 1; @@ -317,12 +289,12 @@ EmitMove: ASMJIT_ASSERT(var.out.isReg()); uint32_t outId = var.out.regId(); - uint32_t outType = var.out.regType(); + RegType outType = var.out.regType(); - uint32_t group = archTraits.regTypeToGroup(outType); - WorkData& wd = ctx._workData[group]; + RegGroup group = archTraits.regTypeToGroup(outType); + WorkData& wd = workData[group]; - if (outId == sa.id() && group == BaseReg::kGroupGp) { + if (outId == sa.id() && group == RegGroup::kGp) { // This register will be processed last as we still need `saRegId`. if (iterCount == 1) { iterCount++; @@ -331,7 +303,7 @@ EmitMove: wd.unassign(wd._physToVarId[outId], outId); } - BaseReg dstReg = BaseReg::fromSignatureAndId(archTraits.regTypeToSignature(outType), outId); + BaseReg dstReg = BaseReg(archTraits.regTypeToSignature(outType), outId); BaseMem srcMem = baseArgPtr.cloneAdjusted(var.cur.stackOffset()); ASMJIT_PROPAGATE(emitArgMove( diff --git a/src/asmjit/core/emithelper_p.h b/src/asmjit/core/emithelper_p.h index cb8ddf0..0333959 100644 --- a/src/asmjit/core/emithelper_p.h +++ b/src/asmjit/core/emithelper_p.h @@ -1,26 +1,7 @@ - -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors +// This file is part of AsmJit project <https://asmjit.com> // -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_EMITHELPER_P_H_INCLUDED #define ASMJIT_CORE_EMITHELPER_P_H_INCLUDED @@ -35,10 +16,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::BaseEmitHelper] -// ============================================================================ - //! Helper class that provides utilities for each supported architecture. class BaseEmitHelper { public: @@ -50,12 +27,11 @@ public: inline BaseEmitter* emitter() const noexcept { return _emitter; } inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; } - //! Emits a pure move operation between two registers or the same type or - //! between a register and its home slot. This function does not handle - //! register conversion. + //! Emits a pure move operation between two registers or the same type or between a register and its home + //! slot. This function does not handle register conversion. virtual Error emitRegMove( const Operand_& dst_, - const Operand_& src_, uint32_t typeId, const char* comment = nullptr) = 0; + const Operand_& src_, TypeId typeId, const char* comment = nullptr) = 0; //! Emits swap between two registers. virtual Error emitRegSwap( @@ -64,13 +40,12 @@ public: //! Emits move from a function argument (either register or stack) to a register. //! - //! This function can handle the necessary conversion from one argument to - //! another, and from one register type to another, if it's possible. Any - //! attempt of conversion that requires third register of a different group + //! This function can handle the necessary conversion from one argument to another, and from one register type + //! to another, if it's possible. Any attempt of conversion that requires third register of a different group //! (for example conversion from K to MMX on X86/X64) will fail. virtual Error emitArgMove( - const BaseReg& dst_, uint32_t dstTypeId, - const Operand_& src_, uint32_t srcTypeId, const char* comment = nullptr) = 0; + const BaseReg& dst_, TypeId dstTypeId, + const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) = 0; Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); }; diff --git a/src/asmjit/core/emitter.cpp b/src/asmjit/core/emitter.cpp index 2877dc8..38061b5 100644 --- a/src/asmjit/core/emitter.cpp +++ b/src/asmjit/core/emitter.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/emitterutils_p.h" @@ -39,91 +21,85 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::BaseEmitter - Construction / Destruction] -// ============================================================================ +// BaseEmitter - Construction & Destruction +// ======================================== -BaseEmitter::BaseEmitter(uint32_t emitterType) noexcept - : _emitterType(uint8_t(emitterType)) {} +BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept + : _emitterType(emitterType) {} BaseEmitter::~BaseEmitter() noexcept { if (_code) { - _addEmitterFlags(kFlagDestroyed); + _addEmitterFlags(EmitterFlags::kDestroyed); _code->detach(this); } } -// ============================================================================ -// [asmjit::BaseEmitter - Finalize] -// ============================================================================ +// BaseEmitter - Finalize +// ====================== Error BaseEmitter::finalize() { // Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`. return kErrorOk; } -// ============================================================================ -// [asmjit::BaseEmitter - Internals] -// ============================================================================ +// BaseEmitter - Internals +// ======================= -static constexpr uint32_t kEmitterPreservedFlags = BaseEmitter::kFlagOwnLogger | BaseEmitter::kFlagOwnErrorHandler; +static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler; static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept { bool emitComments = false; - bool hasValidationOptions = false; + bool hasDiagnosticOptions = false; - if (self->emitterType() == BaseEmitter::kTypeAssembler) { + if (self->emitterType() == EmitterType::kAssembler) { // Assembler: Don't emit comments if logger is not attached. emitComments = self->_code != nullptr && self->_logger != nullptr; - hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionAssembler); + hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateAssembler); } else { // Builder/Compiler: Always emit comments, we cannot assume they won't be used. emitComments = self->_code != nullptr; - hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate); + hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate); } if (emitComments) - self->_addEmitterFlags(BaseEmitter::kFlagLogComments); + self->_addEmitterFlags(EmitterFlags::kLogComments); else - self->_clearEmitterFlags(BaseEmitter::kFlagLogComments); + self->_clearEmitterFlags(EmitterFlags::kLogComments); - // The reserved option tells emitter (Assembler/Builder/Compiler) that there - // may be either a border case (CodeHolder not attached, for example) or that - // logging or validation is required. - if (self->_code == nullptr || self->_logger || hasValidationOptions) - self->_forcedInstOptions |= BaseInst::kOptionReserved; + // The reserved option tells emitter (Assembler/Builder/Compiler) that there may be either a border + // case (CodeHolder not attached, for example) or that logging or validation is required. + if (self->_code == nullptr || self->_logger || hasDiagnosticOptions) + self->_forcedInstOptions |= InstOptions::kReserved; else - self->_forcedInstOptions &= ~BaseInst::kOptionReserved; + self->_forcedInstOptions &= ~InstOptions::kReserved; } -// ============================================================================ -// [asmjit::BaseEmitter - Validation Options] -// ============================================================================ +// BaseEmitter - Diagnostic Options +// ================================ -void BaseEmitter::addValidationOptions(uint32_t options) noexcept { - _validationOptions = uint8_t(_validationOptions | options); +void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options) noexcept { + _diagnosticOptions |= options; BaseEmitter_updateForcedOptions(this); } -void BaseEmitter::clearValidationOptions(uint32_t options) noexcept { - _validationOptions = uint8_t(_validationOptions | options); +void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options) noexcept { + _diagnosticOptions &= ~options; BaseEmitter_updateForcedOptions(this); } -// ============================================================================ -// [asmjit::BaseEmitter - Logging] -// ============================================================================ +// BaseEmitter - Logging +// ===================== void BaseEmitter::setLogger(Logger* logger) noexcept { #ifndef ASMJIT_NO_LOGGING if (logger) { _logger = logger; - _addEmitterFlags(kFlagOwnLogger); + _addEmitterFlags(EmitterFlags::kOwnLogger); } else { _logger = nullptr; - _clearEmitterFlags(kFlagOwnLogger); + _clearEmitterFlags(EmitterFlags::kOwnLogger); if (_code) _logger = _code->logger(); } @@ -133,18 +109,17 @@ void BaseEmitter::setLogger(Logger* logger) noexcept { #endif } -// ============================================================================ -// [asmjit::BaseEmitter - Error Handling] -// ============================================================================ +// BaseEmitter - Error Handling +// ============================ void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept { if (errorHandler) { _errorHandler = errorHandler; - _addEmitterFlags(kFlagOwnErrorHandler); + _addEmitterFlags(EmitterFlags::kOwnErrorHandler); } else { _errorHandler = nullptr; - _clearEmitterFlags(kFlagOwnErrorHandler); + _clearEmitterFlags(EmitterFlags::kOwnErrorHandler); if (_code) _errorHandler = _code->errorHandler(); } @@ -160,58 +135,55 @@ Error BaseEmitter::reportError(Error err, const char* message) { return err; } -// ============================================================================ -// [asmjit::BaseEmitter - Labels] -// ============================================================================ +// BaseEmitter - Labels +// ==================== Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept { - return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : uint32_t(Globals::kInvalidId)); + return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId); } bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept { return _code && labelId < _code->labelCount(); } -// ============================================================================ -// [asmjit::BaseEmitter - Emit (Low-Level)] -// ============================================================================ +// BaseEmitter - Emit (Low-Level) +// ============================== using EmitterUtils::noExt; -Error BaseEmitter::_emitI(uint32_t instId) { +Error BaseEmitter::_emitI(InstId instId) { return _emit(instId, noExt[0], noExt[1], noExt[2], noExt); } -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0) { +Error BaseEmitter::_emitI(InstId instId, const Operand_& o0) { return _emit(instId, o0, noExt[1], noExt[2], noExt); } -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1) { +Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1) { return _emit(instId, o0, o1, noExt[2], noExt); } -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) { +Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) { return _emit(instId, o0, o1, o2, noExt); } -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) { +Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) { Operand_ opExt[3] = { o3 }; return _emit(instId, o0, o1, o2, opExt); } -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) { +Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) { Operand_ opExt[3] = { o3, o4 }; return _emit(instId, o0, o1, o2, opExt); } -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) { +Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) { Operand_ opExt[3] = { o3, o4, o5 }; return _emit(instId, o0, o1, o2, opExt); } -Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) { +Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) { const Operand_* op = operands; - Operand_ opExt[3]; switch (opCount) { @@ -247,9 +219,8 @@ Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_ } } -// ============================================================================ -// [asmjit::BaseEmitter - Emit (High-Level)] -// ============================================================================ +// BaseEmitter - Emit (High-Level) +// =============================== ASMJIT_FAVOR_SIZE Error BaseEmitter::emitProlog(const FuncFrame& frame) { if (ASMJIT_UNLIKELY(!_code)) @@ -314,13 +285,12 @@ ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, return DebugUtils::errored(kErrorInvalidArch); } -// ============================================================================ -// [asmjit::BaseEmitter - Comment] -// ============================================================================ +// BaseEmitter - Comment +// ===================== Error BaseEmitter::commentf(const char* fmt, ...) { - if (!hasEmitterFlag(kFlagLogComments)) { - if (!hasEmitterFlag(kFlagAttached)) + if (!hasEmitterFlag(EmitterFlags::kLogComments)) { + if (!hasEmitterFlag(EmitterFlags::kAttached)) return reportError(DebugUtils::errored(kErrorNotInitialized)); return kErrorOk; } @@ -342,8 +312,8 @@ Error BaseEmitter::commentf(const char* fmt, ...) { } Error BaseEmitter::commentv(const char* fmt, va_list ap) { - if (!hasEmitterFlag(kFlagLogComments)) { - if (!hasEmitterFlag(kFlagAttached)) + if (!hasEmitterFlag(EmitterFlags::kLogComments)) { + if (!hasEmitterFlag(EmitterFlags::kAttached)) return reportError(DebugUtils::errored(kErrorNotInitialized)); return kErrorOk; } @@ -360,18 +330,17 @@ Error BaseEmitter::commentv(const char* fmt, va_list ap) { #endif } -// ============================================================================ -// [asmjit::BaseEmitter - Events] -// ============================================================================ +// BaseEmitter - Events +// ==================== Error BaseEmitter::onAttach(CodeHolder* code) noexcept { _code = code; _environment = code->environment(); - _addEmitterFlags(kFlagAttached); + _addEmitterFlags(EmitterFlags::kAttached); const ArchTraits& archTraits = ArchTraits::byArch(code->arch()); - uint32_t nativeRegType = Environment::is32Bit(code->arch()) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; - _gpRegInfo.setSignature(archTraits._regInfo[nativeRegType].signature()); + RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64; + _gpSignature = archTraits.regTypeToSignature(nativeRegType); onSettingsUpdated(); return kErrorOk; @@ -387,13 +356,13 @@ Error BaseEmitter::onDetach(CodeHolder* code) noexcept { _errorHandler = nullptr; _clearEmitterFlags(~kEmitterPreservedFlags); - _forcedInstOptions = BaseInst::kOptionReserved; + _forcedInstOptions = InstOptions::kReserved; _privateData = 0; _environment.reset(); - _gpRegInfo.reset(); + _gpSignature.reset(); - _instOptions = 0; + _instOptions = InstOptions::kNone; _extraReg.reset(); _inlineComment = nullptr; diff --git a/src/asmjit/core/emitter.h b/src/asmjit/core/emitter.h index 44cda70..17a98ba 100644 --- a/src/asmjit/core/emitter.h +++ b/src/asmjit/core/emitter.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_EMITTER_H_INCLUDED #define ASMJIT_CORE_EMITTER_H_INCLUDED @@ -35,41 +17,203 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class ConstPool; class FuncFrame; class FuncArgsAssignment; -// ============================================================================ -// [asmjit::BaseEmitter] -// ============================================================================ +//! Align mode, used by \ref BaseEmitter::align(). +enum class AlignMode : uint8_t { + //! Align executable code. + kCode = 0, + //! Align non-executable code. + kData = 1, + //! Align by a sequence of zeros. + kZero = 2, + + //! Maximum value of `AlignMode`. + kMaxValue = kZero +}; + +//! Emitter type used by \ref BaseEmitter. +enum class EmitterType : uint8_t { + //! Unknown or uninitialized. + kNone = 0, + //! Emitter inherits from \ref BaseAssembler. + kAssembler = 1, + //! Emitter inherits from \ref BaseBuilder. + kBuilder = 2, + //! Emitter inherits from \ref BaseCompiler. + kCompiler = 3, + + //! Maximum value of `EmitterType`. + kMaxValue = kCompiler +}; + +//! Emitter flags, used by \ref BaseEmitter. +enum class EmitterFlags : uint8_t { + //! No flags. + kNone = 0u, + //! Emitter is attached to CodeHolder. + kAttached = 0x01u, + //! The emitter must emit comments. + kLogComments = 0x08u, + //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder). + kOwnLogger = 0x10u, + //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder). + kOwnErrorHandler = 0x20u, + //! The emitter was finalized. + kFinalized = 0x40u, + //! The emitter was destroyed. + //! + //! This flag is used for a very short time when an emitter is being destroyed by + //! CodeHolder. + kDestroyed = 0x80u +}; +ASMJIT_DEFINE_ENUM_FLAGS(EmitterFlags) + +//! Encoding options. +enum class EncodingOptions : uint32_t { + //! No encoding options. + kNone = 0, + + //! Emit instructions that are optimized for size, if possible. + //! + //! Default: false. + //! + //! X86 Specific + //! ------------ + //! + //! When this option is set it the assembler will try to fix instructions if possible into operation equivalent + //! instructions that take less bytes by taking advantage of implicit zero extension. For example instruction + //! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm` and `and r32, imm` when the + //! immediate constant is lesser than `2^31`. + kOptimizeForSize = 0x00000001u, + + //! Emit optimized code-alignment sequences. + //! + //! Default: false. + //! + //! X86 Specific + //! ------------ + //! + //! Default align sequence used by X86 architecture is one-byte (0x90) opcode that is often shown by disassemblers + //! as NOP. However there are more optimized align sequences for 2-11 bytes that may execute faster on certain CPUs. + //! If this feature is enabled AsmJit will generate specialized sequences for alignment between 2 to 11 bytes. + kOptimizedAlign = 0x00000002u, + + //! Emit jump-prediction hints. + //! + //! Default: false. + //! + //! X86 Specific + //! ------------ + //! + //! Jump prediction is usually based on the direction of the jump. If the jump is backward it is usually predicted as + //! taken; and if the jump is forward it is usually predicted as not-taken. The reason is that loops generally use + //! backward jumps and conditions usually use forward jumps. However this behavior can be overridden by using + //! instruction prefixes. If this option is enabled these hints will be emitted. + //! + //! This feature is disabled by default, because the only processor that used to take into consideration prediction + //! hints was P4. Newer processors implement heuristics for branch prediction and ignore static hints. This means + //! that this feature can be only used for annotation purposes. + kPredictedJumps = 0x00000010u +}; +ASMJIT_DEFINE_ENUM_FLAGS(EncodingOptions) + +//! Diagnostic options are used to tell emitters and their passes to perform diagnostics when emitting or processing +//! user code. These options control validation and extra diagnostics that can be performed by higher level emitters. +//! +//! Instruction Validation +//! ---------------------- +//! +//! \ref BaseAssembler implementation perform by default only basic checks that are necessary to identify all +//! variations of an instruction so the correct encoding can be selected. This is fine for production-ready code +//! as the assembler doesn't have to perform checks that would slow it down. However, sometimes these checks are +//! beneficial especially when the project that uses AsmJit is in a development phase, in which mistakes happen +//! often. To make the experience of using AsmJit seamless it offers validation features that can be controlled +//! by \ref DiagnosticOptions. +//! +//! Compiler Diagnostics +//! -------------------- +//! +//! Diagnostic options work with \ref BaseCompiler passes (precisely with its register allocation pass). These options +//! can be used to enable logging of all operations that the Compiler does. +enum class DiagnosticOptions : uint32_t { + //! No validation options. + kNone = 0, + + //! Perform strict validation in \ref BaseAssembler::emit() implementations. + //! + //! This flag ensures that each instruction is checked before it's encoded into a binary representation. This flag + //! is only relevant for \ref BaseAssembler implementations, but can be set in any other emitter type, in that case + //! if that emitter needs to create an assembler on its own, for the purpose of \ref BaseEmitter::finalize() it + //! would propagate this flag to such assembler so all instructions passed to it are explicitly validated. + //! + //! Default: false. + kValidateAssembler = 0x00000001u, + + //! Perform strict validation in \ref BaseBuilder::emit() and \ref BaseCompiler::emit() implementations. + //! + //! This flag ensures that each instruction is checked before an \ref InstNode representing the instruction is + //! created by \ref BaseBuilder or \ref BaseCompiler. This option could be more useful than \ref kValidateAssembler + //! in cases in which there is an invalid instruction passed to an assembler, which was invalid much earlier, most + //! likely when such instruction was passed to Builder/Compiler. + //! + //! This is a separate option that was introduced, because it's possible to manipulate the instruction stream + //! emitted by \ref BaseBuilder and \ref BaseCompiler - this means that it's allowed to emit invalid instructions + //! (for example with missing operands) that will be fixed later before finalizing it. + //! + //! Default: false. + kValidateIntermediate = 0x00000002u, + + //! Annotate all nodes processed by register allocator (Compiler/RA). + //! + //! \note Annotations don't need debug options, however, some debug options like `kRADebugLiveness` may influence + //! their output (for example the mentioned option would add liveness information to per-instruction annotation). + kRAAnnotate = 0x00000080u, + + //! Debug CFG generation and other related algorithms / operations (Compiler/RA). + kRADebugCFG = 0x00000100u, + + //! Debug liveness analysis (Compiler/RA). + kRADebugLiveness = 0x00000200u, + + //! Debug register allocation assignment (Compiler/RA). + kRADebugAssignment = 0x00000400u, + + //! Debug the removal of code part of unreachable blocks. + kRADebugUnreachable = 0x00000800u, -//! Provides a base foundation to emit code - specialized by `Assembler` and -//! `BaseBuilder`. + //! Enable all debug options (Compiler/RA). + kRADebugAll = 0x0000FF00u, +}; +ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions) + +//! Provides a base foundation to emitting code - specialized by \ref BaseAssembler and \ref BaseBuilder. class ASMJIT_VIRTAPI BaseEmitter { public: ASMJIT_BASE_CLASS(BaseEmitter) + //! \name Members + //! \{ + //! See \ref EmitterType. - uint8_t _emitterType = 0; - //! See \ref BaseEmitter::EmitterFlags. - uint8_t _emitterFlags = 0; - //! Validation flags in case validation is used, see \ref InstAPI::ValidationFlags. + EmitterType _emitterType = EmitterType::kNone; + //! See \ref EmitterFlags. + EmitterFlags _emitterFlags = EmitterFlags::kNone; + //! Validation flags in case validation is used. //! - //! \note Validation flags are specific to the emitter and they are setup at - //! construction time and then never changed. - uint8_t _validationFlags = 0; - //! Validation options, see \ref ValidationOptions. - uint8_t _validationOptions = 0; + //! \note Validation flags are specific to the emitter and they are setup at construction time and then never + //! changed. + ValidationFlags _validationFlags = ValidationFlags::kNone; + //! Validation options. + DiagnosticOptions _diagnosticOptions = DiagnosticOptions::kNone; - //! Encoding options, see \ref EncodingOptions. - uint32_t _encodingOptions = 0; + //! Encoding options. + EncodingOptions _encodingOptions = EncodingOptions::kNone; //! Forced instruction options, combined with \ref _instOptions by \ref emit(). - uint32_t _forcedInstOptions = BaseInst::kOptionReserved; + InstOptions _forcedInstOptions = InstOptions::kReserved; //! Internal private data used freely by any emitter. uint32_t _privateData = 0; @@ -83,143 +227,21 @@ public: //! Describes the target environment, matches \ref CodeHolder::environment(). Environment _environment {}; //! Native GP register signature and signature related information. - RegInfo _gpRegInfo {}; + OperandSignature _gpSignature {}; //! Next instruction options (affects the next instruction). - uint32_t _instOptions = 0; + InstOptions _instOptions = InstOptions::kNone; //! Extra register (op-mask {k} on AVX-512) (affects the next instruction). RegOnly _extraReg {}; //! Inline comment of the next instruction (affects the next instruction). const char* _inlineComment = nullptr; - //! Emitter type. - enum EmitterType : uint32_t { - //! Unknown or uninitialized. - kTypeNone = 0, - //! Emitter inherits from \ref BaseAssembler. - kTypeAssembler = 1, - //! Emitter inherits from \ref BaseBuilder. - kTypeBuilder = 2, - //! Emitter inherits from \ref BaseCompiler. - kTypeCompiler = 3, - - //! Count of emitter types. - kTypeCount = 4 - }; - - //! Emitter flags. - enum EmitterFlags : uint32_t { - //! Emitter is attached to CodeHolder. - kFlagAttached = 0x01u, - //! The emitter must emit comments. - kFlagLogComments = 0x08u, - //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder). - kFlagOwnLogger = 0x10u, - //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder). - kFlagOwnErrorHandler = 0x20u, - //! The emitter was finalized. - kFlagFinalized = 0x40u, - //! The emitter was destroyed. - kFlagDestroyed = 0x80u - }; - - //! Encoding options. - enum EncodingOptions : uint32_t { - //! Emit instructions that are optimized for size, if possible. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! When this option is set it the assembler will try to fix instructions - //! if possible into operation equivalent instructions that take less bytes - //! by taking advantage of implicit zero extension. For example instruction - //! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm` - //! and `and r32, imm` when the immediate constant is lesser than `2^31`. - kEncodingOptionOptimizeForSize = 0x00000001u, - - //! Emit optimized code-alignment sequences. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! Default align sequence used by X86 architecture is one-byte (0x90) - //! opcode that is often shown by disassemblers as NOP. However there are - //! more optimized align sequences for 2-11 bytes that may execute faster - //! on certain CPUs. If this feature is enabled AsmJit will generate - //! specialized sequences for alignment between 2 to 11 bytes. - kEncodingOptionOptimizedAlign = 0x00000002u, - - //! Emit jump-prediction hints. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! Jump prediction is usually based on the direction of the jump. If the - //! jump is backward it is usually predicted as taken; and if the jump is - //! forward it is usually predicted as not-taken. The reason is that loops - //! generally use backward jumps and conditions usually use forward jumps. - //! However this behavior can be overridden by using instruction prefixes. - //! If this option is enabled these hints will be emitted. - //! - //! This feature is disabled by default, because the only processor that - //! used to take into consideration prediction hints was P4. Newer processors - //! implement heuristics for branch prediction and ignore static hints. This - //! means that this feature can be only used for annotation purposes. - kEncodingOptionPredictedJumps = 0x00000010u - }; - -#ifndef ASMJIT_NO_DEPRECATED - enum EmitterOptions : uint32_t { - kOptionOptimizedForSize = kEncodingOptionOptimizeForSize, - kOptionOptimizedAlign = kEncodingOptionOptimizedAlign, - kOptionPredictedJumps = kEncodingOptionPredictedJumps - }; -#endif - - //! Validation options are used to tell emitters to perform strict validation - //! of instructions passed to \ref emit(). - //! - //! \ref BaseAssembler implementation perform by default only basic checks - //! that are necessary to identify all variations of an instruction so the - //! correct encoding can be selected. This is fine for production-ready code - //! as the assembler doesn't have to perform checks that would slow it down. - //! However, sometimes these checks are beneficial especially when the project - //! that uses AsmJit is in a development phase, in which mistakes happen often. - //! To make the experience of using AsmJit seamless it offers validation - //! features that can be controlled by `ValidationOptions`. - enum ValidationOptions : uint32_t { - //! Perform strict validation in \ref BaseAssembler::emit() implementations. - //! - //! This flag ensures that each instruction is checked before it's encoded - //! into a binary representation. This flag is only relevant for \ref - //! BaseAssembler implementations, but can be set in any other emitter type, - //! in that case if that emitter needs to create an assembler on its own, - //! for the purpose of \ref finalize() it would propagate this flag to such - //! assembler so all instructions passed to it are explicitly validated. - //! - //! Default: false. - kValidationOptionAssembler = 0x00000001u, - - //! Perform strict validation in \ref BaseBuilder::emit() and \ref - //! BaseCompiler::emit() implementations. - //! - //! This flag ensures that each instruction is checked before an \ref - //! InstNode representing the instruction is created by Builder or Compiler. - //! - //! Default: false. - kValidationOptionIntermediate = 0x00000002u - }; + //! \} //! \name Construction & Destruction //! \{ - ASMJIT_API explicit BaseEmitter(uint32_t emitterType) noexcept; + ASMJIT_API explicit BaseEmitter(EmitterType emitterType) noexcept; ASMJIT_API virtual ~BaseEmitter() noexcept; //! \} @@ -239,28 +261,28 @@ public: //! \{ //! Returns the type of this emitter, see `EmitterType`. - inline uint32_t emitterType() const noexcept { return _emitterType; } + inline EmitterType emitterType() const noexcept { return _emitterType; } //! Returns emitter flags , see `Flags`. - inline uint32_t emitterFlags() const noexcept { return _emitterFlags; } + inline EmitterFlags emitterFlags() const noexcept { return _emitterFlags; } //! Tests whether the emitter inherits from `BaseAssembler`. - inline bool isAssembler() const noexcept { return _emitterType == kTypeAssembler; } + inline bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; } //! Tests whether the emitter inherits from `BaseBuilder`. //! //! \note Both Builder and Compiler emitters would return `true`. - inline bool isBuilder() const noexcept { return _emitterType >= kTypeBuilder; } + inline bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); } //! Tests whether the emitter inherits from `BaseCompiler`. - inline bool isCompiler() const noexcept { return _emitterType == kTypeCompiler; } + inline bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; } //! Tests whether the emitter has the given `flag` enabled. - inline bool hasEmitterFlag(uint32_t flag) const noexcept { return (_emitterFlags & flag) != 0; } + inline bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); } //! Tests whether the emitter is finalized. - inline bool isFinalized() const noexcept { return hasEmitterFlag(kFlagFinalized); } + inline bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); } //! Tests whether the emitter is destroyed (only used during destruction). - inline bool isDestroyed() const noexcept { return hasEmitterFlag(kFlagDestroyed); } + inline bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); } - inline void _addEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags | flags); } - inline void _clearEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags & ~flags); } + inline void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; } + inline void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; } //! \} @@ -270,7 +292,7 @@ public: //! Returns the CodeHolder this emitter is attached to. inline CodeHolder* code() const noexcept { return _code; } - //! Returns the target environment, see \ref Environment. + //! Returns the target environment. //! //! The returned \ref Environment reference matches \ref CodeHolder::environment(). inline const Environment& environment() const noexcept { return _environment; } @@ -281,9 +303,9 @@ public: inline bool is64Bit() const noexcept { return environment().is64Bit(); } //! Returns the target architecture type. - inline uint32_t arch() const noexcept { return environment().arch(); } + inline Arch arch() const noexcept { return environment().arch(); } //! Returns the target architecture sub-type. - inline uint32_t subArch() const noexcept { return environment().subArch(); } + inline SubArch subArch() const noexcept { return environment().subArch(); } //! Returns the target architecture's GP register size (4 or 8 bytes). inline uint32_t registerSize() const noexcept { return environment().registerSize(); } @@ -298,12 +320,10 @@ public: //! Finalizes this emitter. //! - //! Materializes the content of the emitter by serializing it to the attached - //! \ref CodeHolder through an architecture specific \ref BaseAssembler. This - //! function won't do anything if the emitter inherits from \ref BaseAssembler - //! as assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder. - //! However, if this is an emitter that inherits from \ref BaseBuilder or \ref - //! BaseCompiler then these emitters need the materialization phase as they + //! Materializes the content of the emitter by serializing it to the attached \ref CodeHolder through an architecture + //! specific \ref BaseAssembler. This function won't do anything if the emitter inherits from \ref BaseAssembler as + //! assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder. However, if this is an emitter that + //! inherits from \ref BaseBuilder or \ref BaseCompiler then these emitters need the materialization phase as they //! store their content in a representation not visible to \ref CodeHolder. ASMJIT_API virtual Error finalize(); @@ -317,29 +337,27 @@ public: //! Tests whether the emitter has its own logger. //! - //! Own logger means that it overrides the possible logger that may be used - //! by \ref CodeHolder this emitter is attached to. - inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(kFlagOwnLogger); } + //! Own logger means that it overrides the possible logger that may be used by \ref CodeHolder this emitter is + //! attached to. + inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); } //! Returns the logger this emitter uses. //! - //! The returned logger is either the emitter's own logger or it's logger - //! used by \ref CodeHolder this emitter is attached to. + //! The returned logger is either the emitter's own logger or it's logger used by \ref CodeHolder this emitter + //! is attached to. inline Logger* logger() const noexcept { return _logger; } //! Sets or resets the logger of the emitter. //! - //! If the `logger` argument is non-null then the logger will be considered - //! emitter's own logger, see \ref hasOwnLogger() for more details. If the - //! given `logger` is null then the emitter will automatically use logger + //! If the `logger` argument is non-null then the logger will be considered emitter's own logger, see \ref + //! hasOwnLogger() for more details. If the given `logger` is null then the emitter will automatically use logger //! that is attached to the \ref CodeHolder this emitter is attached to. ASMJIT_API void setLogger(Logger* logger) noexcept; //! Resets the logger of this emitter. //! - //! The emitter will bail to using a logger attached to \ref CodeHolder this - //! emitter is attached to, or no logger at all if \ref CodeHolder doesn't - //! have one. + //! The emitter will bail to using a logger attached to \ref CodeHolder this emitter is attached to, or no logger + //! at all if \ref CodeHolder doesn't have one. inline void resetLogger() noexcept { return setLogger(nullptr); } //! \} @@ -352,14 +370,14 @@ public: //! Tests whether the emitter has its own error handler. //! - //! Own error handler means that it overrides the possible error handler that - //! may be used by \ref CodeHolder this emitter is attached to. - inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(kFlagOwnErrorHandler); } + //! Own error handler means that it overrides the possible error handler that may be used by \ref CodeHolder this + //! emitter is attached to. + inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); } //! Returns the error handler this emitter uses. //! - //! The returned error handler is either the emitter's own error handler or - //! it's error handler used by \ref CodeHolder this emitter is attached to. + //! The returned error handler is either the emitter's own error handler or it's error handler used by + //! \ref CodeHolder this emitter is attached to. inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } //! Sets or resets the error handler of the emitter. @@ -369,11 +387,9 @@ public: inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } //! Handles the given error in the following way: - //! 1. If the emitter has \ref ErrorHandler attached, it calls its - //! \ref ErrorHandler::handleError() member function first, and - //! then returns the error. The `handleError()` function may throw. - //! 2. if the emitter doesn't have \ref ErrorHandler, the error is - //! simply returned. + //! 1. If the emitter has \ref ErrorHandler attached, it calls its \ref ErrorHandler::handleError() member function + //! first, and then returns the error. The `handleError()` function may throw. + //! 2. if the emitter doesn't have \ref ErrorHandler, the error is simply returned. ASMJIT_API Error reportError(Error err, const char* message = nullptr); //! \} @@ -381,61 +397,51 @@ public: //! \name Encoding Options //! \{ - //! Returns encoding options, see \ref EncodingOptions. - inline uint32_t encodingOptions() const noexcept { return _encodingOptions; } + //! Returns encoding options. + inline EncodingOptions encodingOptions() const noexcept { return _encodingOptions; } //! Tests whether the encoding `option` is set. - inline bool hasEncodingOption(uint32_t option) const noexcept { return (_encodingOptions & option) != 0; } + inline bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); } - //! Enables the given encoding `options`, see \ref EncodingOptions. - inline void addEncodingOptions(uint32_t options) noexcept { _encodingOptions |= options; } - //! Disables the given encoding `options`, see \ref EncodingOptions. - inline void clearEncodingOptions(uint32_t options) noexcept { _encodingOptions &= ~options; } + //! Enables the given encoding `options`. + inline void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; } + //! Disables the given encoding `options`. + inline void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; } //! \} - //! \name Validation Options + //! \name Diagnostic Options //! \{ - //! Returns the emitter's validation options, see \ref ValidationOptions. - inline uint32_t validationOptions() const noexcept { - return _validationOptions; - } + //! Returns the emitter's diagnostic options. + inline DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; } - //! Tests whether the given `option` is present in validation options. - inline bool hasValidationOption(uint32_t option) const noexcept { - return (_validationOptions & option) != 0; - } + //! Tests whether the given `option` is present in the emitter's diagnostic options. + inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); } - //! Activates the given validation `options`, see \ref ValidationOptions. + //! Activates the given diagnostic `options`. //! - //! This function is used to activate explicit validation options that will - //! be then used by all emitter implementations. There are in general two - //! possibilities: + //! This function is used to activate explicit validation options that will be then used by all emitter + //! implementations. There are in general two possibilities: //! - //! - Architecture specific assembler is used. In this case a - //! \ref kValidationOptionAssembler can be used to turn on explicit - //! validation that will be used before an instruction is emitted. - //! This means that internally an extra step will be performed to - //! make sure that the instruction is correct. This is needed, because - //! by default assemblers prefer speed over strictness. + //! - Architecture specific assembler is used. In this case a \ref DiagnosticOptions::kValidateAssembler can be + //! used to turn on explicit validation that will be used before an instruction is emitted. This means that + //! internally an extra step will be performed to make sure that the instruction is correct. This is needed, + //! because by default assemblers prefer speed over strictness. //! //! This option should be used in debug builds as it's pretty expensive. //! - //! - Architecture specific builder or compiler is used. In this case - //! the user can turn on \ref kValidationOptionIntermediate option - //! that adds explicit validation step before the Builder or Compiler - //! creates an \ref InstNode to represent an emitted instruction. Error - //! will be returned if the instruction is ill-formed. In addition, - //! also \ref kValidationOptionAssembler can be used, which would not be - //! consumed by Builder / Compiler directly, but it would be propagated - //! to an architecture specific \ref BaseAssembler implementation it - //! creates during \ref BaseEmitter::finalize(). - ASMJIT_API void addValidationOptions(uint32_t options) noexcept; + //! - Architecture specific builder or compiler is used. In this case the user can turn on + //! \ref DiagnosticOptions::kValidateIntermediate option that adds explicit validation step before the Builder + //! or Compiler creates an \ref InstNode to represent an emitted instruction. Error will be returned if the + //! instruction is ill-formed. In addition, also \ref DiagnosticOptions::kValidateAssembler can be used, which + //! would not be consumed by Builder / Compiler directly, but it would be propagated to an architecture specific + //! \ref BaseAssembler implementation it creates during \ref BaseEmitter::finalize(). + ASMJIT_API void addDiagnosticOptions(DiagnosticOptions options) noexcept; //! Deactivates the given validation `options`. //! - //! See \ref addValidationOptions() and \ref ValidationOptions for more details. - ASMJIT_API void clearValidationOptions(uint32_t options) noexcept; + //! See \ref addDiagnosticOptions() and \ref DiagnosticOptions for more details. + ASMJIT_API void clearDiagnosticOptions(DiagnosticOptions options) noexcept; //! \} @@ -444,20 +450,19 @@ public: //! Returns forced instruction options. //! - //! Forced instruction options are merged with next instruction options before - //! the instruction is encoded. These options have some bits reserved that are - //! used by error handling, logging, and instruction validation purposes. Other - //! options are globals that affect each instruction. - inline uint32_t forcedInstOptions() const noexcept { return _forcedInstOptions; } + //! Forced instruction options are merged with next instruction options before the instruction is encoded. These + //! options have some bits reserved that are used by error handling, logging, and instruction validation purposes. + //! Other options are globals that affect each instruction. + inline InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; } //! Returns options of the next instruction. - inline uint32_t instOptions() const noexcept { return _instOptions; } + inline InstOptions instOptions() const noexcept { return _instOptions; } //! Returns options of the next instruction. - inline void setInstOptions(uint32_t options) noexcept { _instOptions = options; } + inline void setInstOptions(InstOptions options) noexcept { _instOptions = options; } //! Adds options of the next instruction. - inline void addInstOptions(uint32_t options) noexcept { _instOptions |= options; } + inline void addInstOptions(InstOptions options) noexcept { _instOptions |= options; } //! Resets options of the next instruction. - inline void resetInstOptions() noexcept { _instOptions = 0; } + inline void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; } //! Tests whether the extra register operand is valid. inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } @@ -474,9 +479,8 @@ public: inline const char* inlineComment() const noexcept { return _inlineComment; } //! Sets comment/annotation of the next instruction. //! - //! \note This string is set back to null by `_emit()`, but until that it has - //! to remain valid as the Emitter is not required to make a copy of it (and - //! it would be slow to do that for each instruction). + //! \note This string is set back to null by `_emit()`, but until that it has to remain valid as the Emitter is not + //! required to make a copy of it (and it would be slow to do that for each instruction). inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } //! Resets the comment/annotation to nullptr. inline void resetInlineComment() noexcept { _inlineComment = nullptr; } @@ -496,19 +500,19 @@ public: //! Creates a new label. virtual Label newLabel() = 0; //! Creates a new named label. - virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) = 0; + virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) = 0; + //! Creates a new anonymous label with a name, which can only be used for debugging purposes. + inline Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); } //! Creates a new external label. - inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { - return newNamedLabel(name, nameSize, Label::kTypeExternal); - } + inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); } //! Returns `Label` by `name`. //! //! Returns invalid Label in case that the name is invalid or label was not found. //! - //! \note This function doesn't trigger ErrorHandler in case the name is invalid - //! or no such label exist. You must always check the validity of the `Label` returned. + //! \note This function doesn't trigger ErrorHandler in case the name is invalid or no such label exist. You must + //! always check the validity of the `Label` returned. ASMJIT_API Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept; //! Binds the `label` to the current position of the current section. @@ -526,41 +530,39 @@ public: //! \name Emit //! \{ - // NOTE: These `emit()` helpers are designed to address a code-bloat generated - // by C++ compilers to call a function having many arguments. Each parameter to - // `_emit()` requires some code to pass it, which means that if we default to - // 5 arguments in `_emit()` and instId the C++ compiler would have to generate - // a virtual function call having 5 parameters and additional `this` argument, - // which is quite a lot. Since by default most instructions have 2 to 3 operands - // it's better to introduce helpers that pass from 0 to 6 operands that help to - // reduce the size of emit(...) function call. + // NOTE: These `emit()` helpers are designed to address a code-bloat generated by C++ compilers to call a function + // having many arguments. Each parameter to `_emit()` requires some code to pass it, which means that if we default + // to 5 arguments in `_emit()` and instId the C++ compiler would have to generate a virtual function call having 5 + // parameters and additional `this` argument, which is quite a lot. Since by default most instructions have 2 to 3 + // operands it's better to introduce helpers that pass from 0 to 6 operands that help to reduce the size of emit(...) + // function call. //! Emits an instruction (internal). - ASMJIT_API Error _emitI(uint32_t instId); + ASMJIT_API Error _emitI(InstId instId); //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0); + ASMJIT_API Error _emitI(InstId instId, const Operand_& o0); //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1); + ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1); //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2); + ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2); //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3); + ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3); //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4); + ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4); //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5); + ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5); //! Emits an instruction `instId` with the given `operands`. template<typename... Args> - ASMJIT_INLINE Error emit(uint32_t instId, Args&&... operands) { + ASMJIT_FORCE_INLINE Error emit(InstId instId, Args&&... operands) { return _emitI(instId, Support::ForwardOp<Args>::forward(operands)...); } - inline Error emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) { + ASMJIT_FORCE_INLINE Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) { return _emitOpArray(instId, operands, opCount); } - inline Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) { + ASMJIT_FORCE_INLINE Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) { setInstOptions(inst.options()); setExtraReg(inst.extraReg()); return _emitOpArray(inst.id(), operands, opCount); @@ -568,9 +570,9 @@ public: //! \cond INTERNAL //! Emits an instruction - all 6 operands must be defined. - virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0; + virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0; //! Emits instruction having operands stored in array. - ASMJIT_API virtual Error _emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount); + ASMJIT_API virtual Error _emitOpArray(InstId instId, const Operand_* operands, size_t opCount); //! \endcond //! \} @@ -589,9 +591,10 @@ public: //! Aligns the current CodeBuffer position to the `alignment` specified. //! - //! The sequence that is used to fill the gap between the aligned location - //! and the current location depends on the align `mode`, see \ref AlignMode. - virtual Error align(uint32_t alignMode, uint32_t alignment) = 0; + //! The sequence that is used to fill the gap between the aligned location and the current location depends on the + //! align `mode`, see \ref AlignMode. The `alignment` argument specifies alignment in bytes, so for example when + //! it's `32` it means that the code buffer will be aligned to `32` bytes. + virtual Error align(AlignMode alignMode, uint32_t alignment) = 0; //! \} @@ -604,49 +607,49 @@ public: //! Embeds a typed data array. //! //! This is the most flexible function for embedding data as it allows to: - //! - Assign a `typeId` to the data, so the emitter knows the type of - //! items stored in `data`. Binary data should use \ref Type::kIdU8. - //! - Repeat the given data `repeatCount` times, so the data can be used - //! as a fill pattern for example, or as a pattern used by SIMD instructions. - virtual Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0; + //! + //! - Assign a `typeId` to the data, so the emitter knows the type of items stored in `data`. Binary data should + //! use \ref TypeId::kUInt8. + //! + //! - Repeat the given data `repeatCount` times, so the data can be used as a fill pattern for example, or as a + //! pattern used by SIMD instructions. + virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0; //! Embeds int8_t `value` repeated by `repeatCount`. - inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI8, &value, 1, repeatCount); } + inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); } //! Embeds uint8_t `value` repeated by `repeatCount`. - inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU8, &value, 1, repeatCount); } + inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); } //! Embeds int16_t `value` repeated by `repeatCount`. - inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI16, &value, 1, repeatCount); } + inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); } //! Embeds uint16_t `value` repeated by `repeatCount`. - inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU16, &value, 1, repeatCount); } + inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); } //! Embeds int32_t `value` repeated by `repeatCount`. - inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI32, &value, 1, repeatCount); } + inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); } //! Embeds uint32_t `value` repeated by `repeatCount`. - inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU32, &value, 1, repeatCount); } + inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); } //! Embeds int64_t `value` repeated by `repeatCount`. - inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI64, &value, 1, repeatCount); } + inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); } //! Embeds uint64_t `value` repeated by `repeatCount`. - inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU64, &value, 1, repeatCount); } + inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); } //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(Type::kIdF32, &value, 1, repeatCount); } + inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); } //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(Type::IdOfT<double>::kTypeId, &value, 1, repeatCount); } + inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); } //! Embeds a constant pool at the current offset by performing the following: - //! 1. Aligns by using kAlignData to the minimum `pool` alignment. + //! 1. Aligns by using AlignMode::kData to the minimum `pool` alignment. //! 2. Binds the ConstPool label so it's bound to an aligned location. //! 3. Emits ConstPool content. virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0; //! Embeds an absolute `label` address as data. //! - //! The `dataSize` is an optional argument that can be used to specify the - //! size of the address data. If it's zero (default) the address size is - //! deduced from the target architecture (either 4 or 8 bytes). + //! The `dataSize` is an optional argument that can be used to specify the size of the address data. If it's zero + //! (default) the address size is deduced from the target architecture (either 4 or 8 bytes). virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0; - //! Embeds a delta (distance) between the `label` and `base` calculating it - //! as `label - base`. This function was designed to make it easier to embed - //! lookup tables where each index is a relative distance of two labels. + //! Embeds a delta (distance) between the `label` and `base` calculating it as `label - base`. This function was + //! designed to make it easier to embed lookup tables where each index is a relative distance of two labels. virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0; //! \} @@ -672,48 +675,20 @@ public: //! Called after the emitter was detached from `CodeHolder`. virtual Error onDetach(CodeHolder* code) noexcept = 0; - //! Called when \ref CodeHolder has updated an important setting, which - //! involves the following: + //! Called when \ref CodeHolder has updated an important setting, which involves the following: //! - //! - \ref Logger has been changed (\ref CodeHolder::setLogger() has been - //! called). - //! - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler() - //! has been called). + //! - \ref Logger has been changed (\ref CodeHolder::setLogger() has been called). //! - //! This function ensures that the settings are properly propagated from - //! \ref CodeHolder to the emitter. + //! - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler() has been called). //! - //! \note This function is virtual and can be overridden, however, if you - //! do so, always call \ref BaseEmitter::onSettingsUpdated() within your - //! own implementation to ensure that the emitter is in a consistent state. + //! This function ensures that the settings are properly propagated from \ref CodeHolder to the emitter. + //! + //! \note This function is virtual and can be overridden, however, if you do so, always call \ref + //! BaseEmitter::onSettingsUpdated() within your own implementation to ensure that the emitter is + //! in a consistent state. ASMJIT_API virtual void onSettingsUpdated() noexcept; //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use environment() instead") - inline CodeInfo codeInfo() const noexcept { - return CodeInfo(_environment, _code ? _code->baseAddress() : Globals::kNoBaseAddress); - } - - ASMJIT_DEPRECATED("Use arch() instead") - inline uint32_t archId() const noexcept { return arch(); } - - ASMJIT_DEPRECATED("Use registerSize() instead") - inline uint32_t gpSize() const noexcept { return registerSize(); } - - ASMJIT_DEPRECATED("Use encodingOptions() instead") - inline uint32_t emitterOptions() const noexcept { return encodingOptions(); } - - ASMJIT_DEPRECATED("Use addEncodingOptions() instead") - inline void addEmitterOptions(uint32_t options) noexcept { addEncodingOptions(options); } - - ASMJIT_DEPRECATED("Use clearEncodingOptions() instead") - inline void clearEmitterOptions(uint32_t options) noexcept { clearEncodingOptions(options); } - - ASMJIT_DEPRECATED("Use forcedInstOptions() instead") - inline uint32_t globalInstOptions() const noexcept { return forcedInstOptions(); } -#endif // !ASMJIT_NO_DEPRECATED }; //! \} diff --git a/src/asmjit/core/emitterutils.cpp b/src/asmjit/core/emitterutils.cpp index 1115934..ba79787 100644 --- a/src/asmjit/core/emitterutils.cpp +++ b/src/asmjit/core/emitterutils.cpp @@ -1,57 +1,33 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/assembler.h" #include "../core/emitterutils_p.h" -#include "../core/formatter.h" +#include "../core/formatter_p.h" #include "../core/logger.h" #include "../core/support.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::EmitterUtils] -// ============================================================================ - namespace EmitterUtils { #ifndef ASMJIT_NO_LOGGING -Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept { - size_t currentSize = sb.size(); - size_t commentSize = comment ? Support::strLen(comment, Globals::kMaxCommentSize) : 0; - - ASMJIT_ASSERT(binSize >= dispSize); +Error finishFormattedLine(String& sb, const FormatOptions& formatOptions, const uint8_t* binData, size_t binSize, size_t offsetSize, size_t immSize, const char* comment) noexcept { + ASMJIT_ASSERT(binSize >= offsetSize); const size_t kNoBinSize = SIZE_MAX; + size_t commentSize = comment ? Support::strLen(comment, Globals::kMaxCommentSize) : 0; + if ((binSize != 0 && binSize != kNoBinSize) || commentSize) { - size_t align = kMaxInstLineSize; char sep = ';'; + size_t padding = Formatter::paddingFromOptions(formatOptions, FormatPaddingGroup::kRegularLine); for (size_t i = (binSize == kNoBinSize); i < 2; i++) { - size_t begin = sb.size(); - ASMJIT_PROPAGATE(sb.padEnd(align)); + ASMJIT_PROPAGATE(sb.padEnd(padding)); if (sep) { ASMJIT_PROPAGATE(sb.append(sep)); @@ -60,8 +36,8 @@ Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t disp // Append binary data or comment. if (i == 0) { - ASMJIT_PROPAGATE(sb.appendHex(binData, binSize - dispSize - immSize)); - ASMJIT_PROPAGATE(sb.appendChars('.', dispSize * 2)); + ASMJIT_PROPAGATE(sb.appendHex(binData, binSize - offsetSize - immSize)); + ASMJIT_PROPAGATE(sb.appendChars('.', offsetSize * 2)); ASMJIT_PROPAGATE(sb.appendHex(binData + binSize - immSize, immSize)); if (commentSize == 0) break; } @@ -69,9 +45,8 @@ Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t disp ASMJIT_PROPAGATE(sb.append(comment, commentSize)); } - currentSize += sb.size() - begin; - align += kMaxBinarySize; sep = '|'; + padding += Formatter::paddingFromOptions(formatOptions, FormatPaddingGroup::kMachineCode); } } @@ -82,55 +57,59 @@ void logLabelBound(BaseAssembler* self, const Label& label) noexcept { Logger* logger = self->logger(); StringTmp<512> sb; - size_t binSize = logger->hasFlag(FormatOptions::kFlagMachineCode) ? size_t(0) : SIZE_MAX; + size_t binSize = logger->hasFlag(FormatFlags::kMachineCode) ? size_t(0) : SIZE_MAX; - sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationLabel)); + sb.appendChars(' ', logger->indentation(FormatIndentationGroup::kLabel)); Formatter::formatLabel(sb, logger->flags(), self, label.id()); sb.append(':'); - EmitterUtils::formatLine(sb, nullptr, binSize, 0, 0, self->_inlineComment); + finishFormattedLine(sb, logger->options(), nullptr, binSize, 0, 0, self->_inlineComment); logger->log(sb.data(), sb.size()); } void logInstructionEmitted( BaseAssembler* self, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, + InstId instId, + InstOptions options, + const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, uint32_t relSize, uint32_t immSize, uint8_t* afterCursor) { Logger* logger = self->logger(); ASMJIT_ASSERT(logger != nullptr); StringTmp<256> sb; - uint32_t flags = logger->flags(); + FormatFlags formatFlags = logger->flags(); uint8_t* beforeCursor = self->bufferPtr(); intptr_t emittedSize = (intptr_t)(afterCursor - beforeCursor); Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); + opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationCode)); - Formatter::formatInstruction(sb, flags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); + sb.appendChars(' ', logger->indentation(FormatIndentationGroup::kCode)); + Formatter::formatInstruction(sb, formatFlags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); - if ((flags & FormatOptions::kFlagMachineCode) != 0) - EmitterUtils::formatLine(sb, self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment()); + if (Support::test(formatFlags, FormatFlags::kMachineCode)) + finishFormattedLine(sb, logger->options(), self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment()); else - EmitterUtils::formatLine(sb, nullptr, SIZE_MAX, 0, 0, self->inlineComment()); + finishFormattedLine(sb, logger->options(), nullptr, SIZE_MAX, 0, 0, self->inlineComment()); logger->log(sb); } Error logInstructionFailed( BaseAssembler* self, Error err, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { + InstId instId, + InstOptions options, + const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { StringTmp<256> sb; sb.append(DebugUtils::errorAsString(err)); sb.append(": "); Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); + opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - Formatter::formatInstruction(sb, 0, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); + Formatter::formatInstruction(sb, FormatFlags::kNone, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); if (self->inlineComment()) { sb.append(" ; "); diff --git a/src/asmjit/core/emitterutils_p.h b/src/asmjit/core/emitterutils_p.h index 7e222d3..b7610e7 100644 --- a/src/asmjit/core/emitterutils_p.h +++ b/src/asmjit/core/emitterutils_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED #define ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED @@ -30,26 +12,26 @@ ASMJIT_BEGIN_NAMESPACE class BaseAssembler; +class FormatOptions; //! \cond INTERNAL //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::EmitterUtils] -// ============================================================================ - +//! Utilities used by various emitters, mostly Assembler implementations. namespace EmitterUtils { -static const Operand_ noExt[3] {}; +//! Default paddings used by Emitter utils and Formatter. + +static constexpr Operand noExt[3]; -enum kOpIndex { +enum kOpIndex : uint32_t { kOp3 = 0, kOp4 = 1, kOp5 = 2 }; -static ASMJIT_INLINE uint32_t opCountFromEmitArgs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { +static ASMJIT_FORCE_INLINE uint32_t opCountFromEmitArgs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { uint32_t opCount = 0; if (opExt[kOp3].isNone()) { @@ -67,7 +49,7 @@ static ASMJIT_INLINE uint32_t opCountFromEmitArgs(const Operand_& o0, const Oper return opCount; } -static ASMJIT_INLINE void opArrayFromEmitArgs(Operand_ dst[Globals::kMaxOpCount], const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { +static ASMJIT_FORCE_INLINE void opArrayFromEmitArgs(Operand_ dst[Globals::kMaxOpCount], const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { dst[0].copyFrom(o0); dst[1].copyFrom(o1); dst[2].copyFrom(o2); @@ -77,25 +59,23 @@ static ASMJIT_INLINE void opArrayFromEmitArgs(Operand_ dst[Globals::kMaxOpCount] } #ifndef ASMJIT_NO_LOGGING -enum : uint32_t { - // Has to be big to be able to hold all metadata compiler can assign to a - // single instruction. - kMaxInstLineSize = 44, - kMaxBinarySize = 26 -}; - -Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept; +Error finishFormattedLine(String& sb, const FormatOptions& formatOptions, const uint8_t* binData, size_t binSize, size_t offsetSize, size_t immSize, const char* comment) noexcept; void logLabelBound(BaseAssembler* self, const Label& label) noexcept; void logInstructionEmitted( BaseAssembler* self, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, + InstId instId, + InstOptions options, + const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, uint32_t relSize, uint32_t immSize, uint8_t* afterCursor); Error logInstructionFailed( BaseAssembler* self, - Error err, uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt); + Error err, + InstId instId, + InstOptions options, + const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt); #endif } diff --git a/src/asmjit/core/environment.cpp b/src/asmjit/core/environment.cpp index 3be2b15..9a694af 100644 --- a/src/asmjit/core/environment.cpp +++ b/src/asmjit/core/environment.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/environment.h" diff --git a/src/asmjit/core/environment.h b/src/asmjit/core/environment.h index 58e8734..8225ef2 100644 --- a/src/asmjit/core/environment.h +++ b/src/asmjit/core/environment.h @@ -1,30 +1,12 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ENVIRONMENT_H_INCLUDED #define ASMJIT_CORE_ENVIRONMENT_H_INCLUDED -#include "../core/globals.h" +#include "../core/archtraits.h" #if defined(__APPLE__) #include <TargetConditionals.h> @@ -35,301 +17,222 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::Environment] -// ============================================================================ - -//! Represents an environment, which is usually related to a \ref Target. -//! -//! Environment has usually an 'arch-subarch-vendor-os-abi' format, which is -//! sometimes called "Triple" (historically it used to be 3 only parts) or -//! "Tuple", which is a convention used by Debian Linux. +//! Vendor. //! -//! AsmJit doesn't support all possible combinations or architectures and ABIs, -//! however, it models the environment similarly to other compilers for future -//! extensibility. -class Environment { -public: - //! Architecture type, see \ref Arch. - uint8_t _arch; - //! Sub-architecture type, see \ref SubArch. - uint8_t _subArch; - //! Vendor type, see \ref Vendor. - uint8_t _vendor; - //! Platform type, see \ref Platform. - uint8_t _platform; - //! ABI type, see \ref Abi. - uint8_t _abi; - //! Object format, see \ref Format. - uint8_t _format; - //! Reserved for future use, must be zero. - uint16_t _reserved; - - //! Architecture. - enum Arch : uint32_t { - //! Unknown or uninitialized architecture. - kArchUnknown = 0, - - //! Mask used by 32-bit architectures (odd are 32-bit, even are 64-bit). - kArch32BitMask = 0x01, - //! Mask used by big-endian architectures. - kArchBigEndianMask = 0x80u, - - //! 32-bit X86 architecture. - kArchX86 = 1, - //! 64-bit X86 architecture also known as X86_64 and AMD64. - kArchX64 = 2, - - //! 32-bit RISC-V architecture. - kArchRISCV32 = 3, - //! 64-bit RISC-V architecture. - kArchRISCV64 = 4, - - //! 32-bit ARM architecture (little endian). - kArchARM = 5, - //! 32-bit ARM architecture (big endian). - kArchARM_BE = kArchARM | kArchBigEndianMask, - //! 64-bit ARM architecture in (little endian). - kArchAArch64 = 6, - //! 64-bit ARM architecture in (big endian). - kArchAArch64_BE = kArchAArch64 | kArchBigEndianMask, - //! 32-bit ARM in Thumb mode (little endian). - kArchThumb = 7, - //! 32-bit ARM in Thumb mode (big endian). - kArchThumb_BE = kArchThumb | kArchBigEndianMask, - - // 8 is not used, even numbers are 64-bit architectures. - - //! 32-bit MIPS architecture in (little endian). - kArchMIPS32_LE = 9, - //! 32-bit MIPS architecture in (big endian). - kArchMIPS32_BE = kArchMIPS32_LE | kArchBigEndianMask, - //! 64-bit MIPS architecture in (little endian). - kArchMIPS64_LE = 10, - //! 64-bit MIPS architecture in (big endian). - kArchMIPS64_BE = kArchMIPS64_LE | kArchBigEndianMask, - - //! Count of architectures. - kArchCount = 11 - }; - - //! Sub-architecture. - enum SubArch : uint32_t { - //! Unknown or uninitialized architecture sub-type. - kSubArchUnknown = 0, - - //! Count of sub-architectures. - kSubArchCount - }; - - //! Vendor. - //! - //! \note AsmJit doesn't use vendor information at the moment. It's provided - //! for future use, if required. - enum Vendor : uint32_t { - //! Unknown or uninitialized vendor. - kVendorUnknown = 0, - - //! Count of vendor identifiers. - kVendorCount - }; - - //! Platform / OS. - enum Platform : uint32_t { - //! Unknown or uninitialized platform. - kPlatformUnknown = 0, - - //! Windows OS. - kPlatformWindows, - - //! Other platform, most likely POSIX based. - kPlatformOther, - - //! Linux OS. - kPlatformLinux, - //! GNU/Hurd OS. - kPlatformHurd, - - //! FreeBSD OS. - kPlatformFreeBSD, - //! OpenBSD OS. - kPlatformOpenBSD, - //! NetBSD OS. - kPlatformNetBSD, - //! DragonFly BSD OS. - kPlatformDragonFlyBSD, - - //! Haiku OS. - kPlatformHaiku, - - //! Apple OSX. - kPlatformOSX, - //! Apple iOS. - kPlatformIOS, - //! Apple TVOS. - kPlatformTVOS, - //! Apple WatchOS. - kPlatformWatchOS, - - //! Emscripten platform. - kPlatformEmscripten, - - //! Count of platform identifiers. - kPlatformCount - }; - - //! ABI. - enum Abi : uint32_t { - //! Unknown or uninitialied environment. - kAbiUnknown = 0, - //! Microsoft ABI. - kAbiMSVC, - //! GNU ABI. - kAbiGNU, - //! Android Environment / ABI. - kAbiAndroid, - //! Cygwin ABI. - kAbiCygwin, - - //! Count of known ABI types. - kAbiCount - }; - - //! Object format. - //! - //! \note AsmJit doesn't really use anything except \ref kFormatUnknown and - //! \ref kFormatJIT at the moment. Object file formats are provided for - //! future extensibility and a possibility to generate object files at some - //! point. - enum Format : uint32_t { - //! Unknown or uninitialized object format. - kFormatUnknown = 0, - - //! JIT code generation object, most likely \ref JitRuntime or a custom - //! \ref Target implementation. - kFormatJIT, - - //! Executable and linkable format (ELF). - kFormatELF, - //! Common object file format. - kFormatCOFF, - //! Extended COFF object format. - kFormatXCOFF, - //! Mach object file format. - kFormatMachO, - - //! Count of object format types. - kFormatCount - }; - - //! \name Environment Detection - //! \{ - -#ifdef _DOXYGEN - //! Architecture detected at compile-time (architecture of the host). - static constexpr Arch kArchHost = DETECTED_AT_COMPILE_TIME; - //! Sub-architecture detected at compile-time (sub-architecture of the host). - static constexpr SubArch kSubArchHost = DETECTED_AT_COMPILE_TIME; - //! Vendor detected at compile-time (vendor of the host). - static constexpr Vendor kVendorHost = DETECTED_AT_COMPILE_TIME; - //! Platform detected at compile-time (platform of the host). - static constexpr Platform kPlatformHost = DETECTED_AT_COMPILE_TIME; - //! ABI detected at compile-time (ABI of the host). - static constexpr Abi kAbiHost = DETECTED_AT_COMPILE_TIME; +//! \note AsmJit doesn't use vendor information at the moment. It's provided for future use, if required. +enum class Vendor : uint8_t { + //! Unknown or uninitialized platform vendor. + kUnknown = 0, + + //! Maximum value of `PlatformVendor`. + kMaxValue = kUnknown, + + //! Platform vendor detected at compile-time. + kHost = +#if defined(_DOXYGEN) + DETECTED_AT_COMPILE_TIME #else - static constexpr Arch kArchHost = - ASMJIT_ARCH_X86 == 32 ? kArchX86 : - ASMJIT_ARCH_X86 == 64 ? kArchX64 : - - ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kArchARM : - ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kArchARM_BE : - ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kArchAArch64 : - ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_BE ? kArchAArch64_BE : - - ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_LE ? kArchMIPS32_LE : - ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_BE ? kArchMIPS32_BE : - ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_LE ? kArchMIPS64_LE : - ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_BE ? kArchMIPS64_BE : - - kArchUnknown; - - static constexpr SubArch kSubArchHost = - kSubArchUnknown; + kUnknown +#endif +}; - static constexpr Vendor kVendorHost = - kVendorUnknown; +//! Platform - runtime environment or operating system. +enum class Platform : uint8_t { + //! Unknown or uninitialized platform. + kUnknown = 0, + + //! Windows OS. + kWindows, + + //! Other platform that is not Windows, most likely POSIX based. + kOther, + + //! Linux OS. + kLinux, + //! GNU/Hurd OS. + kHurd, + + //! FreeBSD OS. + kFreeBSD, + //! OpenBSD OS. + kOpenBSD, + //! NetBSD OS. + kNetBSD, + //! DragonFly BSD OS. + kDragonFlyBSD, + + //! Haiku OS. + kHaiku, + + //! Apple OSX. + kOSX, + //! Apple iOS. + kIOS, + //! Apple TVOS. + kTVOS, + //! Apple WatchOS. + kWatchOS, + + //! Emscripten platform. + kEmscripten, + + //! Maximum value of `Platform`. + kMaxValue = kEmscripten, - static constexpr Platform kPlatformHost = -#if defined(__EMSCRIPTEN__) - kPlatformEmscripten + //! Platform detected at compile-time (platform of the host). + kHost = +#if defined(_DOXYGEN) + DETECTED_AT_COMPILE_TIME +#elif defined(__EMSCRIPTEN__) + kEmscripten #elif defined(_WIN32) - kPlatformWindows + kWindows #elif defined(__linux__) - kPlatformLinux + kLinux #elif defined(__gnu_hurd__) - kPlatformHurd + kHurd #elif defined(__FreeBSD__) - kPlatformFreeBSD + kFreeBSD #elif defined(__OpenBSD__) - kPlatformOpenBSD + kOpenBSD #elif defined(__NetBSD__) - kPlatformNetBSD + kNetBSD #elif defined(__DragonFly__) - kPlatformDragonFlyBSD + kDragonFlyBSD #elif defined(__HAIKU__) - kPlatformHaiku + kHaiku #elif defined(__APPLE__) && TARGET_OS_OSX - kPlatformOSX + kOSX #elif defined(__APPLE__) && TARGET_OS_TV - kPlatformTVOS + kTVOS #elif defined(__APPLE__) && TARGET_OS_WATCH - kPlatformWatchOS + kWatchOS #elif defined(__APPLE__) && TARGET_OS_IPHONE - kPlatformIOS + kIOS #else - kPlatformOther + kOther #endif - ; +}; - static constexpr Abi kAbiHost = -#if defined(_MSC_VER) - kAbiMSVC +//! Platform ABI (application binary interface). +enum class PlatformABI : uint8_t { + //! Unknown or uninitialied environment. + kUnknown = 0, + //! Microsoft ABI. + kMSVC, + //! GNU ABI. + kGNU, + //! Android Environment / ABI. + kAndroid, + //! Cygwin ABI. + kCygwin, + + //! Maximum value of `PlatformABI`. + kMaxValue, + + //! Host ABI detected at compile-time. + kHost = +#if defined(_DOXYGEN) + DETECTED_AT_COMPILE_TIME +#elif defined(_MSC_VER) + kMSVC #elif defined(__CYGWIN__) - kAbiCygwin + kCygwin #elif defined(__MINGW32__) || defined(__GLIBC__) - kAbiGNU + kGNU #elif defined(__ANDROID__) - kAbiAndroid + kAndroid #else - kAbiUnknown + kUnknown #endif - ; +}; -#endif +//! Object format. +//! +//! \note AsmJit doesn't really use anything except \ref ObjectFormat::kUnknown and \ref ObjectFormat::kJIT at +//! the moment. Object file formats are provided for future extensibility and a possibility to generate object +//! files at some point. +enum class ObjectFormat : uint8_t { + //! Unknown or uninitialized object format. + kUnknown = 0, + + //! JIT code generation object, most likely \ref JitRuntime or a custom + //! \ref Target implementation. + kJIT, + + //! Executable and linkable format (ELF). + kELF, + //! Common object file format. + kCOFF, + //! Extended COFF object format. + kXCOFF, + //! Mach object file format. + kMachO, + + //! Maximum value of `ObjectFormat`. + kMaxValue +}; + +//! Represents an environment, which is usually related to a \ref Target. +//! +//! Environment has usually an 'arch-subarch-vendor-os-abi' format, which is sometimes called "Triple" (historically +//! it used to be 3 only parts) or "Tuple", which is a convention used by Debian Linux. +//! +//! AsmJit doesn't support all possible combinations or architectures and ABIs, however, it models the environment +//! similarly to other compilers for future extensibility. +class Environment { +public: + //! \name Members + //! \{ + + //! Architecture. + Arch _arch; + //! Sub-architecture type. + SubArch _subArch; + //! Vendor type. + Vendor _vendor; + //! Platform. + Platform _platform; + //! Platform ABI. + PlatformABI _platformABI; + //! Object format. + ObjectFormat _objectFormat; + //! Reserved for future use, must be zero. + uint8_t _reserved[2]; //! \} - //! \name Construction / Destruction + //! \name Construction & Destruction //! \{ inline Environment() noexcept : - _arch(uint8_t(kArchUnknown)), - _subArch(uint8_t(kSubArchUnknown)), - _vendor(uint8_t(kVendorUnknown)), - _platform(uint8_t(kPlatformUnknown)), - _abi(uint8_t(kAbiUnknown)), - _format(uint8_t(kFormatUnknown)), - _reserved(0) {} + _arch(Arch::kUnknown), + _subArch(SubArch::kUnknown), + _vendor(Vendor::kUnknown), + _platform(Platform::kUnknown), + _platformABI(PlatformABI::kUnknown), + _objectFormat(ObjectFormat::kUnknown), + _reserved { 0, 0 } {} + + inline explicit Environment( + Arch arch, + SubArch subArch = SubArch::kUnknown, + Vendor vendor = Vendor::kUnknown, + Platform platform = Platform::kUnknown, + PlatformABI abi = PlatformABI::kUnknown, + ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept { + + init(arch, subArch, vendor, platform, abi, objectFormat); + } inline Environment(const Environment& other) noexcept = default; - inline explicit Environment(uint32_t arch, - uint32_t subArch = kSubArchUnknown, - uint32_t vendor = kVendorUnknown, - uint32_t platform = kPlatformUnknown, - uint32_t abi = kAbiUnknown, - uint32_t format = kFormatUnknown) noexcept { - init(arch, subArch, vendor, platform, abi, format); + //! Returns the host environment constructed from preprocessor macros defined by the compiler. + //! + //! The returned environment should precisely match the target host architecture, sub-architecture, platform, + //! and ABI. + static inline Environment host() noexcept { + return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown); } //! \} @@ -358,7 +261,7 @@ public: //! Tests whether the environment is initialized, which means it must have //! a valid architecture. inline bool isInitialized() const noexcept { - return _arch != kArchUnknown; + return _arch != Arch::kUnknown; } inline uint64_t _packed() const noexcept { @@ -369,56 +272,60 @@ public: //! Resets all members of the environment to zero / unknown. inline void reset() noexcept { - _arch = uint8_t(kArchUnknown); - _subArch = uint8_t(kSubArchUnknown); - _vendor = uint8_t(kVendorUnknown); - _platform = uint8_t(kPlatformUnknown); - _abi = uint8_t(kAbiUnknown); - _format = uint8_t(kFormatUnknown); - _reserved = 0; + _arch = Arch::kUnknown; + _subArch = SubArch::kUnknown; + _vendor = Vendor::kUnknown; + _platform = Platform::kUnknown; + _platformABI = PlatformABI::kUnknown; + _objectFormat = ObjectFormat::kUnknown; + _reserved[0] = 0; + _reserved[1] = 0; } inline bool equals(const Environment& other) const noexcept { return _packed() == other._packed(); } - //! Returns the architecture, see \ref Arch. - inline uint32_t arch() const noexcept { return _arch; } - //! Returns the sub-architecture, see \ref SubArch. - inline uint32_t subArch() const noexcept { return _subArch; } - //! Returns vendor, see \ref Vendor. - inline uint32_t vendor() const noexcept { return _vendor; } - //! Returns target's platform or operating system, see \ref Platform. - inline uint32_t platform() const noexcept { return _platform; } - //! Returns target's ABI, see \ref Abi. - inline uint32_t abi() const noexcept { return _abi; } - //! Returns target's object format, see \ref Format. - inline uint32_t format() const noexcept { return _format; } - - inline void init(uint32_t arch, - uint32_t subArch = kSubArchUnknown, - uint32_t vendor = kVendorUnknown, - uint32_t platform = kPlatformUnknown, - uint32_t abi = kAbiUnknown, - uint32_t format = kFormatUnknown) noexcept { - _arch = uint8_t(arch); - _subArch = uint8_t(subArch); - _vendor = uint8_t(vendor); - _platform = uint8_t(platform); - _abi = uint8_t(abi); - _format = uint8_t(format); - _reserved = 0; + //! Returns the architecture. + inline Arch arch() const noexcept { return _arch; } + //! Returns the sub-architecture. + inline SubArch subArch() const noexcept { return _subArch; } + //! Returns vendor. + inline Vendor vendor() const noexcept { return _vendor; } + //! Returns target's platform or operating system. + inline Platform platform() const noexcept { return _platform; } + //! Returns target's ABI. + inline PlatformABI platformABI() const noexcept { return _platformABI; } + //! Returns target's object format. + inline ObjectFormat objectFormat() const noexcept { return _objectFormat; } + + inline void init( + Arch arch, + SubArch subArch = SubArch::kUnknown, + Vendor vendor = Vendor::kUnknown, + Platform platform = Platform::kUnknown, + PlatformABI platformABI = PlatformABI::kUnknown, + ObjectFormat objectFormat = ObjectFormat::kUnknown) noexcept { + + _arch = arch; + _subArch = subArch; + _vendor = vendor; + _platform = platform; + _platformABI = platformABI; + _objectFormat = objectFormat; + _reserved[0] = 0; + _reserved[1] = 0; } - inline bool isArchX86() const noexcept { return _arch == kArchX86; } - inline bool isArchX64() const noexcept { return _arch == kArchX64; } - inline bool isArchRISCV32() const noexcept { return _arch == kArchRISCV32; } - inline bool isArchRISCV64() const noexcept { return _arch == kArchRISCV64; } - inline bool isArchARM() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchARM; } - inline bool isArchThumb() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchThumb; } - inline bool isArchAArch64() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchAArch64; } - inline bool isArchMIPS32() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchMIPS32_LE; } - inline bool isArchMIPS64() const noexcept { return (_arch & ~kArchBigEndianMask) == kArchMIPS64_LE; } + inline bool isArchX86() const noexcept { return _arch == Arch::kX86; } + inline bool isArchX64() const noexcept { return _arch == Arch::kX64; } + inline bool isArchARM() const noexcept { return isArchARM(_arch); } + inline bool isArchThumb() const noexcept { return isArchThumb(_arch); } + inline bool isArchAArch64() const noexcept { return isArchAArch64(_arch); } + inline bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); } + inline bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); } + inline bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; } + inline bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; } //! Tests whether the architecture is 32-bit. inline bool is32Bit() const noexcept { return is32Bit(_arch); } @@ -432,45 +339,45 @@ public: //! Tests whether this architecture is of X86 family. inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); } - //! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit). - inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); } //! Tests whether this architecture family is ARM, Thumb, or AArch64. inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); } //! Tests whether this architecture family is MISP or MIPS64. inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); } + //! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit). + inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); } //! Tests whether the environment platform is Windows. - inline bool isPlatformWindows() const noexcept { return _platform == kPlatformWindows; } + inline bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; } //! Tests whether the environment platform is Linux. - inline bool isPlatformLinux() const noexcept { return _platform == kPlatformLinux; } + inline bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; } //! Tests whether the environment platform is Hurd. - inline bool isPlatformHurd() const noexcept { return _platform == kPlatformHurd; } + inline bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; } //! Tests whether the environment platform is Haiku. - inline bool isPlatformHaiku() const noexcept { return _platform == kPlatformHaiku; } + inline bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; } //! Tests whether the environment platform is any BSD. inline bool isPlatformBSD() const noexcept { - return _platform == kPlatformFreeBSD || - _platform == kPlatformOpenBSD || - _platform == kPlatformNetBSD || - _platform == kPlatformDragonFlyBSD; + return _platform == Platform::kFreeBSD || + _platform == Platform::kOpenBSD || + _platform == Platform::kNetBSD || + _platform == Platform::kDragonFlyBSD; } //! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS). inline bool isPlatformApple() const noexcept { - return _platform == kPlatformOSX || - _platform == kPlatformIOS || - _platform == kPlatformTVOS || - _platform == kPlatformWatchOS; + return _platform == Platform::kOSX || + _platform == Platform::kIOS || + _platform == Platform::kTVOS || + _platform == Platform::kWatchOS; } //! Tests whether the ABI is MSVC. - inline bool isAbiMSVC() const noexcept { return _abi == kAbiMSVC; } + inline bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; } //! Tests whether the ABI is GNU. - inline bool isAbiGNU() const noexcept { return _abi == kAbiGNU; } + inline bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; } //! Returns a calculated stack alignment for this environment. ASMJIT_API uint32_t stackAlignment() const noexcept; @@ -479,134 +386,109 @@ public: uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); } //! Sets the architecture to `arch`. - inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); } + inline void setArch(Arch arch) noexcept { _arch = arch; } //! Sets the sub-architecture to `subArch`. - inline void setSubArch(uint32_t subArch) noexcept { _subArch = uint8_t(subArch); } + inline void setSubArch(SubArch subArch) noexcept { _subArch = subArch; } //! Sets the vendor to `vendor`. - inline void setVendor(uint32_t vendor) noexcept { _vendor = uint8_t(vendor); } + inline void setVendor(Vendor vendor) noexcept { _vendor = vendor; } //! Sets the platform to `platform`. - inline void setPlatform(uint32_t platform) noexcept { _platform = uint8_t(platform); } - //! Sets the ABI to `abi`. - inline void setAbi(uint32_t abi) noexcept { _abi = uint8_t(abi); } - //! Sets the object format to `format`. - inline void setFormat(uint32_t format) noexcept { _format = uint8_t(format); } + inline void setPlatform(Platform platform) noexcept { _platform = platform; } + //! Sets the ABI to `platformABI`. + inline void setPlatformABI(PlatformABI platformABI) noexcept { _platformABI = platformABI; } + //! Sets the object format to `objectFormat`. + inline void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; } //! \} //! \name Static Utilities //! \{ - static inline bool isValidArch(uint32_t arch) noexcept { - return (arch & ~kArchBigEndianMask) != 0 && - (arch & ~kArchBigEndianMask) < kArchCount; + static inline bool isDefinedArch(Arch arch) noexcept { + return uint32_t(arch) <= uint32_t(Arch::kMaxValue); + } + + static inline bool isValidArch(Arch arch) noexcept { + return arch != Arch::kUnknown && uint32_t(arch) <= uint32_t(Arch::kMaxValue); } //! Tests whether the given architecture `arch` is 32-bit. - static inline bool is32Bit(uint32_t arch) noexcept { - return (arch & kArch32BitMask) == kArch32BitMask; + static inline bool is32Bit(Arch arch) noexcept { + return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == uint32_t(Arch::k32BitMask); } //! Tests whether the given architecture `arch` is 64-bit. - static inline bool is64Bit(uint32_t arch) noexcept { - return (arch & kArch32BitMask) == 0; + static inline bool is64Bit(Arch arch) noexcept { + return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == 0; } //! Tests whether the given architecture `arch` is little endian. - static inline bool isLittleEndian(uint32_t arch) noexcept { - return (arch & kArchBigEndianMask) == 0; + static inline bool isLittleEndian(Arch arch) noexcept { + return uint32_t(arch) < uint32_t(Arch::kBigEndian); } //! Tests whether the given architecture `arch` is big endian. - static inline bool isBigEndian(uint32_t arch) noexcept { - return (arch & kArchBigEndianMask) == kArchBigEndianMask; + static inline bool isBigEndian(Arch arch) noexcept { + return uint32_t(arch) >= uint32_t(Arch::kBigEndian); } - //! Tests whether the given architecture is AArch64. - static inline bool isArchAArch64(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchAArch64; + //! Tests whether the given architecture is ARM or ARM_BE. + static inline bool isArchARM(Arch arch) noexcept { + return arch == Arch::kARM || arch == Arch::kARM_BE; } - //! Tests whether the given architecture family is X86 or X64. - static inline bool isFamilyX86(uint32_t arch) noexcept { - return arch == kArchX86 || - arch == kArchX64; + //! Tests whether the given architecture is Thumb or Thumb_BE. + static inline bool isArchThumb(Arch arch) noexcept { + return arch == Arch::kThumb || arch == Arch::kThumb_BE; } - //! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit). - static inline bool isFamilyRISCV(uint32_t arch) noexcept { - return arch == kArchRISCV32 || - arch == kArchRISCV64; + //! Tests whether the given architecture is AArch64 or AArch64_BE. + static inline bool isArchAArch64(Arch arch) noexcept { + return arch == Arch::kAArch64 || arch == Arch::kAArch64_BE; + } + + //! Tests whether the given architecture is MIPS32_LE or MIPS32_BE. + static inline bool isArchMIPS32(Arch arch) noexcept { + return arch == Arch::kMIPS32_LE || arch == Arch::kMIPS32_BE; + } + + //! Tests whether the given architecture is MIPS64_LE or MIPS64_BE. + static inline bool isArchMIPS64(Arch arch) noexcept { + return arch == Arch::kMIPS64_LE || arch == Arch::kMIPS64_BE; + } + + //! Tests whether the given architecture family is X86 or X64. + static inline bool isFamilyX86(Arch arch) noexcept { + return arch == Arch::kX86 || arch == Arch::kX64; } //! Tests whether the given architecture family is ARM, Thumb, or AArch64. - static inline bool isFamilyARM(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchARM || - arch == kArchAArch64 || - arch == kArchThumb; + static inline bool isFamilyARM(Arch arch) noexcept { + return isArchARM(arch) || isArchAArch64(arch) || isArchThumb(arch); } //! Tests whether the given architecture family is MISP or MIPS64. - static inline bool isFamilyMIPS(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchMIPS32_LE || - arch == kArchMIPS64_LE; + static inline bool isFamilyMIPS(Arch arch) noexcept { + return isArchMIPS32(arch) || isArchMIPS64(arch); + } + + //! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit). + static inline bool isFamilyRISCV(Arch arch) noexcept { + return arch == Arch::kRISCV32 || arch == Arch::kRISCV64; } //! Returns a native general purpose register size from the given architecture. - static uint32_t registerSizeFromArch(uint32_t arch) noexcept { + static inline uint32_t registerSizeFromArch(Arch arch) noexcept { return is32Bit(arch) ? 4u : 8u; } //! \} }; -//! Returns the host environment constructed from preprocessor macros defined -//! by the compiler. -//! -//! The returned environment should precisely match the target host architecture, -//! sub-architecture, platform, and ABI. -static ASMJIT_INLINE Environment hostEnvironment() noexcept { - return Environment(Environment::kArchHost, - Environment::kSubArchHost, - Environment::kVendorHost, - Environment::kPlatformHost, - Environment::kAbiHost, - Environment::kFormatUnknown); -} - static_assert(sizeof(Environment) == 8, "Environment must occupy exactly 8 bytes."); //! \} -#ifndef ASMJIT_NO_DEPRECATED -class ASMJIT_DEPRECATED_STRUCT("Use Environment instead") ArchInfo : public Environment { -public: - inline ArchInfo() noexcept : Environment() {} - - inline ArchInfo(const Environment& other) noexcept : Environment(other) {} - inline explicit ArchInfo(uint32_t arch, uint32_t subArch = kSubArchUnknown) noexcept - : Environment(arch, subArch) {} - - enum Id : uint32_t { - kIdNone = Environment::kArchUnknown, - kIdX86 = Environment::kArchX86, - kIdX64 = Environment::kArchX64, - kIdA32 = Environment::kArchARM, - kIdA64 = Environment::kArchAArch64, - kIdHost = Environment::kArchHost - }; - - enum SubType : uint32_t { - kSubIdNone = Environment::kSubArchUnknown - }; - - static inline ArchInfo host() noexcept { return ArchInfo(hostEnvironment()); } -}; -#endif // !ASMJIT_NO_DEPRECATED - ASMJIT_END_NAMESPACE #endif // ASMJIT_CORE_ENVIRONMENT_H_INCLUDED diff --git a/src/asmjit/core/errorhandler.cpp b/src/asmjit/core/errorhandler.cpp index 8372d75..5a7dac5 100644 --- a/src/asmjit/core/errorhandler.cpp +++ b/src/asmjit/core/errorhandler.cpp @@ -1,36 +1,13 @@ - -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors +// This file is part of AsmJit project <https://asmjit.com> // -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/errorhandler.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ErrorHandler] -// ============================================================================ - ErrorHandler::ErrorHandler() noexcept {} ErrorHandler::~ErrorHandler() noexcept {} diff --git a/src/asmjit/core/errorhandler.h b/src/asmjit/core/errorhandler.h index b26a654..5151d43 100644 --- a/src/asmjit/core/errorhandler.h +++ b/src/asmjit/core/errorhandler.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ERRORHANDLER_H_INCLUDED #define ASMJIT_CORE_ERRORHANDLER_H_INCLUDED @@ -31,41 +13,28 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_error_handling //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class BaseEmitter; -// ============================================================================ -// [asmjit::ErrorHandler] -// ============================================================================ - //! Error handler can be used to override the default behavior of error handling. //! -//! It's available to all classes that inherit `BaseEmitter`. Override -//! \ref ErrorHandler::handleError() to implement your own error handler. +//! It's available to all classes that inherit `BaseEmitter`. Override \ref ErrorHandler::handleError() to implement +//! your own error handler. //! //! The following use-cases are supported: //! -//! - Record the error and continue code generation. This is the simplest -//! approach that can be used to at least log possible errors. -//! - Throw an exception. AsmJit doesn't use exceptions and is completely -//! exception-safe, but it's perfectly legal to throw an exception from -//! the error handler. -//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, -//! Builder and Compiler to a consistent state before calling \ref handleError(), -//! so `longjmp()` can be used without issues to cancel the code-generation if -//! an error occurred. This method can be used if exception handling in your -//! project is turned off and you still want some comfort. In most cases it -//! should be safe as AsmJit uses \ref Zone memory and the ownership of memory -//! it allocates always ends with the instance that allocated it. If using this -//! approach please never jump outside the life-time of \ref CodeHolder and -//! \ref BaseEmitter. -//! -//! \ref ErrorHandler can be attached to \ref CodeHolder or \ref BaseEmitter, -//! which has a priority. The example below uses error handler that just prints -//! the error, but lets AsmJit continue: +//! - Record the error and continue code generation. This is the simplest approach that can be used to at least log +//! possible errors. +//! - Throw an exception. AsmJit doesn't use exceptions and is completely exception-safe, but it's perfectly legal +//! to throw an exception from the error handler. +//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, Builder and Compiler to +//! a consistent state before calling \ref handleError(), so `longjmp()` can be used without issues to cancel the +//! code generation if an error occurred. This method can be used if exception handling in your project is turned +//! off and you still want some comfort. In most cases it should be safe as AsmJit uses \ref Zone memory and the +//! ownership of memory it allocates always ends with the instance that allocated it. If using this approach please +//! never jump outside the life-time of \ref CodeHolder and \ref BaseEmitter. +//! +//! \ref ErrorHandler can be attached to \ref CodeHolder or \ref BaseEmitter, which has a priority. The example below +//! uses error handler that just prints the error, but lets AsmJit continue: //! //! ``` //! // Error Handling #1 - Logging and returning Error. @@ -108,12 +77,10 @@ class BaseEmitter; //! } //! ``` //! -//! If error happens during instruction emitting / encoding the assembler behaves -//! transactionally - the output buffer won't advance if encoding failed, thus -//! either a fully encoded instruction or nothing is emitted. The error handling -//! shown above is useful, but it's still not the best way of dealing with errors -//! in AsmJit. The following example shows how to use exception handling to handle -//! errors in a more C++ way: +//! If error happens during instruction emitting / encoding the assembler behaves transactionally - the output buffer +//! won't advance if encoding failed, thus either a fully encoded instruction or nothing is emitted. The error handling +//! shown above is useful, but it's still not the best way of dealing with errors in AsmJit. The following example +//! shows how to use exception handling to handle errors in a more C++ way: //! //! ``` //! // Error Handling #2 - Throwing an exception. @@ -168,13 +135,10 @@ class BaseEmitter; //! } //! ``` //! -//! If C++ exceptions are not what you like or your project turns off them -//! completely there is still a way of reducing the error handling to a minimum -//! by using a standard setjmp/longjmp approach. AsmJit is exception-safe and -//! cleans up everything before calling the ErrorHandler, so any approach is -//! safe. You can simply jump from the error handler without causing any -//! side-effects or memory leaks. The following example demonstrates how it -//! could be done: +//! If C++ exceptions are not what you like or your project turns off them completely there is still a way of reducing +//! the error handling to a minimum by using a standard setjmp/longjmp approach. AsmJit is exception-safe and cleans +//! up everything before calling the ErrorHandler, so any approach is safe. You can simply jump from the error handler +//! without causing any side-effects or memory leaks. The following example demonstrates how it could be done: //! //! ``` //! // Error Handling #3 - Using setjmp/longjmp if exceptions are not allowed. @@ -223,40 +187,37 @@ class ASMJIT_VIRTAPI ErrorHandler { public: ASMJIT_BASE_CLASS(ErrorHandler) - // -------------------------------------------------------------------------- - // [Construction / Destruction] - // -------------------------------------------------------------------------- + //! \name Construction & Destruction + //! \{ //! Creates a new `ErrorHandler` instance. ASMJIT_API ErrorHandler() noexcept; //! Destroys the `ErrorHandler` instance. ASMJIT_API virtual ~ErrorHandler() noexcept; - // -------------------------------------------------------------------------- - // [Handle Error] - // -------------------------------------------------------------------------- + //! \} + + //! \name Interface + //! \{ //! Error handler (must be reimplemented). //! - //! Error handler is called after an error happened and before it's propagated - //! to the caller. There are multiple ways how the error handler can be used: + //! Error handler is called after an error happened and before it's propagated to the caller. There are multiple + //! ways how the error handler can be used: //! - //! 1. User-based error handling without throwing exception or using C's - //! `longjmp()`. This is for users that don't use exceptions and want - //! customized error handling. + //! 1. User-based error handling without throwing exception or using C's`longjmp()`. This is for users that don't + //! use exceptions and want customized error handling. //! - //! 2. Throwing an exception. AsmJit doesn't use exceptions and is completely - //! exception-safe, but you can throw exception from your error handler if - //! this way is the preferred way of handling errors in your project. + //! 2. Throwing an exception. AsmJit doesn't use exceptions and is completely exception-safe, but you can throw + //! exception from your error handler if this way is the preferred way of handling errors in your project. //! - //! 3. Using plain old C's `setjmp()` and `longjmp()`. Asmjit always puts - //! `BaseEmitter` to a consistent state before calling `handleError()` - //! so `longjmp()` can be used without any issues to cancel the code - //! generation if an error occurred. There is no difference between - //! exceptions and `longjmp()` from AsmJit's perspective, however, - //! never jump outside of `CodeHolder` and `BaseEmitter` scope as you - //! would leak memory. + //! 3. Using plain old C's `setjmp()` and `longjmp()`. Asmjit always puts `BaseEmitter` to a consistent state before + //! calling `handleError()` so `longjmp()` can be used without any issues to cancel the code generation if an + //! error occurred. There is no difference between exceptions and `longjmp()` from AsmJit's perspective, however, + //! never jump outside of `CodeHolder` and `BaseEmitter` scope as you would leak memory. virtual void handleError(Error err, const char* message, BaseEmitter* origin) = 0; + + //! \} }; //! \} diff --git a/src/asmjit/core/features.h b/src/asmjit/core/features.h deleted file mode 100644 index 0f2cfe2..0000000 --- a/src/asmjit/core/features.h +++ /dev/null @@ -1,186 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FEATURES_H_INCLUDED -#define ASMJIT_CORE_FEATURES_H_INCLUDED - -#include "../core/globals.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::BaseFeatures] -// ============================================================================ - -//! Base class that provides information about CPU features. -//! -//! Internally each feature is represented by a single bit in an embedded -//! bit-array, however, feature bits are defined by an architecture specific -//! implementations, like \ref x86::Features. -class BaseFeatures { -public: - typedef Support::BitWord BitWord; - typedef Support::BitVectorIterator<BitWord> Iterator; - - enum : uint32_t { - kMaxFeatures = 256, - kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits - }; - - BitWord _bits[kNumBitWords]; - - //! \name Construction & Destruction - //! \{ - - inline BaseFeatures() noexcept { reset(); } - inline BaseFeatures(const BaseFeatures& other) noexcept = default; - inline explicit BaseFeatures(Globals::NoInit_) noexcept {} - - inline void reset() noexcept { - for (size_t i = 0; i < kNumBitWords; i++) - _bits[i] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseFeatures& operator=(const BaseFeatures& other) noexcept = default; - - inline bool operator==(const BaseFeatures& other) noexcept { return eq(other); } - inline bool operator!=(const BaseFeatures& other) noexcept { return !eq(other); } - - //! \} - - //! \name Cast - //! \{ - - //! Casts this base class into a derived type `T`. - template<typename T> - inline T& as() noexcept { return static_cast<T&>(*this); } - - //! Casts this base class into a derived type `T` (const). - template<typename T> - inline const T& as() const noexcept { return static_cast<const T&>(*this); } - - //! \} - - //! \name Accessors - //! \{ - - inline bool empty() const noexcept { - for (uint32_t i = 0; i < kNumBitWords; i++) - if (_bits[i]) - return false; - return true; - } - - //! Returns all features as array of bitwords (see \ref Support::BitWord). - inline BitWord* bits() noexcept { return _bits; } - //! Returns all features as array of bitwords (const). - inline const BitWord* bits() const noexcept { return _bits; } - - //! Returns the number of BitWords returned by \ref bits(). - inline size_t bitWordCount() const noexcept { return kNumBitWords; } - - //! Returns \ref Support::BitVectorIterator, that can be used to iterate - //! all features efficiently - inline Iterator iterator() const noexcept { - return Iterator(_bits, kNumBitWords); - } - - //! Tests whether the feature `featureId` is present. - inline bool has(uint32_t featureId) const noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - return bool((_bits[idx] >> bit) & 0x1); - } - - //! Tests whether all features as defined by `other` are present. - inline bool hasAll(const BaseFeatures& other) const noexcept { - for (uint32_t i = 0; i < kNumBitWords; i++) - if ((_bits[i] & other._bits[i]) != other._bits[i]) - return false; - return true; - } - - //! \} - - //! \name Utilities - //! \{ - - //! Adds the given CPU `featureId` to the list of features. - inline void add(uint32_t featureId) noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - _bits[idx] |= BitWord(1) << bit; - } - - template<typename... Args> - inline void add(uint32_t featureId, Args... otherIds) noexcept { - add(featureId); - add(otherIds...); - } - - //! Removes the given CPU `featureId` from the list of features. - inline void remove(uint32_t featureId) noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - _bits[idx] &= ~(BitWord(1) << bit); - } - - template<typename... Args> - inline void remove(uint32_t featureId, Args... otherIds) noexcept { - remove(featureId); - remove(otherIds...); - } - - inline bool eq(const BaseFeatures& other) const noexcept { - for (size_t i = 0; i < kNumBitWords; i++) - if (_bits[i] != other._bits[i]) - return false; - return true; - } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_FEATURES_H_INCLUDED diff --git a/src/asmjit/core/formatter.cpp b/src/asmjit/core/formatter.cpp index 124eebf..efa0c47 100644 --- a/src/asmjit/core/formatter.cpp +++ b/src/asmjit/core/formatter.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_LOGGING @@ -29,7 +11,7 @@ #include "../core/codeholder.h" #include "../core/compiler.h" #include "../core/emitter.h" -#include "../core/formatter.h" +#include "../core/formatter_p.h" #include "../core/string.h" #include "../core/support.h" #include "../core/type.h" @@ -48,10 +30,6 @@ ASMJIT_BEGIN_NAMESPACE class VirtReg; #endif -// ============================================================================ -// [asmjit::Formatter] -// ============================================================================ - namespace Formatter { static const char wordNameTable[][8] = { @@ -72,40 +50,44 @@ static const char wordNameTable[][8] = { }; -Error formatTypeId(String& sb, uint32_t typeId) noexcept { - if (typeId == Type::kIdVoid) +Error formatTypeId(String& sb, TypeId typeId) noexcept { + if (typeId == TypeId::kVoid) return sb.append("void"); - if (!Type::isValid(typeId)) + if (!TypeUtils::isValid(typeId)) return sb.append("unknown"); const char* typeName = "unknown"; - uint32_t typeSize = Type::sizeOf(typeId); - - uint32_t baseId = Type::baseOf(typeId); - switch (baseId) { - case Type::kIdIntPtr : typeName = "iptr" ; break; - case Type::kIdUIntPtr: typeName = "uptr" ; break; - case Type::kIdI8 : typeName = "i8" ; break; - case Type::kIdU8 : typeName = "u8" ; break; - case Type::kIdI16 : typeName = "i16" ; break; - case Type::kIdU16 : typeName = "u16" ; break; - case Type::kIdI32 : typeName = "i32" ; break; - case Type::kIdU32 : typeName = "u32" ; break; - case Type::kIdI64 : typeName = "i64" ; break; - case Type::kIdU64 : typeName = "u64" ; break; - case Type::kIdF32 : typeName = "f32" ; break; - case Type::kIdF64 : typeName = "f64" ; break; - case Type::kIdF80 : typeName = "f80" ; break; - case Type::kIdMask8 : typeName = "mask8" ; break; - case Type::kIdMask16 : typeName = "mask16"; break; - case Type::kIdMask32 : typeName = "mask32"; break; - case Type::kIdMask64 : typeName = "mask64"; break; - case Type::kIdMmx32 : typeName = "mmx32" ; break; - case Type::kIdMmx64 : typeName = "mmx64" ; break; + uint32_t typeSize = TypeUtils::sizeOf(typeId); + TypeId scalarType = TypeUtils::scalarOf(typeId); + + switch (scalarType) { + case TypeId::kIntPtr : typeName = "intptr" ; break; + case TypeId::kUIntPtr: typeName = "uintptr"; break; + case TypeId::kInt8 : typeName = "int8" ; break; + case TypeId::kUInt8 : typeName = "uint8" ; break; + case TypeId::kInt16 : typeName = "int16" ; break; + case TypeId::kUInt16 : typeName = "uint16" ; break; + case TypeId::kInt32 : typeName = "int32" ; break; + case TypeId::kUInt32 : typeName = "uint32" ; break; + case TypeId::kInt64 : typeName = "int64" ; break; + case TypeId::kUInt64 : typeName = "uint64" ; break; + case TypeId::kFloat32: typeName = "float32"; break; + case TypeId::kFloat64: typeName = "float64"; break; + case TypeId::kFloat80: typeName = "float80"; break; + case TypeId::kMask8 : typeName = "mask8" ; break; + case TypeId::kMask16 : typeName = "mask16" ; break; + case TypeId::kMask32 : typeName = "mask32" ; break; + case TypeId::kMask64 : typeName = "mask64" ; break; + case TypeId::kMmx32 : typeName = "mmx32" ; break; + case TypeId::kMmx64 : typeName = "mmx64" ; break; + + default: + typeName = "unknown"; + break; } - uint32_t baseSize = Type::sizeOf(baseId); + uint32_t baseSize = TypeUtils::sizeOf(scalarType); if (typeSize > baseSize) { uint32_t count = typeSize / baseSize; return sb.appendFormat("%sx%u", typeName, unsigned(count)); @@ -117,7 +99,7 @@ Error formatTypeId(String& sb, uint32_t typeId) noexcept { Error formatFeature( String& sb, - uint32_t arch, + Arch arch, uint32_t featureId) noexcept { #if !defined(ASMJIT_NO_X86) @@ -135,7 +117,7 @@ Error formatFeature( Error formatLabel( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, uint32_t labelId) noexcept { @@ -159,6 +141,9 @@ Error formatLabel( ASMJIT_PROPAGATE(sb.append('.')); } + + if (le->type() == LabelType::kAnonymous) + ASMJIT_PROPAGATE(sb.append("L%u@", labelId)); return sb.append(le->name()); } else { @@ -168,10 +153,10 @@ Error formatLabel( Error formatRegister( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, + Arch arch, + RegType regType, uint32_t regId) noexcept { #if !defined(ASMJIT_NO_X86) @@ -189,9 +174,9 @@ Error formatRegister( Error formatOperand( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const Operand_& op) noexcept { #if !defined(ASMJIT_NO_X86) @@ -209,21 +194,21 @@ Error formatOperand( ASMJIT_API Error formatDataType( String& sb, - uint32_t formatFlags, - uint32_t arch, - uint32_t typeId) noexcept + FormatFlags formatFlags, + Arch arch, + TypeId typeId) noexcept { DebugUtils::unused(formatFlags); - if (ASMJIT_UNLIKELY(arch >= Environment::kArchCount)) + if (ASMJIT_UNLIKELY(uint32_t(arch) > uint32_t(Arch::kMaxValue))) return DebugUtils::errored(kErrorInvalidArch); - uint32_t typeSize = Type::sizeOf(typeId); + uint32_t typeSize = TypeUtils::sizeOf(typeId); if (typeSize == 0 || typeSize > 8) return DebugUtils::errored(kErrorInvalidState); uint32_t typeSizeLog2 = Support::ctz(typeSize); - return sb.append(wordNameTable[size_t(_archTraits[arch].isaWordNameId(typeSizeLog2))]); + return sb.append(wordNameTable[size_t(ArchTraits::byArch(arch).typeNameIdByIndex(typeSizeLog2))]); } static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSize, const uint8_t* data, size_t itemCount) noexcept { @@ -232,7 +217,7 @@ static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSiz sb.append(' '); for (size_t i = 0; i < itemCount; i++) { - uint64_t v; + uint64_t v = 0; if (i != 0) ASMJIT_PROPAGATE(sb.append(", ", 2)); @@ -244,7 +229,7 @@ static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSiz case 8: v = Support::readU64u(data); break; } - ASMJIT_PROPAGATE(sb.appendUInt(v, 16, typeSize * 2, String::kFormatAlternate)); + ASMJIT_PROPAGATE(sb.appendUInt(v, 16, typeSize * 2, StringFormatFlags::kAlternate)); data += typeSize; } @@ -253,16 +238,16 @@ static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSiz Error formatData( String& sb, - uint32_t formatFlags, - uint32_t arch, - uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) noexcept + FormatFlags formatFlags, + Arch arch, + TypeId typeId, const void* data, size_t itemCount, size_t repeatCount) noexcept { DebugUtils::unused(formatFlags); - if (ASMJIT_UNLIKELY(arch >= Environment::kArchCount)) + if (ASMJIT_UNLIKELY(!Environment::isDefinedArch(arch))) return DebugUtils::errored(kErrorInvalidArch); - uint32_t typeSize = Type::sizeOf(typeId); + uint32_t typeSize = TypeUtils::sizeOf(typeId); if (typeSize == 0) return DebugUtils::errored(kErrorInvalidState); @@ -277,7 +262,7 @@ Error formatData( } uint32_t typeSizeLog2 = Support::ctz(typeSize); - const char* wordName = wordNameTable[size_t(_archTraits[arch].isaWordNameId(typeSizeLog2))]; + const char* wordName = wordNameTable[size_t(ArchTraits::byArch(arch).typeNameIdByIndex(typeSizeLog2))]; if (repeatCount > 1) ASMJIT_PROPAGATE(sb.appendFormat(".repeat %zu ", repeatCount)); @@ -287,9 +272,9 @@ Error formatData( Error formatInstruction( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { #if !defined(ASMJIT_NO_X86) @@ -308,8 +293,8 @@ Error formatInstruction( #ifndef ASMJIT_NO_BUILDER #ifndef ASMJIT_NO_COMPILER -static Error formatFuncValue(String& sb, uint32_t formatFlags, const BaseEmitter* emitter, FuncValue value) noexcept { - uint32_t typeId = value.typeId(); +static Error formatFuncValue(String& sb, FormatFlags formatFlags, const BaseEmitter* emitter, FuncValue value) noexcept { + TypeId typeId = value.typeId(); ASMJIT_PROPAGATE(formatTypeId(sb, typeId)); if (value.isAssigned()) { @@ -338,10 +323,10 @@ static Error formatFuncValue(String& sb, uint32_t formatFlags, const BaseEmitter static Error formatFuncValuePack( String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, + FormatFlags formatFlags, + const BaseCompiler* cc, const FuncValuePack& pack, - VirtReg* const* vRegs) noexcept { + const RegOnly* vRegs) noexcept { size_t count = pack.count(); if (!count) @@ -358,11 +343,16 @@ static Error formatFuncValuePack( if (valueIndex) ASMJIT_PROPAGATE(sb.append(", ")); - ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, emitter, value)); + ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, cc, value)); if (vRegs) { - static const char nullRet[] = "<none>"; - ASMJIT_PROPAGATE(sb.appendFormat(" %s", vRegs[valueIndex] ? vRegs[valueIndex]->name() : nullRet)); + const VirtReg* virtReg = nullptr; + static const char nullReg[] = "<none>"; + + if (vRegs[valueIndex].isReg() && cc->isVirtIdValid(vRegs[valueIndex].id())) + virtReg = cc->virtRegById(vRegs[valueIndex].id()); + + ASMJIT_PROPAGATE(sb.appendFormat(" %s", virtReg ? virtReg->name() : nullReg)); } } @@ -374,17 +364,17 @@ static Error formatFuncValuePack( static Error formatFuncRets( String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, + FormatFlags formatFlags, + const BaseCompiler* cc, const FuncDetail& fd) noexcept { - return formatFuncValuePack(sb, formatFlags, emitter, fd.retPack(), nullptr); + return formatFuncValuePack(sb, formatFlags, cc, fd.retPack(), nullptr); } static Error formatFuncArgs( String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, + FormatFlags formatFlags, + const BaseCompiler* cc, const FuncDetail& fd, const FuncNode::ArgPack* argPacks) noexcept { @@ -396,7 +386,7 @@ static Error formatFuncArgs( if (argIndex) ASMJIT_PROPAGATE(sb.append(", ")); - ASMJIT_PROPAGATE(formatFuncValuePack(sb, formatFlags, emitter, fd.argPack(argIndex), argPacks[argIndex]._data)); + ASMJIT_PROPAGATE(formatFuncValuePack(sb, formatFlags, cc, fd.argPack(argIndex), argPacks[argIndex]._data)); } return kErrorOk; @@ -405,25 +395,26 @@ static Error formatFuncArgs( Error formatNode( String& sb, - uint32_t formatFlags, + const FormatOptions& formatOptions, const BaseBuilder* builder, const BaseNode* node) noexcept { - if (node->hasPosition() && (formatFlags & FormatOptions::kFlagPositions) != 0) + if (node->hasPosition() && formatOptions.hasFlag(FormatFlags::kPositions)) ASMJIT_PROPAGATE(sb.appendFormat("<%05u> ", node->position())); + size_t startLineIndex = sb.size(); + switch (node->type()) { - case BaseNode::kNodeInst: - case BaseNode::kNodeJump: { + case NodeType::kInst: + case NodeType::kJump: { const InstNode* instNode = node->as<InstNode>(); - ASMJIT_PROPAGATE( - formatInstruction(sb, formatFlags, builder, - builder->arch(), - instNode->baseInst(), instNode->operands(), instNode->opCount())); + ASMJIT_PROPAGATE(formatInstruction(sb, formatOptions.flags(), builder, + builder->arch(), + instNode->baseInst(), instNode->operands(), instNode->opCount())); break; } - case BaseNode::kNodeSection: { + case NodeType::kSection: { const SectionNode* sectionNode = node->as<SectionNode>(); if (builder->_code->isSectionValid(sectionNode->id())) { const Section* section = builder->_code->sectionById(sectionNode->id()); @@ -432,65 +423,64 @@ Error formatNode( break; } - case BaseNode::kNodeLabel: { + case NodeType::kLabel: { const LabelNode* labelNode = node->as<LabelNode>(); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, labelNode->labelId())); + ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, labelNode->labelId())); ASMJIT_PROPAGATE(sb.append(":")); break; } - case BaseNode::kNodeAlign: { + case NodeType::kAlign: { const AlignNode* alignNode = node->as<AlignNode>(); - ASMJIT_PROPAGATE( - sb.appendFormat(".align %u (%s)", - alignNode->alignment(), - alignNode->alignMode() == kAlignCode ? "code" : "data")); + ASMJIT_PROPAGATE(sb.appendFormat(".align %u (%s)", + alignNode->alignment(), + alignNode->alignMode() == AlignMode::kCode ? "code" : "data")); break; } - case BaseNode::kNodeEmbedData: { + case NodeType::kEmbedData: { const EmbedDataNode* embedNode = node->as<EmbedDataNode>(); ASMJIT_PROPAGATE(sb.append('.')); - ASMJIT_PROPAGATE(formatDataType(sb, formatFlags, builder->arch(), embedNode->typeId())); + ASMJIT_PROPAGATE(formatDataType(sb, formatOptions.flags(), builder->arch(), embedNode->typeId())); ASMJIT_PROPAGATE(sb.appendFormat(" {Count=%zu Repeat=%zu TotalSize=%zu}", embedNode->itemCount(), embedNode->repeatCount(), embedNode->dataSize())); break; } - case BaseNode::kNodeEmbedLabel: { + case NodeType::kEmbedLabel: { const EmbedLabelNode* embedNode = node->as<EmbedLabelNode>(); ASMJIT_PROPAGATE(sb.append(".label ")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId())); + ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, embedNode->labelId())); break; } - case BaseNode::kNodeEmbedLabelDelta: { + case NodeType::kEmbedLabelDelta: { const EmbedLabelDeltaNode* embedNode = node->as<EmbedLabelDeltaNode>(); ASMJIT_PROPAGATE(sb.append(".label (")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId())); + ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, embedNode->labelId())); ASMJIT_PROPAGATE(sb.append(" - ")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->baseLabelId())); + ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, embedNode->baseLabelId())); ASMJIT_PROPAGATE(sb.append(")")); break; } - case BaseNode::kNodeConstPool: { + case NodeType::kConstPool: { const ConstPoolNode* constPoolNode = node->as<ConstPoolNode>(); ASMJIT_PROPAGATE(sb.appendFormat("[ConstPool Size=%zu Alignment=%zu]", constPoolNode->size(), constPoolNode->alignment())); break; }; - case BaseNode::kNodeComment: { + case NodeType::kComment: { const CommentNode* commentNode = node->as<CommentNode>(); ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment())); break; } - case BaseNode::kNodeSentinel: { + case NodeType::kSentinel: { const SentinelNode* sentinelNode = node->as<SentinelNode>(); const char* sentinelName = nullptr; switch (sentinelNode->sentinelType()) { - case SentinelNode::kSentinelFuncEnd: + case SentinelType::kFuncEnd: sentinelName = "[FuncEnd]"; break; @@ -504,20 +494,22 @@ Error formatNode( } #ifndef ASMJIT_NO_COMPILER - case BaseNode::kNodeFunc: { + case NodeType::kFunc: { const FuncNode* funcNode = node->as<FuncNode>(); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, funcNode->labelId())); - ASMJIT_PROPAGATE(sb.append(": ")); + if (builder->isCompiler()) { + ASMJIT_PROPAGATE(formatLabel(sb, formatOptions.flags(), builder, funcNode->labelId())); + ASMJIT_PROPAGATE(sb.append(": ")); - ASMJIT_PROPAGATE(formatFuncRets(sb, formatFlags, builder, funcNode->detail())); - ASMJIT_PROPAGATE(sb.append(" Func(")); - ASMJIT_PROPAGATE(formatFuncArgs(sb, formatFlags, builder, funcNode->detail(), funcNode->argPacks())); - ASMJIT_PROPAGATE(sb.append(")")); + ASMJIT_PROPAGATE(formatFuncRets(sb, formatOptions.flags(), static_cast<const BaseCompiler*>(builder), funcNode->detail())); + ASMJIT_PROPAGATE(sb.append(" Func(")); + ASMJIT_PROPAGATE(formatFuncArgs(sb, formatOptions.flags(), static_cast<const BaseCompiler*>(builder), funcNode->detail(), funcNode->argPacks())); + ASMJIT_PROPAGATE(sb.append(")")); + } break; } - case BaseNode::kNodeFuncRet: { + case NodeType::kFuncRet: { const FuncRetNode* retNode = node->as<FuncRetNode>(); ASMJIT_PROPAGATE(sb.append("[FuncRet]")); @@ -525,18 +517,17 @@ Error formatNode( const Operand_& op = retNode->_opArray[i]; if (!op.isNone()) { ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); - ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, builder, builder->arch(), op)); + ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op)); } } break; } - case BaseNode::kNodeInvoke: { + case NodeType::kInvoke: { const InvokeNode* invokeNode = node->as<InvokeNode>(); - ASMJIT_PROPAGATE( - formatInstruction(sb, formatFlags, builder, - builder->arch(), - invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount())); + ASMJIT_PROPAGATE(formatInstruction(sb, formatOptions.flags(), builder, + builder->arch(), + invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount())); break; } #endif @@ -547,28 +538,38 @@ Error formatNode( } } + if (node->hasInlineComment()) { + size_t requiredPadding = paddingFromOptions(formatOptions, FormatPaddingGroup::kRegularLine); + size_t currentPadding = sb.size() - startLineIndex; + + if (currentPadding < requiredPadding) + ASMJIT_PROPAGATE(sb.appendChars(' ', requiredPadding - currentPadding)); + + ASMJIT_PROPAGATE(sb.append("; ")); + ASMJIT_PROPAGATE(sb.append(node->inlineComment())); + } + return kErrorOk; } - Error formatNodeList( String& sb, - uint32_t formatFlags, + const FormatOptions& formatOptions, const BaseBuilder* builder) noexcept { - return formatNodeList(sb, formatFlags, builder, builder->firstNode(), nullptr); + return formatNodeList(sb, formatOptions, builder, builder->firstNode(), nullptr); } Error formatNodeList( String& sb, - uint32_t formatFlags, + const FormatOptions& formatOptions, const BaseBuilder* builder, const BaseNode* begin, const BaseNode* end) noexcept { const BaseNode* node = begin; while (node != end) { - ASMJIT_PROPAGATE(formatNode(sb, formatFlags, builder, node)); + ASMJIT_PROPAGATE(formatNode(sb, formatOptions, builder, node)); ASMJIT_PROPAGATE(sb.append('\n')); node = node->next(); } diff --git a/src/asmjit/core/formatter.h b/src/asmjit/core/formatter.h index 513d764..d7a4b93 100644 --- a/src/asmjit/core/formatter.h +++ b/src/asmjit/core/formatter.h @@ -1,126 +1,98 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_FORMATTER_H_INCLUDED #define ASMJIT_CORE_FORMATTER_H_INCLUDED +#include "../core/globals.h" #include "../core/inst.h" #include "../core/string.h" - -#ifndef ASMJIT_NO_LOGGING +#include "../core/support.h" ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_logging //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - +class BaseBuilder; class BaseEmitter; +class BaseNode; struct Operand_; -#ifndef ASMJIT_NO_BUILDER -class BaseBuilder; -class BaseNode; -#endif +//! Format flags used by \ref Logger and \ref FormatOptions. +enum class FormatFlags : uint32_t { + //! No formatting flags. + kNone = 0u, + + //! Show also binary form of each logged instruction (Assembler). + kMachineCode = 0x00000001u, + //! Show a text explanation of some immediate values. + kExplainImms = 0x00000002u, + //! Use hexadecimal notation of immediate values. + kHexImms = 0x00000004u, + //! Use hexadecimal notation of addresses and offsets in addresses. + kHexOffsets = 0x00000008u, + //! Show casts between virtual register types (Compiler output). + kRegCasts = 0x00000010u, + //! Show positions associated with nodes (Compiler output). + kPositions = 0x00000020u +}; +ASMJIT_DEFINE_ENUM_FLAGS(FormatFlags) + +//! Format indentation group, used by \ref FormatOptions. +enum class FormatIndentationGroup : uint32_t { + //! Indentation used for instructions and directives. + kCode = 0u, + //! Indentation used for labels and function nodes. + kLabel = 1u, + //! Indentation used for comments (not inline comments). + kComment = 2u, + + //! \cond INTERNAL + //! Reserved for future use. + kReserved = 3u, + //! \endcond + + //! Maximum value of `FormatIndentationGroup`. + kMaxValue = kReserved +}; -#ifndef ASMJIT_NO_COMPILER -class BaseCompiler; -#endif +//! Format padding group, used by \ref FormatOptions. +enum class FormatPaddingGroup : uint32_t { + //! Describes padding of a regular line, which can represent instruction, data, or assembler directives. + kRegularLine = 0, + //! Describes padding of machine code dump that is visible next to the instruction, if enabled. + kMachineCode = 1, -// ============================================================================ -// [asmjit::FormatOptions] -// ============================================================================ + //! Maximum value of `FormatPaddingGroup`. + kMaxValue = kMachineCode +}; //! Formatting options used by \ref Logger and \ref Formatter. class FormatOptions { public: - //! Format flags, see \ref Flags. - uint32_t _flags; - //! Indentation by type, see \ref IndentationType. - uint8_t _indentation[4]; - - //! Flags can enable a logging feature. - enum Flags : uint32_t { - //! No flags. - kNoFlags = 0u, - - //! Show also binary form of each logged instruction (Assembler). - kFlagMachineCode = 0x00000001u, - //! Show a text explanation of some immediate values. - kFlagExplainImms = 0x00000002u, - //! Use hexadecimal notation of immediate values. - kFlagHexImms = 0x00000004u, - //! Use hexadecimal notation of address offsets. - kFlagHexOffsets = 0x00000008u, - //! Show casts between virtual register types (Compiler). - kFlagRegCasts = 0x00000010u, - //! Show positions associated with nodes (Compiler). - kFlagPositions = 0x00000020u, - //! Annotate nodes that are lowered by passes. - kFlagAnnotations = 0x00000040u, - - // TODO: These must go, keep this only for formatting. - //! Show an additional output from passes. - kFlagDebugPasses = 0x00000080u, - //! Show an additional output from RA. - kFlagDebugRA = 0x00000100u - }; - - //! Describes indentation type of code, label, or comment in logger output. - enum IndentationType : uint32_t { - //! Indentation used for instructions and directives. - kIndentationCode = 0u, - //! Indentation used for labels and function nodes. - kIndentationLabel = 1u, - //! Indentation used for comments (not inline comments). - kIndentationComment = 2u, - //! \cond INTERNAL - //! Reserved for future use. - kIndentationReserved = 3u - //! \endcond - }; - - //! \name Construction & Destruction + //! \name Members //! \{ - //! Creates a default-initialized FormatOptions. - constexpr FormatOptions() noexcept - : _flags(0), - _indentation { 0, 0, 0, 0 } {} + //! Format flags. + FormatFlags _flags = FormatFlags::kNone; + //! Indentations for each indentation group. + Support::Array<uint8_t, uint32_t(FormatIndentationGroup::kMaxValue) + 1> _indentation {}; + //! Paddings for each padding group. + Support::Array<uint16_t, uint32_t(FormatPaddingGroup::kMaxValue) + 1> _padding {}; - constexpr FormatOptions(const FormatOptions& other) noexcept = default; - inline FormatOptions& operator=(const FormatOptions& other) noexcept = default; + //! \} + + //! \name Reset + //! \{ //! Resets FormatOptions to its default initialized state. inline void reset() noexcept { - _flags = 0; - _indentation[0] = 0; - _indentation[1] = 0; - _indentation[2] = 0; - _indentation[3] = 0; + _flags = FormatFlags::kNone; + _indentation.fill(uint8_t(0)); + _padding.fill(uint16_t(0)); } //! \} @@ -129,104 +101,109 @@ public: //! \{ //! Returns format flags. - constexpr uint32_t flags() const noexcept { return _flags; } + inline FormatFlags flags() const noexcept { return _flags; } //! Tests whether the given `flag` is set in format flags. - constexpr bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } + inline bool hasFlag(FormatFlags flag) const noexcept { return Support::test(_flags, flag); } + //! Resets all format flags to `flags`. - inline void setFlags(uint32_t flags) noexcept { _flags = flags; } + inline void setFlags(FormatFlags flags) noexcept { _flags = flags; } //! Adds `flags` to format flags. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } + inline void addFlags(FormatFlags flags) noexcept { _flags |= flags; } //! Removes `flags` from format flags. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } - - //! Returns indentation for the given `type`, see \ref IndentationType. - constexpr uint8_t indentation(uint32_t type) const noexcept { return _indentation[type]; } - //! Sets indentation for the given `type`, see \ref IndentationType. - inline void setIndentation(uint32_t type, uint32_t n) noexcept { _indentation[type] = uint8_t(n); } - //! Resets indentation for the given `type` to zero. - inline void resetIndentation(uint32_t type) noexcept { _indentation[type] = uint8_t(0); } + inline void clearFlags(FormatFlags flags) noexcept { _flags &= ~flags; } + + //! Returns indentation for the given indentation `group`. + inline uint8_t indentation(FormatIndentationGroup group) const noexcept { return _indentation[group]; } + //! Sets indentation for the given indentation `group`. + inline void setIndentation(FormatIndentationGroup group, uint32_t n) noexcept { _indentation[group] = uint8_t(n); } + //! Resets indentation for the given indentation `group` to zero. + inline void resetIndentation(FormatIndentationGroup group) noexcept { _indentation[group] = uint8_t(0); } + + //! Returns pading for the given padding `group`. + inline size_t padding(FormatPaddingGroup group) const noexcept { return _padding[group]; } + //! Sets pading for the given padding `group`. + inline void setPadding(FormatPaddingGroup group, size_t n) noexcept { _padding[group] = uint16_t(n); } + //! Resets pading for the given padding `group` to zero, which means that a default padding will be used + //! based on the target architecture properties. + inline void resetPadding(FormatPaddingGroup group) noexcept { _padding[group] = uint16_t(0); } //! \} }; -// ============================================================================ -// [asmjit::Formatter] -// ============================================================================ - //! Provides formatting functionality to format operands, instructions, and nodes. namespace Formatter { +#ifndef ASMJIT_NO_LOGGING + //! Appends a formatted `typeId` to the output string `sb`. ASMJIT_API Error formatTypeId( String& sb, - uint32_t typeId) noexcept; + TypeId typeId) noexcept; //! Appends a formatted `featureId` to the output string `sb`. //! -//! See \ref BaseFeatures. +//! See \ref CpuFeatures. ASMJIT_API Error formatFeature( String& sb, - uint32_t arch, + Arch arch, uint32_t featureId) noexcept; //! Appends a formatted register to the output string `sb`. //! -//! \note Emitter is optional, but it's required to format virtual registers, -//! which won't be formatted properly if the `emitter` is not provided. +//! \note Emitter is optional, but it's required to format virtual registers, which won't be formatted properly +//! if the `emitter` is not provided. ASMJIT_API Error formatRegister( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, + Arch arch, + RegType regType, uint32_t regId) noexcept; //! Appends a formatted label to the output string `sb`. //! -//! \note Emitter is optional, but it's required to format named labels -//! properly, otherwise the formatted as it is an anonymous label. +//! \note Emitter is optional, but it's required to format named labels properly, otherwise the formatted as +//! it is an anonymous label. ASMJIT_API Error formatLabel( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, uint32_t labelId) noexcept; //! Appends a formatted operand to the output string `sb`. //! -//! \note Emitter is optional, but it's required to format named labels and -//! virtual registers. See \ref formatRegister() and \ref formatLabel() for -//! more details. +//! \note Emitter is optional, but it's required to format named labels and virtual registers. See +//! \ref formatRegister() and \ref formatLabel() for more details. ASMJIT_API Error formatOperand( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const Operand_& op) noexcept; //! Appends a formatted data-type to the output string `sb`. ASMJIT_API Error formatDataType( String& sb, - uint32_t formatFlags, - uint32_t arch, - uint32_t typeId) noexcept; + FormatFlags formatFlags, + Arch arch, + TypeId typeId) noexcept; //! Appends a formatted data to the output string `sb`. ASMJIT_API Error formatData( String& sb, - uint32_t formatFlags, - uint32_t arch, - uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) noexcept; + FormatFlags formatFlags, + Arch arch, + TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) noexcept; //! Appends a formatted instruction to the output string `sb`. //! -//! \note Emitter is optional, but it's required to format named labels and -//! virtual registers. See \ref formatRegister() and \ref formatLabel() for -//! more details. +//! \note Emitter is optional, but it's required to format named labels and virtual registers. See +//! \ref formatRegister() and \ref formatLabel() for more details. ASMJIT_API Error formatInstruction( String& sb, - uint32_t formatFlags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept; #ifndef ASMJIT_NO_BUILDER @@ -235,7 +212,7 @@ ASMJIT_API Error formatInstruction( //! The `node` must belong to the provided `builder`. ASMJIT_API Error formatNode( String& sb, - uint32_t formatFlags, + const FormatOptions& formatOptions, const BaseBuilder* builder, const BaseNode* node) noexcept; @@ -244,27 +221,27 @@ ASMJIT_API Error formatNode( //! All nodes that are part of the given `builder` will be appended. ASMJIT_API Error formatNodeList( String& sb, - uint32_t formatFlags, + const FormatOptions& formatOptions, const BaseBuilder* builder) noexcept; //! Appends formatted nodes to the output string `sb`. //! -//! This function works the same as \ref formatNode(), but appends more nodes -//! to the output string, separating each node with a newline '\n' character. +//! This function works the same as \ref formatNode(), but appends more nodes to the output string, +//! separating each node with a newline '\n' character. ASMJIT_API Error formatNodeList( String& sb, - uint32_t formatFlags, + const FormatOptions& formatOptions, const BaseBuilder* builder, const BaseNode* begin, const BaseNode* end) noexcept; #endif +#endif + } // {Formatter} //! \} ASMJIT_END_NAMESPACE -#endif - #endif // ASMJIT_CORE_FORMATTER_H_INCLUDED diff --git a/src/asmjit/core/formatter_p.h b/src/asmjit/core/formatter_p.h new file mode 100644 index 0000000..6070fd7 --- /dev/null +++ b/src/asmjit/core/formatter_p.h @@ -0,0 +1,34 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_CORE_FORMATTER_P_H_INCLUDED +#define ASMJIT_CORE_FORMATTER_P_H_INCLUDED + +#include "../core/formatter.h" + +ASMJIT_BEGIN_NAMESPACE + +//! \cond INTERNAL +//! \addtogroup asmjit_logging +//! \{ + +namespace Formatter { + +static ASMJIT_FORCE_INLINE size_t paddingFromOptions(const FormatOptions& formatOptions, FormatPaddingGroup group) noexcept { + static constexpr uint16_t _defaultPaddingTable[uint32_t(FormatPaddingGroup::kMaxValue) + 1] = { 44, 26 }; + static_assert(uint32_t(FormatPaddingGroup::kMaxValue) + 1 == 2, "If a new group is defined it must be added here"); + + size_t padding = formatOptions.padding(group); + return padding ? padding : size_t(_defaultPaddingTable[uint32_t(group)]); +} + +} // {Formatter} + +//! \} +//! \endcond + +ASMJIT_END_NAMESPACE + +#endif // ASMJIT_CORE_FORMATTER_H_P_INCLUDED diff --git a/src/asmjit/core/func.cpp b/src/asmjit/core/func.cpp index cf017fe..fcc962c 100644 --- a/src/asmjit/core/func.cpp +++ b/src/asmjit/core/func.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/archtraits.h" @@ -38,11 +20,10 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::CallConv - Init / Reset] -// ============================================================================ +// CallConv - Init & Reset +// ======================= -ASMJIT_FAVOR_SIZE Error CallConv::init(uint32_t ccId, const Environment& environment) noexcept { +ASMJIT_FAVOR_SIZE Error CallConv::init(CallConvId ccId, const Environment& environment) noexcept { reset(); #if !defined(ASMJIT_NO_X86) @@ -58,12 +39,11 @@ ASMJIT_FAVOR_SIZE Error CallConv::init(uint32_t ccId, const Environment& environ return DebugUtils::errored(kErrorInvalidArgument); } -// ============================================================================ -// [asmjit::FuncDetail - Init / Reset] -// ============================================================================ +// FuncDetail - Init / Reset +// ========================= ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const Environment& environment) noexcept { - uint32_t ccId = signature.callConv(); + CallConvId ccId = signature.callConvId(); uint32_t argCount = signature.argCount(); if (ASMJIT_UNLIKELY(argCount > Globals::kMaxFuncArgs)) @@ -73,19 +53,20 @@ ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const E ASMJIT_PROPAGATE(cc.init(ccId, environment)); uint32_t registerSize = Environment::registerSizeFromArch(cc.arch()); - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize); + uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize); - const uint8_t* signatureArgs = signature.args(); + const TypeId* signatureArgs = signature.args(); for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { FuncValuePack& argPack = _args[argIndex]; - argPack[0].initTypeId(Type::deabstract(signatureArgs[argIndex], deabstractDelta)); + argPack[0].initTypeId(TypeUtils::deabstract(signatureArgs[argIndex], deabstractDelta)); } + _argCount = uint8_t(argCount); _vaIndex = uint8_t(signature.vaIndex()); - uint32_t ret = signature.ret(); - if (ret != Type::kIdVoid) - _rets[0].initTypeId(Type::deabstract(ret, deabstractDelta)); + TypeId ret = signature.ret(); + if (ret != TypeId::kVoid) + _rets[0].initTypeId(TypeUtils::deabstract(ret, deabstractDelta)); #if !defined(ASMJIT_NO_X86) if (environment.isFamilyX86()) @@ -97,28 +78,26 @@ ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const E return arm::FuncInternal::initFuncDetail(*this, signature, registerSize); #endif - // We should never bubble here as if `cc.init()` succeeded then there has to - // be an implementation for the current architecture. However, stay safe. + // We should never bubble here as if `cc.init()` succeeded then there has to be an implementation for the current + // architecture. However, stay safe. return DebugUtils::errored(kErrorInvalidArgument); } -// ============================================================================ -// [asmjit::FuncFrame - Init / Finalize] -// ============================================================================ +// FuncFrame - Init +// ================ ASMJIT_FAVOR_SIZE Error FuncFrame::init(const FuncDetail& func) noexcept { - uint32_t arch = func.callConv().arch(); + Arch arch = func.callConv().arch(); if (!Environment::isValidArch(arch)) return DebugUtils::errored(kErrorInvalidArch); const ArchTraits& archTraits = ArchTraits::byArch(arch); - // Initializing FuncFrame means making a copy of some properties of `func`. - // Properties like `_localStackSize` will be set by the user before the frame - // is finalized. + // Initializing FuncFrame means making a copy of some properties of `func`. Properties like `_localStackSize` will + // be set by the user before the frame is finalized. reset(); - _arch = uint8_t(arch); + _arch = arch; _spRegId = uint8_t(archTraits.spRegId()); _saRegId = uint8_t(BaseReg::kIdBad); @@ -134,34 +113,37 @@ ASMJIT_FAVOR_SIZE Error FuncFrame::init(const FuncDetail& func) noexcept { _spillZoneSize = uint8_t(func.spillZoneSize()); _finalStackAlignment = uint8_t(_naturalStackAlignment); - if (func.hasFlag(CallConv::kFlagCalleePopsStack)) { + if (func.hasFlag(CallConvFlags::kCalleePopsStack)) { _calleeStackCleanup = uint16_t(func.argStackSize()); } // Initial masks of dirty and preserved registers. - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { _dirtyRegs[group] = func.usedRegs(group); _preservedRegs[group] = func.preservedRegs(group); } // Exclude stack pointer - this register is never included in saved GP regs. - _preservedRegs[BaseReg::kGroupGp] &= ~Support::bitMask(archTraits.spRegId()); + _preservedRegs[RegGroup::kGp] &= ~Support::bitMask(archTraits.spRegId()); - // The size and alignment of save/restore area of registers for each significant register group. - memcpy(_saveRestoreRegSize, func.callConv()._saveRestoreRegSize, sizeof(_saveRestoreRegSize)); - memcpy(_saveRestoreAlignment, func.callConv()._saveRestoreAlignment, sizeof(_saveRestoreAlignment)); + // The size and alignment of save/restore area of registers for each virtual register group + _saveRestoreRegSize = func.callConv()._saveRestoreRegSize; + _saveRestoreAlignment = func.callConv()._saveRestoreAlignment; return kErrorOk; } +// FuncFrame - Finalize +// ==================== + ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { if (!Environment::isValidArch(arch())) return DebugUtils::errored(kErrorInvalidArch); const ArchTraits& archTraits = ArchTraits::byArch(arch()); - uint32_t registerSize = _saveRestoreRegSize[BaseReg::kGroupGp]; - uint32_t vectorSize = _saveRestoreRegSize[BaseReg::kGroupVec]; + uint32_t registerSize = _saveRestoreRegSize[RegGroup::kGp]; + uint32_t vectorSize = _saveRestoreRegSize[RegGroup::kVec]; uint32_t returnAddressSize = archTraits.hasLinkReg() ? 0u : registerSize; // The final stack alignment must be updated accordingly to call and local stack alignments. @@ -179,12 +161,12 @@ ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { // Make frame pointer dirty if the function uses it. if (hasFP) { - _dirtyRegs[BaseReg::kGroupGp] |= Support::bitMask(kFp); + _dirtyRegs[RegGroup::kGp] |= Support::bitMask(kFp); - // Currently required by ARM, if this works differently across architectures - // we would have to generalize most likely in CallConv. + // Currently required by ARM, if this works differently across architectures we would have to generalize most + // likely in CallConv. if (kLr != BaseReg::kIdBad) - _dirtyRegs[BaseReg::kGroupGp] |= Support::bitMask(kLr); + _dirtyRegs[RegGroup::kGp] |= Support::bitMask(kLr); } // These two are identical if the function doesn't align its stack dynamically. @@ -192,22 +174,22 @@ ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { if (saRegId == BaseReg::kIdBad) saRegId = kSp; - // Fix stack arguments base-register from SP to FP in case it was not picked - // before and the function performs dynamic stack alignment. + // Fix stack arguments base-register from SP to FP in case it was not picked before and the function performs + // dynamic stack alignment. if (hasDA && saRegId == kSp) saRegId = kFp; // Mark as dirty any register but SP if used as SA pointer. if (saRegId != kSp) - _dirtyRegs[BaseReg::kGroupGp] |= Support::bitMask(saRegId); + _dirtyRegs[RegGroup::kGp] |= Support::bitMask(saRegId); _spRegId = uint8_t(kSp); _saRegId = uint8_t(saRegId); // Setup stack size used to save preserved registers. uint32_t saveRestoreSizes[2] {}; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - saveRestoreSizes[size_t(!archTraits.hasPushPop(group))] + for (RegGroup group : RegGroupVirtValues{}) + saveRestoreSizes[size_t(!archTraits.hasInstPushPop(group))] += Support::alignUp(Support::popcnt(savedRegs(group)) * saveRestoreRegSize(group), saveRestoreAlignment(group)); _pushPopSaveSize = uint16_t(saveRestoreSizes[0]); @@ -220,11 +202,10 @@ ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { _localStackOffset = v; // Store 'localStackOffset' <- Function's local stack starts here. v += localStackSize(); // Count 'localStackSize' <- Function's local stack ends here. - // If the function's stack must be aligned, calculate the alignment necessary - // to store vector registers, and set `FuncFrame::kAttrAlignedVecSR` to inform - // PEI that it can use instructions that perform aligned stores/loads. + // If the function's stack must be aligned, calculate the alignment necessary to store vector registers, and set + // `FuncAttributes::kAlignedVecSR` to inform PEI that it can use instructions that perform aligned stores/loads. if (stackAlignment >= vectorSize && _extraRegSaveSize) { - addAttributes(FuncFrame::kAttrAlignedVecSR); + addAttributes(FuncAttributes::kAlignedVecSR); v = Support::alignUp(v, vectorSize); // Align 'extraRegSaveOffset'. } @@ -243,23 +224,19 @@ ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { // Link Register // ------------- // - // The stack is aligned after the function call as the return address is - // stored in a link register. Some architectures may require to always - // have aligned stack after PUSH/POP operation, which is represented by - // ArchTraits::stackAlignmentConstraint(). + // The stack is aligned after the function call as the return address is stored in a link register. Some + // architectures may require to always have aligned stack after PUSH/POP operation, which is represented + // by ArchTraits::stackAlignmentConstraint(). // // No Link Register (X86/X64) // -------------------------- // - // The return address should be stored after GP save/restore regs. It has - // the same size as `registerSize` (basically the native register/pointer - // size). We don't adjust it now as `v` now contains the exact size that the - // function requires to adjust (call frame + stack frame, vec stack size). - // The stack (if we consider this size) is misaligned now, as it's always - // aligned before the function call - when `call()` is executed it pushes - // the current EIP|RIP onto the stack, and misaligns it by 12 or 8 bytes - // (depending on the architecture). So count number of bytes needed to align - // it up to the function's CallFrame (the beginning). + // The return address should be stored after GP save/restore regs. It has the same size as `registerSize` + // (basically the native register/pointer size). We don't adjust it now as `v` now contains the exact size + // that the function requires to adjust (call frame + stack frame, vec stack size). The stack (if we consider + // this size) is misaligned now, as it's always aligned before the function call - when `call()` is executed + // it pushes the current EIP|RIP onto the stack, and misaligns it by 12 or 8 bytes (depending on the + // architecture). So count number of bytes needed to align it up to the function's CallFrame (the beginning). if (v || hasFuncCalls() || !returnAddressSize) v += Support::alignUpDiff(v + pushPopSaveSize() + returnAddressSize, stackAlignment); @@ -285,12 +262,11 @@ ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::FuncArgsAssignment] -// ============================================================================ +// FuncArgsAssignment - UpdateFuncFrame +// ==================================== ASMJIT_FAVOR_SIZE Error FuncArgsAssignment::updateFuncFrame(FuncFrame& frame) const noexcept { - uint32_t arch = frame.arch(); + Arch arch = frame.arch(); const FuncDetail* func = funcDetail(); if (!func) diff --git a/src/asmjit/core/func.h b/src/asmjit/core/func.h index 9f63096..8ecf148 100644 --- a/src/asmjit/core/func.h +++ b/src/asmjit/core/func.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_FUNC_H_INCLUDED #define ASMJIT_CORE_FUNC_H_INCLUDED @@ -35,23 +17,172 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_function //! \{ -// ============================================================================ -// [asmjit::CallConv] -// ============================================================================ +//! Calling convention id. +//! +//! Calling conventions can be divided into the following groups: +//! +//! - Universal - calling conventions are applicable to any target. They will be converted to a target dependent +//! calling convention at runtime by \ref CallConv::init() with some help from \ref Environment. The purpose of +//! these calling conventions is to make using functions less target dependent and closer to C and C++. +//! +//! - Target specific - calling conventions that are used by a particular architecture and ABI. For example +//! Windows 64-bit calling convention and AMD64 SystemV calling convention. +enum class CallConvId : uint8_t { + //! None or invalid (can't be used). + kNone = 0, + + // Universal Calling Conventions + // ----------------------------- + + //! Standard function call or explicit `__cdecl` where it can be specified. + //! + //! This is a universal calling convention, which is used to initialize specific calling connventions based on + //! architecture, platform, and its ABI. + kCDecl = 1, + + //! `__stdcall` on targets that support this calling convention (X86). + //! + //! \note This calling convention is only supported on 32-bit X86. If used on environment that doesn't support + //! this calling convention it will be replaced by \ref CallConvId::kCDecl. + kStdCall = 2, + + //! `__fastcall` on targets that support this calling convention (X86). + //! + //! \note This calling convention is only supported on 32-bit X86. If used on environment that doesn't support + //! this calling convention it will be replaced by \ref CallConvId::kCDecl. + kFastCall = 3, + + //! `__vectorcall` on targets that support this calling convention (X86/X64). + //! + //! \note This calling convention is only supported on 32-bit and 64-bit X86 architecture on Windows platform. + //! If used on environment that doesn't support this calling it will be replaced by \ref CallConvId::kCDecl. + kVectorCall = 4, + + //! `__thiscall` on targets that support this calling convention (X86). + //! + //! \note This calling convention is only supported on 32-bit X86 Windows platform. If used on environment that + //! doesn't support this calling convention it will be replaced by \ref CallConvId::kCDecl. + kThisCall = 5, + + //! `__attribute__((regparm(1)))` convention (GCC and Clang). + kRegParm1 = 6, + //! `__attribute__((regparm(2)))` convention (GCC and Clang). + kRegParm2 = 7, + //! `__attribute__((regparm(3)))` convention (GCC and Clang). + kRegParm3 = 8, + + //! Soft-float calling convention (ARM). + //! + //! Floating point arguments are passed via general purpose registers. + kSoftFloat = 9, + + //! Hard-float calling convention (ARM). + //! + //! Floating point arguments are passed via SIMD registers. + kHardFloat = 10, + + //! AsmJit specific calling convention designed for calling functions inside a multimedia code that don't use many + //! registers internally, but are long enough to be called and not inlined. These functions are usually used to + //! calculate trigonometric functions, logarithms, etc... + kLightCall2 = 16, + kLightCall3 = 17, + kLightCall4 = 18, + + // ABI-Specific Calling Conventions + // -------------------------------- + + //! X64 System-V calling convention. + kX64SystemV = 32, + //! X64 Windows calling convention. + kX64Windows = 33, + + //! Maximum value of `CallConvId`. + kMaxValue = kX64Windows, + + // Host Calling Conventions + // ------------------------ + + //! Host calling convention detected at compile-time. + kHost = +#if defined(_DOXYGEN) + DETECTED_AT_COMPILE_TIME +#elif ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) + kSoftFloat +#elif ASMJIT_ARCH_ARM == 32 && !defined(__SOFTFP__) + kHardFloat +#else + kCDecl +#endif +}; + +//! Strategy used by calling conventions to assign registers to function arguments. +//! +//! Calling convention strategy describes how AsmJit should convert function arguments used by \ref FuncSignature +//! into register identifiers and stack offsets. The \ref CallConvStrategy::kDefault strategy assigns registers +//! and then stack whereas \ref CallConvStrategy::kX64Windows strategy does register shadowing as defined by WIN64 +//! calling convention, which is only used by 64-bit Windows. +enum class CallConvStrategy : uint8_t { + //! Default register assignment strategy. + kDefault = 0, + //! Windows 64-bit ABI register assignment strategy. + kX64Windows = 1, + //! Windows 64-bit __vectorcall register assignment strategy. + kX64VectorCall = 2, + + //! Maximum value of `CallConvStrategy`. + kMaxValue = kX64VectorCall +}; + +//! Calling convention flags. +enum class CallConvFlags : uint32_t { + //! No flags. + kNone = 0, + //! Callee is responsible for cleaning up the stack. + kCalleePopsStack = 0x0001u, + //! Pass vector arguments indirectly (as a pointer). + kIndirectVecArgs = 0x0002u, + //! Pass F32 and F64 arguments via VEC128 register. + kPassFloatsByVec = 0x0004u, + //! Pass MMX and vector arguments via stack if the function has variable arguments. + kPassVecByStackIfVA = 0x0008u, + //! MMX registers are passed and returned via GP registers. + kPassMmxByGp = 0x0010u, + //! MMX registers are passed and returned via XMM registers. + kPassMmxByXmm = 0x0020u, + //! Calling convention can be used with variable arguments. + kVarArgCompatible = 0x0080u +}; +ASMJIT_DEFINE_ENUM_FLAGS(CallConvFlags) //! Function calling convention. //! -//! Function calling convention is a scheme that defines how function parameters -//! are passed and how function returns its result. AsmJit defines a variety of -//! architecture and OS specific calling conventions and also provides a compile -//! time detection to make the code-generation easier. +//! Function calling convention is a scheme that defines how function parameters are passed and how function +//! returns its result. AsmJit defines a variety of architecture and OS specific calling conventions and also +//! provides a compile time detection to make the code-generation easier. struct CallConv { - //! Calling convention id, see \ref Id. - uint8_t _id; - //! Architecture identifier, see \ref Environment::Arch. - uint8_t _arch; - //! Register assignment strategy, see \ref Strategy. - uint8_t _strategy; + //! \name Constants + //! \{ + + enum : uint32_t { + //! Maximum number of register arguments per register group. + //! + //! \note This is not really AsmJit's limitatation, it's just the number that makes sense considering all common + //! calling conventions. Usually even conventions that use registers to pass function arguments are limited to 8 + //! and less arguments passed via registers per group. + kMaxRegArgsPerGroup = 16 + }; + + //! \} + + //! \name Members + //! \{ + + //! Target architecture. + Arch _arch; + //! Calling convention id. + CallConvId _id; + //! Register assignment strategy. + CallConvStrategy _strategy; //! Red zone size (AMD64 == 128 bytes). uint8_t _redZoneSize; @@ -60,29 +191,18 @@ struct CallConv { //! Natural stack alignment as defined by OS/ABI. uint8_t _naturalStackAlignment; - //! Flags. - uint16_t _flags; + //! Calling convention flags. + CallConvFlags _flags; //! Size to save/restore per register group. - uint8_t _saveRestoreRegSize[BaseReg::kGroupVirt]; + Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreRegSize; //! Alignment of save/restore groups. - uint8_t _saveRestoreAlignment[BaseReg::kGroupVirt]; + Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreAlignment; //! Mask of all passed registers, per group. - uint32_t _passedRegs[BaseReg::kGroupVirt]; + Support::Array<RegMask, Globals::kNumVirtGroups> _passedRegs; //! Mask of all preserved registers, per group. - uint32_t _preservedRegs[BaseReg::kGroupVirt]; - - //! Internal limits of AsmJit's CallConv. - enum Limits : uint32_t { - //! Maximum number of register arguments per register group. - //! - //! \note This is not really AsmJit's limitatation, it's just the number - //! that makes sense considering all common calling conventions. Usually - //! even conventions that use registers to pass function arguments are - //! limited to 8 and less arguments passed via registers per group. - kMaxRegArgsPerGroup = 16 - }; + Support::Array<RegMask, Globals::kNumVirtGroups> _preservedRegs; //! Passed registers' order. union RegOrder { @@ -93,177 +213,26 @@ struct CallConv { }; //! Passed registers' order, per register group. - RegOrder _passedOrder[BaseReg::kGroupVirt]; - - //! Calling convention id. - //! - //! Calling conventions can be divided into the following groups: - //! - //! - Universal - calling conventions are applicable to any target. They - //! will be converted to a target dependent calling convention at runtime - //! by \ref init(). The purpose of these conventions is to make using - //! functions less target dependent and closer to how they are declared - //! in C and C++. - //! - //! - Target specific - calling conventions that are used by a particular - //! architecture and ABI. For example Windows 64-bit calling convention - //! and AMD64 SystemV calling convention. - enum Id : uint32_t { - //! None or invalid (can't be used). - kIdNone = 0, - - // ------------------------------------------------------------------------ - // [Universal Calling Conventions] - // ------------------------------------------------------------------------ - - //! Standard function call or explicit `__cdecl` where it can be specified. - //! - //! This is a universal calling convention, which is used to initialize - //! specific calling connventions based on architecture, platform, and its ABI. - kIdCDecl = 1, - - //! `__stdcall` on targets that support this calling convention (X86). - //! - //! \note This calling convention is only supported on 32-bit X86. If used - //! on environment that doesn't support this calling convention it will be - //! replaced by \ref kIdCDecl. - kIdStdCall = 2, - - //! `__fastcall` on targets that support this calling convention (X86). - //! - //! \note This calling convention is only supported on 32-bit X86. If used - //! on environment that doesn't support this calling convention it will be - //! replaced by \ref kIdCDecl. - kIdFastCall = 3, - - //! `__vectorcall` on targets that support this calling convention (X86/X64). - //! - //! \note This calling convention is only supported on 32-bit and 64-bit - //! X86 architecture on Windows platform. If used on environment that doesn't - //! support this calling it will be replaced by \ref kIdCDecl. - kIdVectorCall = 4, - - //! `__thiscall` on targets that support this calling convention (X86). - //! - //! \note This calling convention is only supported on 32-bit X86 Windows - //! platform. If used on environment that doesn't support this calling - //! convention it will be replaced by \ref kIdCDecl. - kIdThisCall = 5, - - //! `__attribute__((regparm(1)))` convention (GCC and Clang). - kIdRegParm1 = 6, - //! `__attribute__((regparm(2)))` convention (GCC and Clang). - kIdRegParm2 = 7, - //! `__attribute__((regparm(3)))` convention (GCC and Clang). - kIdRegParm3 = 8, - - //! Soft-float calling convention (ARM). - //! - //! Floating point arguments are passed via general purpose registers. - kIdSoftFloat = 9, - - //! Hard-float calling convention (ARM). - //! - //! Floating point arguments are passed via SIMD registers. - kIdHardFloat = 10, - - //! AsmJit specific calling convention designed for calling functions - //! inside a multimedia code that don't use many registers internally, - //! but are long enough to be called and not inlined. These functions are - //! usually used to calculate trigonometric functions, logarithms, etc... - kIdLightCall2 = 16, - kIdLightCall3 = 17, - kIdLightCall4 = 18, - - // ------------------------------------------------------------------------ - // [ABI-Specific Calling Conventions] - // ------------------------------------------------------------------------ - - //! X64 System-V calling convention. - kIdX64SystemV = 32, - //! X64 Windows calling convention. - kIdX64Windows = 33, - - // ------------------------------------------------------------------------ - // [Host] - // ------------------------------------------------------------------------ - - //! Host calling convention detected at compile-time. - kIdHost = -#if ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) - kIdSoftFloat -#elif ASMJIT_ARCH_ARM == 32 && !defined(__SOFTFP__) - kIdHardFloat -#else - kIdCDecl -#endif - -#ifndef ASMJIT_NO_DEPRECATE - , kIdHostCDecl = kIdCDecl - , kIdHostStdCall = kIdStdCall - , kIdHostFastCall = kIdFastCall - , kIdHostLightCall2 = kIdLightCall2 - , kIdHostLightCall3 = kIdLightCall3 - , kIdHostLightCall4 = kIdLightCall4 -#endif // !ASMJIT_NO_DEPRECATE - }; - - //! Strategy used to assign registers to function arguments. - //! - //! This is AsmJit specific. It basically describes how AsmJit should convert - //! the function arguments defined by `FuncSignature` into register IDs and - //! stack offsets. The default strategy `kStrategyDefault` assigns registers - //! and then stack whereas `kStrategyWin64` strategy does register shadowing - //! as defined by WIN64 calling convention - it applies to 64-bit calling - //! conventions only. - enum Strategy : uint32_t { - //! Default register assignment strategy. - kStrategyDefault = 0, - //! Windows 64-bit ABI register assignment strategy. - kStrategyX64Windows = 1, - //! Windows 64-bit __vectorcall register assignment strategy. - kStrategyX64VectorCall = 2, - - //! Number of assignment strategies. - kStrategyCount = 3 - }; + Support::Array<RegOrder, Globals::kNumVirtGroups> _passedOrder; - //! Calling convention flags. - enum Flags : uint32_t { - //! Callee is responsible for cleaning up the stack. - kFlagCalleePopsStack = 0x0001u, - //! Pass vector arguments indirectly (as a pointer). - kFlagIndirectVecArgs = 0x0002u, - //! Pass F32 and F64 arguments via VEC128 register. - kFlagPassFloatsByVec = 0x0004u, - //! Pass MMX and vector arguments via stack if the function has variable arguments. - kFlagPassVecByStackIfVA = 0x0008u, - //! MMX registers are passed and returned via GP registers. - kFlagPassMmxByGp = 0x0010u, - //! MMX registers are passed and returned via XMM registers. - kFlagPassMmxByXmm = 0x0020u, - //! Calling convention can be used with variable arguments. - kFlagVarArgCompatible = 0x0080u - }; + //! \} //! \name Construction & Destruction //! \{ - //! Initializes this calling convention to the given `ccId` based on the - //! `environment`. + //! Initializes this calling convention to the given `ccId` based on the `environment`. //! - //! See \ref Id and \ref Environment for more details. - ASMJIT_API Error init(uint32_t ccId, const Environment& environment) noexcept; + //! See \ref CallConvId and \ref Environment for more details. + ASMJIT_API Error init(CallConvId ccId, const Environment& environment) noexcept; //! Resets this CallConv struct into a defined state. //! - //! It's recommended to reset the \ref CallConv struct in case you would - //! like create a custom calling convention as it prevents from using an - //! uninitialized data (CallConv doesn't have a constructor that would - //! initialize it, it's just a struct). + //! It's recommended to reset the \ref CallConv struct in case you would like create a custom calling convention + //! as it prevents from using an uninitialized data (CallConv doesn't have a constructor that would initialize it, + //! it's just a struct). inline void reset() noexcept { memset(this, 0, sizeof(*this)); - memset(_passedOrder, 0xFF, sizeof(_passedOrder)); + memset(_passedOrder.data(), 0xFF, sizeof(_passedOrder)); } //! \} @@ -271,29 +240,29 @@ struct CallConv { //! \name Accessors //! \{ - //! Returns the calling convention id, see `Id`. - inline uint32_t id() const noexcept { return _id; } - //! Sets the calling convention id, see `Id`. - inline void setId(uint32_t id) noexcept { _id = uint8_t(id); } + //! Returns the target architecture of this calling convention. + inline Arch arch() const noexcept { return _arch; } + //! Sets the target architecture of this calling convention. + inline void setArch(Arch arch) noexcept { _arch = arch; } - //! Returns the calling function architecture id. - inline uint32_t arch() const noexcept { return _arch; } - //! Sets the calling function architecture id. - inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); } + //! Returns the calling convention id. + inline CallConvId id() const noexcept { return _id; } + //! Sets the calling convention id. + inline void setId(CallConvId ccId) noexcept { _id = ccId; } - //! Returns the strategy used to assign registers to arguments, see `Strategy`. - inline uint32_t strategy() const noexcept { return _strategy; } - //! Sets the strategy used to assign registers to arguments, see `Strategy`. - inline void setStrategy(uint32_t strategy) noexcept { _strategy = uint8_t(strategy); } + //! Returns the strategy used to assign registers to arguments. + inline CallConvStrategy strategy() const noexcept { return _strategy; } + //! Sets the strategy used to assign registers to arguments. + inline void setStrategy(CallConvStrategy ccStrategy) noexcept { _strategy = ccStrategy; } //! Tests whether the calling convention has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (uint32_t(_flags) & flag) != 0; } + inline bool hasFlag(CallConvFlags flag) const noexcept { return Support::test(_flags, flag); } //! Returns the calling convention flags, see `Flags`. - inline uint32_t flags() const noexcept { return _flags; } + inline CallConvFlags flags() const noexcept { return _flags; } //! Adds the calling convention flags, see `Flags`. - inline void setFlags(uint32_t flag) noexcept { _flags = uint16_t(flag); }; + inline void setFlags(CallConvFlags flag) noexcept { _flags = flag; }; //! Adds the calling convention flags, see `Flags`. - inline void addFlags(uint32_t flags) noexcept { _flags = uint16_t(_flags | flags); }; + inline void addFlags(CallConvFlags flags) noexcept { _flags |= flags; }; //! Tests whether this calling convention specifies 'RedZone'. inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } @@ -314,35 +283,34 @@ struct CallConv { inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } //! Sets a natural stack alignment. //! - //! This function can be used to override the default stack alignment in case - //! that you know that it's alignment is different. For example it allows to - //! implement custom calling conventions that guarantee higher stack alignment. + //! This function can be used to override the default stack alignment in case that you know that it's alignment is + //! different. For example it allows to implement custom calling conventions that guarantee higher stack alignment. inline void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); } //! Returns the size of a register (or its part) to be saved and restored of the given `group`. - inline uint32_t saveRestoreRegSize(uint32_t group) const noexcept { return _saveRestoreRegSize[group]; } + inline uint32_t saveRestoreRegSize(RegGroup group) const noexcept { return _saveRestoreRegSize[group]; } //! Sets the size of a vector register (or its part) to be saved and restored. - inline void setSaveRestoreRegSize(uint32_t group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); } + inline void setSaveRestoreRegSize(RegGroup group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); } //! Returns the alignment of a save-restore area of the given `group`. - inline uint32_t saveRestoreAlignment(uint32_t group) const noexcept { return _saveRestoreAlignment[group]; } + inline uint32_t saveRestoreAlignment(RegGroup group) const noexcept { return _saveRestoreAlignment[group]; } //! Sets the alignment of a save-restore area of the given `group`. - inline void setSaveRestoreAlignment(uint32_t group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); } + inline void setSaveRestoreAlignment(RegGroup group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); } - //! Returns the order of passed registers of the given `group`, see \ref BaseReg::RegGroup. - inline const uint8_t* passedOrder(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _passedOrder[group].id; + //! Returns the order of passed registers of the given `group`. + inline const uint8_t* passedOrder(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + return _passedOrder[size_t(group)].id; } - //! Returns the mask of passed registers of the given `group`, see \ref BaseReg::RegGroup. - inline uint32_t passedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _passedRegs[group]; + //! Returns the mask of passed registers of the given `group`. + inline RegMask passedRegs(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + return _passedRegs[size_t(group)]; } - inline void _setPassedPacked(uint32_t group, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline void _setPassedPacked(RegGroup group, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _passedOrder[group].packed[0] = p0; _passedOrder[group].packed[1] = p1; @@ -351,19 +319,19 @@ struct CallConv { } //! Resets the order and mask of passed registers. - inline void setPassedToNone(uint32_t group) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline void setPassedToNone(RegGroup group) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _setPassedPacked(group, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); - _passedRegs[group] = 0u; + _passedRegs[size_t(group)] = 0u; } //! Sets the order and mask of passed registers. - inline void setPassedOrder(uint32_t group, uint32_t a0, uint32_t a1 = 0xFF, uint32_t a2 = 0xFF, uint32_t a3 = 0xFF, uint32_t a4 = 0xFF, uint32_t a5 = 0xFF, uint32_t a6 = 0xFF, uint32_t a7 = 0xFF) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline void setPassedOrder(RegGroup group, uint32_t a0, uint32_t a1 = 0xFF, uint32_t a2 = 0xFF, uint32_t a3 = 0xFF, uint32_t a4 = 0xFF, uint32_t a5 = 0xFF, uint32_t a6 = 0xFF, uint32_t a7 = 0xFF) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); - // NOTE: This should always be called with all arguments known at compile time, - // so even if it looks scary it should be translated into few instructions. + // NOTE: This should always be called with all arguments known at compile time, so even if it looks scary it + // should be translated into few instructions. _setPassedPacked(group, Support::bytepack32_4x8(a0, a1, a2, a3), Support::bytepack32_4x8(a4, a5, a6, a7), 0xFFFFFFFFu, @@ -379,59 +347,63 @@ struct CallConv { (a7 != 0xFF ? 1u << a7 : 0u) ; } - //! Returns preserved register mask of the given `group`, see \ref BaseReg::RegGroup. - inline uint32_t preservedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + //! Returns preserved register mask of the given `group`. + inline RegMask preservedRegs(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _preservedRegs[group]; } - //! Sets preserved register mask of the given `group`, see \ref BaseReg::RegGroup. - inline void setPreservedRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + //! Sets preserved register mask of the given `group`. + inline void setPreservedRegs(RegGroup group, RegMask regs) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _preservedRegs[group] = regs; } //! \} }; -// ============================================================================ -// [asmjit::FuncSignature] -// ============================================================================ - //! Function signature. //! -//! Contains information about function return type, count of arguments and -//! their TypeIds. Function signature is a low level structure which doesn't -//! contain platform specific or calling convention specific information. +//! Contains information about function return type, count of arguments and their TypeIds. Function signature is +//! a low level structure which doesn't contain platform specific or calling convention specific information. struct FuncSignature { + //! \name Constants + //! \{ + + enum : uint8_t { + //! Doesn't have variable number of arguments (`...`). + kNoVarArgs = 0xFFu + }; + + //! \} + + //! \name Members + //! \{ + //! Calling convention id. - uint8_t _callConv; + CallConvId _ccId; //! Count of arguments. uint8_t _argCount; //! Index of a first VA or `kNoVarArgs`. uint8_t _vaIndex; //! Return value TypeId. - uint8_t _ret; + TypeId _ret; //! Function arguments TypeIds. - const uint8_t* _args; + const TypeId* _args; - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFF - }; + //! \} //! \name Initializtion & Reset //! \{ //! Initializes the function signature. - inline void init(uint32_t ccId, uint32_t vaIndex, uint32_t ret, const uint8_t* args, uint32_t argCount) noexcept { - ASMJIT_ASSERT(ccId <= 0xFF); + inline void init(CallConvId ccId, uint32_t vaIndex, TypeId ret, const TypeId* args, uint32_t argCount) noexcept { ASMJIT_ASSERT(argCount <= 0xFF); - _callConv = uint8_t(ccId); + _ccId = ccId; _argCount = uint8_t(argCount); _vaIndex = uint8_t(vaIndex); - _ret = uint8_t(ret); + _ret = ret; _args = args; } @@ -443,9 +415,9 @@ struct FuncSignature { //! \{ //! Returns the calling convention. - inline uint32_t callConv() const noexcept { return _callConv; } + inline CallConvId callConvId() const noexcept { return _ccId; } //! Sets the calling convention to `ccId`; - inline void setCallConv(uint32_t ccId) noexcept { _callConv = uint8_t(ccId); } + inline void setCallConvId(CallConvId ccId) noexcept { _ccId = ccId; } //! Tests whether the function has variable number of arguments (...). inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } @@ -459,48 +431,40 @@ struct FuncSignature { //! Returns the number of function arguments. inline uint32_t argCount() const noexcept { return _argCount; } - inline bool hasRet() const noexcept { return _ret != Type::kIdVoid; } + inline bool hasRet() const noexcept { return _ret != TypeId::kVoid; } //! Returns the return value type. - inline uint32_t ret() const noexcept { return _ret; } + inline TypeId ret() const noexcept { return _ret; } //! Returns the type of the argument at index `i`. - inline uint32_t arg(uint32_t i) const noexcept { + inline TypeId arg(uint32_t i) const noexcept { ASMJIT_ASSERT(i < _argCount); return _args[i]; } //! Returns the array of function arguments' types. - inline const uint8_t* args() const noexcept { return _args; } + inline const TypeId* args() const noexcept { return _args; } //! \} }; -// ============================================================================ -// [asmjit::FuncSignatureT] -// ============================================================================ - template<typename... RET_ARGS> class FuncSignatureT : public FuncSignature { public: - inline FuncSignatureT(uint32_t ccId = CallConv::kIdHost, uint32_t vaIndex = kNoVarArgs) noexcept { - static const uint8_t ret_args[] = { (uint8_t(Type::IdOfT<RET_ARGS>::kTypeId))... }; + inline FuncSignatureT(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept { + static constexpr TypeId ret_args[] = { (TypeId(TypeUtils::TypeIdOfT<RET_ARGS>::kTypeId))... }; init(ccId, vaIndex, ret_args[0], ret_args + 1, uint32_t(ASMJIT_ARRAY_SIZE(ret_args) - 1)); } }; -// ============================================================================ -// [asmjit::FuncSignatureBuilder] -// ============================================================================ - //! Function signature builder. class FuncSignatureBuilder : public FuncSignature { public: - uint8_t _builderArgList[Globals::kMaxFuncArgs]; + TypeId _builderArgList[Globals::kMaxFuncArgs]; //! \name Initializtion & Reset //! \{ - inline FuncSignatureBuilder(uint32_t ccId = CallConv::kIdHost, uint32_t vaIndex = kNoVarArgs) noexcept { - init(ccId, vaIndex, Type::kIdVoid, _builderArgList, 0); + inline FuncSignatureBuilder(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept { + init(ccId, vaIndex, TypeId::kVoid, _builderArgList, 0); } //! \} @@ -509,42 +473,39 @@ public: //! \{ //! Sets the return type to `retType`. - inline void setRet(uint32_t retType) noexcept { _ret = uint8_t(retType); } + inline void setRet(TypeId retType) noexcept { _ret = retType; } //! Sets the return type based on `T`. template<typename T> - inline void setRetT() noexcept { setRet(Type::IdOfT<T>::kTypeId); } + inline void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } //! Sets the argument at index `index` to `argType`. - inline void setArg(uint32_t index, uint32_t argType) noexcept { + inline void setArg(uint32_t index, TypeId argType) noexcept { ASMJIT_ASSERT(index < _argCount); - _builderArgList[index] = uint8_t(argType); + _builderArgList[index] = argType; } //! Sets the argument at index `i` to the type based on `T`. template<typename T> - inline void setArgT(uint32_t index) noexcept { setArg(index, Type::IdOfT<T>::kTypeId); } + inline void setArgT(uint32_t index) noexcept { setArg(index, TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } //! Appends an argument of `type` to the function prototype. - inline void addArg(uint32_t type) noexcept { + inline void addArg(TypeId type) noexcept { ASMJIT_ASSERT(_argCount < Globals::kMaxFuncArgs); - _builderArgList[_argCount++] = uint8_t(type); + _builderArgList[_argCount++] = type; } //! Appends an argument of type based on `T` to the function prototype. template<typename T> - inline void addArgT() noexcept { addArg(Type::IdOfT<T>::kTypeId); } + inline void addArgT() noexcept { addArg(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); } //! \} }; -// ============================================================================ -// [asmjit::FuncValue] -// ============================================================================ - -//! Argument or return value (or its part) as defined by `FuncSignature`, but -//! with register or stack address (and other metadata) assigned. +//! Argument or return value (or its part) as defined by `FuncSignature`, but with register or stack address +//! (and other metadata) assigned. struct FuncValue { - uint32_t _data; + //! \name Constants + //! \{ - enum Parts : uint32_t { + enum Bits : uint32_t { kTypeIdShift = 0, //!< TypeId shift. kTypeIdMask = 0x000000FFu, //!< TypeId mask. @@ -563,23 +524,33 @@ struct FuncValue { kRegTypeMask = 0xFF000000u //!< RegType mask. }; - //! \name Initializtion & Reset + //! \} + + //! \name Members //! \{ - // These initialize the whole `FuncValue` to either register or stack. Useful - // when you know all of these properties and wanna just set it up. + uint32_t _data; + + //! \} + + //! \name Initializtion & Reset + //! + //! These initialize the whole `FuncValue` to either register or stack. Useful when you know all of these + //! properties and wanna just set it up. + //! + //! \{ //! Initializes the `typeId` of this `FuncValue`. - inline void initTypeId(uint32_t typeId) noexcept { - _data = typeId << kTypeIdShift; + inline void initTypeId(TypeId typeId) noexcept { + _data = uint32_t(typeId) << kTypeIdShift; } - inline void initReg(uint32_t regType, uint32_t regId, uint32_t typeId, uint32_t flags = 0) noexcept { - _data = (regType << kRegTypeShift) | (regId << kRegIdShift) | (typeId << kTypeIdShift) | kFlagIsReg | flags; + inline void initReg(RegType regType, uint32_t regId, TypeId typeId, uint32_t flags = 0) noexcept { + _data = (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsReg | flags; } - inline void initStack(int32_t offset, uint32_t typeId) noexcept { - _data = (uint32_t(offset) << kStackOffsetShift) | (typeId << kTypeIdShift) | kFlagIsStack; + inline void initStack(int32_t offset, TypeId typeId) noexcept { + _data = (uint32_t(offset) << kStackOffsetShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsStack; } //! Resets the value to its unassigned state. @@ -588,15 +559,15 @@ struct FuncValue { //! \} //! \name Assign + //! + //! These initialize only part of `FuncValue`, useful when building `FuncValue` incrementally. The caller + //! should first init the type-id by caliing `initTypeId` and then continue building either register or stack. + //! //! \{ - // These initialize only part of `FuncValue`, useful when building `FuncValue` - // incrementally. The caller should first init the type-id by caliing `initTypeId` - // and then continue building either register or stack. - - inline void assignRegData(uint32_t regType, uint32_t regId) noexcept { + inline void assignRegData(RegType regType, uint32_t regId) noexcept { ASMJIT_ASSERT((_data & (kRegTypeMask | kRegIdMask)) == 0); - _data |= (regType << kRegTypeShift) | (regId << kRegIdShift) | kFlagIsReg; + _data |= (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | kFlagIsReg; } inline void assignStackOffset(int32_t offset) noexcept { @@ -609,12 +580,13 @@ struct FuncValue { //! \name Accessors //! \{ + //! Returns true if the value is initialized (explicit bool cast). inline explicit operator bool() const noexcept { return _data != 0; } inline void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; } //! Tests whether the `FuncValue` has a flag `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (_data & flag) != 0; } + inline bool hasFlag(uint32_t flag) const noexcept { return Support::test(_data, flag); } //! Adds `flags` to `FuncValue`. inline void addFlags(uint32_t flags) noexcept { _data |= flags; } //! Clears `flags` of `FuncValue`. @@ -635,9 +607,9 @@ struct FuncValue { inline bool isDone() const noexcept { return hasFlag(kFlagIsDone); } //! Returns a register type of the register used to pass function argument or return value. - inline uint32_t regType() const noexcept { return (_data & kRegTypeMask) >> kRegTypeShift; } + inline RegType regType() const noexcept { return RegType((_data & kRegTypeMask) >> kRegTypeShift); } //! Sets a register type of the register used to pass function argument or return value. - inline void setRegType(uint32_t regType) noexcept { _replaceValue(kRegTypeMask, regType << kRegTypeShift); } + inline void setRegType(RegType regType) noexcept { _replaceValue(kRegTypeMask, uint32_t(regType) << kRegTypeShift); } //! Returns a physical id of the register used to pass function argument or return value. inline uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; } @@ -649,35 +621,43 @@ struct FuncValue { //! Sets a stack offset of this argument. inline void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); } - //! Tests whether the argument or return value has associated `Type::Id`. - inline bool hasTypeId() const noexcept { return (_data & kTypeIdMask) != 0; } + //! Tests whether the argument or return value has associated `TypeId`. + inline bool hasTypeId() const noexcept { return Support::test(_data, kTypeIdMask); } //! Returns a TypeId of this argument or return value. - inline uint32_t typeId() const noexcept { return (_data & kTypeIdMask) >> kTypeIdShift; } + inline TypeId typeId() const noexcept { return TypeId((_data & kTypeIdMask) >> kTypeIdShift); } //! Sets a TypeId of this argument or return value. - inline void setTypeId(uint32_t typeId) noexcept { _replaceValue(kTypeIdMask, typeId << kTypeIdShift); } + inline void setTypeId(TypeId typeId) noexcept { _replaceValue(kTypeIdMask, uint32_t(typeId) << kTypeIdShift); } //! \} }; -// ============================================================================ -// [asmjit::FuncValuePack] -// ============================================================================ - -//! Contains multiple `FuncValue` instances in an array so functions that use -//! multiple registers for arguments or return values can represent all inputs -//! and outputs. +//! Contains multiple `FuncValue` instances in an array so functions that use multiple registers for arguments or +//! return values can represent all inputs and outputs. struct FuncValuePack { public: - //! Values data. + //! \name Members + //! \{ + + //! Values of the pack. FuncValue _values[Globals::kMaxValuePack]; + //! \} + + //! \name Initialization & Reset + //! \{ + + //! Resets all values in the pack. inline void reset() noexcept { for (size_t i = 0; i < Globals::kMaxValuePack; i++) _values[i].reset(); } - //! Calculates how many values are in the pack, checking for non-values - //! from the end. + //! \} + + //! \name Accessors + //! \{ + + //! Calculates how many values are in the pack, checking for non-values from the end. inline uint32_t count() const noexcept { uint32_t n = Globals::kMaxValuePack; while (n && !_values[n - 1]) @@ -698,18 +678,18 @@ public: return _values[index].isInitialized(); } - inline void assignReg(size_t index, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignReg(size_t index, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); ASMJIT_ASSERT(reg.isPhysReg()); _values[index].initReg(reg.type(), reg.id(), typeId); } - inline void assignReg(size_t index, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignReg(size_t index, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].initReg(regType, regId, typeId); } - inline void assignStack(size_t index, int32_t offset, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignStack(size_t index, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(index < Globals::kMaxValuePack); _values[index].initStack(offset, typeId); } @@ -723,19 +703,70 @@ public: ASMJIT_ASSERT(index < Globals::kMaxValuePack); return _values[index]; } + + //! \} }; -// ============================================================================ -// [asmjit::FuncDetail] -// ============================================================================ +//! Attributes are designed in a way that all are initially false, and user or \ref FuncFrame finalizer adds +//! them when necessary. +enum class FuncAttributes : uint32_t { + //! No attributes. + kNoAttributes = 0, + + //! Function has variable number of arguments. + kHasVarArgs = 0x00000001u, + //! Preserve frame pointer (don't omit FP). + kHasPreservedFP = 0x00000010u, + //! Function calls other functions (is not leaf). + kHasFuncCalls = 0x00000020u, + //! Function has aligned save/restore of vector registers. + kAlignedVecSR = 0x00000040u, + //! FuncFrame is finalized and can be used by prolog/epilog inserter (PEI). + kIsFinalized = 0x00000800u, + + // X86 Specific Attributes + // ----------------------- + + //! Enables the use of AVX within the function's body, prolog, and epilog (X86). + //! + //! This flag instructs prolog and epilog emitter to use AVX instead of SSE for manipulating XMM registers. + kX86_AVXEnabled = 0x00010000u, + + //! Enables the use of AVX-512 within the function's body, prolog, and epilog (X86). + //! + //! This flag instructs Compiler register allocator to use additional 16 registers introduced by AVX-512. + //! Additionally, if the functions saves full width of ZMM registers (custom calling conventions only) then + //! the prolog/epilog inserter would use AVX-512 move instructions to emit the save and restore sequence. + kX86_AVX512Enabled = 0x00020000u, + + //! This flag instructs the epilog writer to emit EMMS instruction before RET (X86). + kX86_MMXCleanup = 0x00040000u, + + //! This flag instructs the epilog writer to emit VZEROUPPER instruction before RET (X86). + kX86_AVXCleanup = 0x00080000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(FuncAttributes) -//! Function detail - CallConv and expanded FuncSignature. +//! Function detail - \ref CallConv and expanded \ref FuncSignature. //! -//! Function detail is architecture and OS dependent representation of a function. -//! It contains calling convention and expanded function signature so all -//! arguments have assigned either register type & id or stack address. +//! Function detail is architecture and OS dependent representation of a function. It contains a materialized +//! calling convention and expanded function signature so all arguments have assigned either register type/id +//! or stack address. class FuncDetail { public: + //! \name Constants + //! \{ + + enum : uint8_t { + //! Doesn't have variable number of arguments (`...`). + kNoVarArgs = 0xFFu + }; + + //! \} + + //! \name Members + //! \{ + //! Calling convention. CallConv _callConv; //! Number of function arguments. @@ -744,8 +775,8 @@ public: uint8_t _vaIndex; //! Reserved for future use. uint16_t _reserved; - //! Registers that contains arguments. - uint32_t _usedRegs[BaseReg::kGroupVirt]; + //! Registers that contain arguments. + Support::Array<RegMask, Globals::kNumVirtGroups> _usedRegs; //! Size of arguments passed by stack. uint32_t _argStackSize; //! Function return value(s). @@ -753,10 +784,7 @@ public: //! Function arguments. FuncValuePack _args[Globals::kMaxFuncArgs]; - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFF - }; + //! \} //! \name Construction & Destruction //! \{ @@ -777,9 +805,9 @@ public: inline const CallConv& callConv() const noexcept { return _callConv; } //! Returns the associated calling convention flags, see `CallConv::Flags`. - inline uint32_t flags() const noexcept { return _callConv.flags(); } + inline CallConvFlags flags() const noexcept { return _callConv.flags(); } //! Checks whether a CallConv `flag` is set, see `CallConv::Flags`. - inline bool hasFlag(uint32_t ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); } + inline bool hasFlag(CallConvFlags ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); } //! Tests whether the function has a return value. inline bool hasRet() const noexcept { return bool(_rets[0]); } @@ -851,50 +879,47 @@ public: inline uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); } //! Returns a mask of all passed registers of the given register `group`. - inline uint32_t passedRegs(uint32_t group) const noexcept { return _callConv.passedRegs(group); } + inline RegMask passedRegs(RegGroup group) const noexcept { return _callConv.passedRegs(group); } //! Returns a mask of all preserved registers of the given register `group`. - inline uint32_t preservedRegs(uint32_t group) const noexcept { return _callConv.preservedRegs(group); } + inline RegMask preservedRegs(RegGroup group) const noexcept { return _callConv.preservedRegs(group); } //! Returns a mask of all used registers of the given register `group`. - inline uint32_t usedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _usedRegs[group]; + inline RegMask usedRegs(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + return _usedRegs[size_t(group)]; } //! Adds `regs` to the mask of used registers of the given register `group`. - inline void addUsedRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _usedRegs[group] |= regs; + inline void addUsedRegs(RegGroup group, RegMask regs) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + _usedRegs[size_t(group)] |= regs; } //! \} }; -// ============================================================================ -// [asmjit::FuncFrame] -// ============================================================================ - //! Function frame. //! -//! Function frame is used directly by prolog and epilog insertion (PEI) utils. -//! It provides information necessary to insert a proper and ABI comforming -//! prolog and epilog. Function frame calculation is based on `CallConv` and +//! Function frame is used directly by prolog and epilog insertion (PEI) utils. It provides information necessary to +//! insert a proper and ABI comforming prolog and epilog. Function frame calculation is based on `CallConv` and //! other function attributes. //! //! SSE vs AVX vs AVX-512 //! --------------------- //! -//! Function frame provides a way to tell prolog/epilog inserter to use AVX -//! instructions instead of SSE. Use `setAvxEnabled()` and `setAvx512Enabled()` -//! to enable AVX and/or AVX-512, respectively. Enabling AVX-512 is mostly for -//! Compiler as it would use 32 SIMD registers instead of 16 when enabled. +//! Function frame provides a way to tell prolog/epilog inserter to use AVX instructions instead of SSE. Use +//! `setAvxEnabled()` and `setAvx512Enabled()` to enable AVX and/or AVX-512, respectively. Enabling AVX-512 +//! is mostly for Compiler as it would use 32 SIMD registers instead of 16 when enabled. +//! +//! \note If your code uses AVX instructions and AVX is not enabled there would be a performance hit in case that +//! some registers had to be saved/restored in function's prolog/epilog, respectively. Thus, it's recommended to +//! always let the function frame know about the use of AVX. //! //! Function Frame Structure //! ------------------------ //! -//! Various properties can contribute to the size and structure of the function -//! frame. The function frame in most cases won't use all of the properties -//! illustrated (for example Spill Zone and Red Zone are never used together). +//! Various properties can contribute to the size and structure of the function frame. The function frame in most +//! cases won't use all of the properties illustrated (for example Spill Zone and Red Zone are never used together). //! //! ``` //! +-----------------------------+ @@ -915,49 +940,24 @@ public: //! ``` class FuncFrame { public: - enum Tag : uint32_t { + //! \name Constants + //! \{ + + enum : uint32_t { //! Tag used to inform that some offset is invalid. kTagInvalidOffset = 0xFFFFFFFFu }; - //! Attributes are designed in a way that all are initially false, and user - //! or FuncFrame finalizer adds them when necessary. - enum Attributes : uint32_t { - //! Function has variable number of arguments. - kAttrHasVarArgs = 0x00000001u, - //! Preserve frame pointer (don't omit FP). - kAttrHasPreservedFP = 0x00000010u, - //! Function calls other functions (is not leaf). - kAttrHasFuncCalls = 0x00000020u, - - //! Function uses AVX (X86). - //! - //! This flag instructs prolog and epilog emitter to use AVX instead of SSE for manipulating - //! XMM registers. - kAttrX86AvxEnabled = 0x00010000u, - //! Function uses AVX-512 (X86). - //! - //! This flag instructs Compiler register allocator to use additional 16 registers introduced - //! by AVX-512. - kAttrX86Avx512Enabled = 0x00020000u, - - //! This flag instructs epilog writer to emit EMMS instruction before RET (X86). - kAttrX86MmxCleanup = 0x00040000u, - - //! This flag instructs epilog writer to emit VZEROUPPER instruction before RET (X86). - kAttrX86AvxCleanup = 0x00080000u, + //! \} - //! Function has aligned save/restore of vector registers. - kAttrAlignedVecSR = 0x40000000u, - //! FuncFrame is finalized and can be used by PEI. - kAttrIsFinalized = 0x80000000u - }; + //! \name Members + //! \{ //! Function attributes. - uint32_t _attributes; + FuncAttributes _attributes; - //! Architecture, see \ref Environment::Arch. - uint8_t _arch; + //! Target architecture. + Arch _arch; //! SP register ID (to access call stack and local stack). uint8_t _spRegId; //! SA register ID (to access stack arguments). @@ -1002,13 +1002,13 @@ public: uint32_t _stackAdjustment; //! Registers that are dirty. - uint32_t _dirtyRegs[BaseReg::kGroupVirt]; + Support::Array<RegMask, Globals::kNumVirtGroups> _dirtyRegs; //! Registers that must be preserved (copied from CallConv). - uint32_t _preservedRegs[BaseReg::kGroupVirt]; + Support::Array<RegMask, Globals::kNumVirtGroups> _preservedRegs; //! Size to save/restore per register group. - uint8_t _saveRestoreRegSize[BaseReg::kGroupVirt]; + Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreRegSize; //! Alignment of save/restore area per register group. - uint8_t _saveRestoreAlignment[BaseReg::kGroupVirt]; + Support::Array<uint8_t, Globals::kNumVirtGroups> _saveRestoreAlignment; //! Stack size required to save registers with push/pop. uint16_t _pushPopSaveSize; @@ -1019,6 +1019,8 @@ public: //! Offset where extra ragisters that cannot use push/pop are stored. uint32_t _extraRegSaveOffset; + //! \} + //! \name Construction & Destruction //! \{ @@ -1040,72 +1042,72 @@ public: //! \{ //! Returns the target architecture of the function frame. - inline uint32_t arch() const noexcept { return _arch; } + inline Arch arch() const noexcept { return _arch; } //! Returns function frame attributes, see `Attributes`. - inline uint32_t attributes() const noexcept { return _attributes; } + inline FuncAttributes attributes() const noexcept { return _attributes; } //! Checks whether the FuncFame contains an attribute `attr`. - inline bool hasAttribute(uint32_t attr) const noexcept { return (_attributes & attr) != 0; } + inline bool hasAttribute(FuncAttributes attr) const noexcept { return Support::test(_attributes, attr); } //! Adds attributes `attrs` to the FuncFrame. - inline void addAttributes(uint32_t attrs) noexcept { _attributes |= attrs; } + inline void addAttributes(FuncAttributes attrs) noexcept { _attributes |= attrs; } //! Clears attributes `attrs` from the FrameFrame. - inline void clearAttributes(uint32_t attrs) noexcept { _attributes &= ~attrs; } + inline void clearAttributes(FuncAttributes attrs) noexcept { _attributes &= ~attrs; } //! Tests whether the function has variable number of arguments. - inline bool hasVarArgs() const noexcept { return hasAttribute(kAttrHasVarArgs); } + inline bool hasVarArgs() const noexcept { return hasAttribute(FuncAttributes::kHasVarArgs); } //! Sets the variable arguments flag. - inline void setVarArgs() noexcept { addAttributes(kAttrHasVarArgs); } + inline void setVarArgs() noexcept { addAttributes(FuncAttributes::kHasVarArgs); } //! Resets variable arguments flag. - inline void resetVarArgs() noexcept { clearAttributes(kAttrHasVarArgs); } + inline void resetVarArgs() noexcept { clearAttributes(FuncAttributes::kHasVarArgs); } //! Tests whether the function preserves frame pointer (EBP|ESP on X86). - inline bool hasPreservedFP() const noexcept { return hasAttribute(kAttrHasPreservedFP); } + inline bool hasPreservedFP() const noexcept { return hasAttribute(FuncAttributes::kHasPreservedFP); } //! Enables preserved frame pointer. - inline void setPreservedFP() noexcept { addAttributes(kAttrHasPreservedFP); } + inline void setPreservedFP() noexcept { addAttributes(FuncAttributes::kHasPreservedFP); } //! Disables preserved frame pointer. - inline void resetPreservedFP() noexcept { clearAttributes(kAttrHasPreservedFP); } + inline void resetPreservedFP() noexcept { clearAttributes(FuncAttributes::kHasPreservedFP); } //! Tests whether the function calls other functions. - inline bool hasFuncCalls() const noexcept { return hasAttribute(kAttrHasFuncCalls); } + inline bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); } //! Sets `kFlagHasCalls` to true. - inline void setFuncCalls() noexcept { addAttributes(kAttrHasFuncCalls); } + inline void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); } //! Sets `kFlagHasCalls` to false. - inline void resetFuncCalls() noexcept { clearAttributes(kAttrHasFuncCalls); } + inline void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); } //! Tests whether the function has AVX enabled. - inline bool isAvxEnabled() const noexcept { return hasAttribute(kAttrX86AvxEnabled); } + inline bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); } //! Enables AVX use. - inline void setAvxEnabled() noexcept { addAttributes(kAttrX86AvxEnabled); } + inline void setAvxEnabled() noexcept { addAttributes(FuncAttributes::kX86_AVXEnabled); } //! Disables AVX use. - inline void resetAvxEnabled() noexcept { clearAttributes(kAttrX86AvxEnabled); } + inline void resetAvxEnabled() noexcept { clearAttributes(FuncAttributes::kX86_AVXEnabled); } //! Tests whether the function has AVX-512 enabled. - inline bool isAvx512Enabled() const noexcept { return hasAttribute(kAttrX86Avx512Enabled); } + inline bool isAvx512Enabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVX512Enabled); } //! Enables AVX-512 use. - inline void setAvx512Enabled() noexcept { addAttributes(kAttrX86Avx512Enabled); } + inline void setAvx512Enabled() noexcept { addAttributes(FuncAttributes::kX86_AVX512Enabled); } //! Disables AVX-512 use. - inline void resetAvx512Enabled() noexcept { clearAttributes(kAttrX86Avx512Enabled); } + inline void resetAvx512Enabled() noexcept { clearAttributes(FuncAttributes::kX86_AVX512Enabled); } //! Tests whether the function has MMX cleanup - 'emms' instruction in epilog. - inline bool hasMmxCleanup() const noexcept { return hasAttribute(kAttrX86MmxCleanup); } + inline bool hasMmxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_MMXCleanup); } //! Enables MMX cleanup. - inline void setMmxCleanup() noexcept { addAttributes(kAttrX86MmxCleanup); } + inline void setMmxCleanup() noexcept { addAttributes(FuncAttributes::kX86_MMXCleanup); } //! Disables MMX cleanup. - inline void resetMmxCleanup() noexcept { clearAttributes(kAttrX86MmxCleanup); } + inline void resetMmxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_MMXCleanup); } //! Tests whether the function has AVX cleanup - 'vzeroupper' instruction in epilog. - inline bool hasAvxCleanup() const noexcept { return hasAttribute(kAttrX86AvxCleanup); } + inline bool hasAvxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXCleanup); } //! Enables AVX cleanup. - inline void setAvxCleanup() noexcept { addAttributes(kAttrX86AvxCleanup); } + inline void setAvxCleanup() noexcept { addAttributes(FuncAttributes::kX86_AVXCleanup); } //! Disables AVX cleanup. - inline void resetAvxCleanup() noexcept { clearAttributes(kAttrX86AvxCleanup); } + inline void resetAvxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_AVXCleanup); } //! Tests whether the function uses call stack. inline bool hasCallStack() const noexcept { return _callStackSize != 0; } //! Tests whether the function uses local stack. inline bool hasLocalStack() const noexcept { return _localStackSize != 0; } //! Tests whether vector registers can be saved and restored by using aligned reads and writes. - inline bool hasAlignedVecSR() const noexcept { return hasAttribute(kAttrAlignedVecSR); } + inline bool hasAlignedVecSR() const noexcept { return hasAttribute(FuncAttributes::kAlignedVecSR); } //! Tests whether the function has to align stack dynamically. inline bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; } @@ -1201,28 +1203,26 @@ public: inline uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; } inline uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; } - //! Returns mask of registers of the given register `group` that are modified - //! by the function. The engine would then calculate which registers must be - //! saved & restored by the function by using the data provided by the calling - //! convention. - inline uint32_t dirtyRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + //! Returns mask of registers of the given register `group` that are modified by the function. The engine would + //! then calculate which registers must be saved & restored by the function by using the data provided by the + //! calling convention. + inline RegMask dirtyRegs(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _dirtyRegs[group]; } //! Sets which registers (as a mask) are modified by the function. //! - //! \remarks Please note that this will completely overwrite the existing - //! register mask, use `addDirtyRegs()` to modify the existing register - //! mask. - inline void setDirtyRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + //! \remarks Please note that this will completely overwrite the existing register mask, use `addDirtyRegs()` + //! to modify the existing register mask. + inline void setDirtyRegs(RegGroup group, RegMask regs) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _dirtyRegs[group] = regs; } //! Adds which registers (as a mask) are modified by the function. - inline void addDirtyRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline void addDirtyRegs(RegGroup group, RegMask regs) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _dirtyRegs[group] |= regs; } @@ -1234,7 +1234,7 @@ public: //! \overload template<typename... Args> - ASMJIT_INLINE void addDirtyRegs(const BaseReg& reg, Args&&... args) noexcept { + inline void addDirtyRegs(const BaseReg& reg, Args&&... args) noexcept { addDirtyRegs(reg); addDirtyRegs(std::forward<Args>(args)...); } @@ -1244,37 +1244,35 @@ public: _dirtyRegs[i] = 0xFFFFFFFFu; } - inline void setAllDirty(uint32_t group) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline void setAllDirty(RegGroup group) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); _dirtyRegs[group] = 0xFFFFFFFFu; } - //! Returns a calculated mask of registers of the given `group` that will be - //! saved and restored in the function's prolog and epilog, respectively. The - //! register mask is calculated from both `dirtyRegs` (provided by user) and + //! Returns a calculated mask of registers of the given `group` that will be saved and restored in the function's + //! prolog and epilog, respectively. The register mask is calculated from both `dirtyRegs` (provided by user) and //! `preservedMask` (provided by the calling convention). - inline uint32_t savedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline RegMask savedRegs(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _dirtyRegs[group] & _preservedRegs[group]; } //! Returns the mask of preserved registers of the given register `group`. //! - //! Preserved registers are those that must survive the function call - //! unmodified. The function can only modify preserved registers it they - //! are saved and restored in funciton's prolog and epilog, respectively. - inline uint32_t preservedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + //! Preserved registers are those that must survive the function call unmodified. The function can only modify + //! preserved registers it they are saved and restored in funciton's prolog and epilog, respectively. + inline RegMask preservedRegs(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _preservedRegs[group]; } - inline uint32_t saveRestoreRegSize(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline uint32_t saveRestoreRegSize(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _saveRestoreRegSize[group]; } - inline uint32_t saveRestoreAlignment(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline uint32_t saveRestoreAlignment(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); return _saveRestoreAlignment[group]; } @@ -1288,12 +1286,10 @@ public: //! Returns an offset to the stack where registers are saved via push/pop. inline uint32_t pushPopSaveOffset() const noexcept { return _pushPopSaveOffset; } - //! Returns stack size required to save/restore extra registers that don't - //! use push/pop/ + //! Returns stack size required to save/restore extra registers that don't use push/pop/ //! - //! \note On X86 this covers all registers except GP registers, on other - //! architectures it can be always zero (for example AArch64 saves all - //! registers via push/pop like instructions, so this would be zero). + //! \note On X86 this covers all registers except GP registers, on other architectures it can be always + //! zero (for example AArch64 saves all registers via push/pop like instructions, so this would be zero). inline uint32_t extraRegSaveSize() const noexcept { return _extraRegSaveSize; } //! Returns an offset to the stack where extra registers are saved. inline uint32_t extraRegSaveOffset() const noexcept { return _extraRegSaveOffset; } @@ -1302,9 +1298,8 @@ public: inline bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; } //! Returns function's stack adjustment used in function's prolog and epilog. //! - //! If the returned value is zero it means that the stack is not adjusted. - //! This can mean both that the stack is not used and/or the stack is only - //! adjusted by instructions that pust/pop registers into/from stack. + //! If the returned value is zero it means that the stack is not adjusted. This can mean both that the stack + //! is not used and/or the stack is only adjusted by instructions that pust/pop registers into/from stack. inline uint32_t stackAdjustment() const noexcept { return _stackAdjustment; } //! \} @@ -1317,14 +1312,13 @@ public: //! \} }; -// ============================================================================ -// [asmjit::FuncArgsAssignment] -// ============================================================================ - -//! A helper class that can be used to assign a physical register for each -//! function argument. Use with `BaseEmitter::emitArgsAssignment()`. +//! A helper class that can be used to assign a physical register for each function argument. Use with +//! `BaseEmitter::emitArgsAssignment()`. class FuncArgsAssignment { public: + //! \name Members + //! \{ + //! Function detail. const FuncDetail* _funcDetail; //! Register that can be used to access arguments passed by stack. @@ -1334,6 +1328,8 @@ public: //! Mapping of each function argument. FuncValuePack _argPacks[Globals::kMaxFuncArgs]; + //! \} + //! \name Construction & Destruction //! \{ @@ -1377,41 +1373,40 @@ public: return _argPacks[argIndex][valueIndex].isAssigned(); } - inline void assignReg(size_t argIndex, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignReg(size_t argIndex, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); ASMJIT_ASSERT(reg.isPhysReg()); _argPacks[argIndex][0].initReg(reg.type(), reg.id(), typeId); } - inline void assignReg(size_t argIndex, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignReg(size_t argIndex, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][0].initReg(regType, regId, typeId); } - inline void assignStack(size_t argIndex, int32_t offset, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignStack(size_t argIndex, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][0].initStack(offset, typeId); } - inline void assignRegInPack(size_t argIndex, size_t valueIndex, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignRegInPack(size_t argIndex, size_t valueIndex, const BaseReg& reg, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); ASMJIT_ASSERT(reg.isPhysReg()); _argPacks[argIndex][valueIndex].initReg(reg.type(), reg.id(), typeId); } - inline void assignRegInPack(size_t argIndex, size_t valueIndex, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignRegInPack(size_t argIndex, size_t valueIndex, RegType regType, uint32_t regId, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][valueIndex].initReg(regType, regId, typeId); } - inline void assignStackInPack(size_t argIndex, size_t valueIndex, int32_t offset, uint32_t typeId = Type::kIdVoid) noexcept { + inline void assignStackInPack(size_t argIndex, size_t valueIndex, int32_t offset, TypeId typeId = TypeId::kVoid) noexcept { ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks)); _argPacks[argIndex][valueIndex].initStack(offset, typeId); } - // NOTE: All `assignAll()` methods are shortcuts to assign all arguments at - // once, however, since registers are passed all at once these initializers - // don't provide any way to pass TypeId and/or to keep any argument between + // NOTE: All `assignAll()` methods are shortcuts to assign all arguments at once, however, since registers are + // passed all at once these initializers don't provide any way to pass TypeId and/or to keep any argument between // the arguments passed unassigned. inline void _assignAllInternal(size_t argIndex, const BaseReg& reg) noexcept { assignReg(argIndex, reg); @@ -1435,9 +1430,8 @@ public: //! Update `FuncFrame` based on function's arguments assignment. //! - //! \note You MUST call this in orher to use `BaseEmitter::emitArgsAssignment()`, - //! otherwise the FuncFrame would not contain the information necessary to - //! assign all arguments into the registers and/or stack specified. + //! \note You MUST call this in orher to use `BaseEmitter::emitArgsAssignment()`, otherwise the FuncFrame would + //! not contain the information necessary to assign all arguments into the registers and/or stack specified. ASMJIT_API Error updateFuncFrame(FuncFrame& frame) const noexcept; //! \} diff --git a/src/asmjit/core/funcargscontext.cpp b/src/asmjit/core/funcargscontext.cpp index 331e205..8ce806f 100644 --- a/src/asmjit/core/funcargscontext.cpp +++ b/src/asmjit/core/funcargscontext.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/funcargscontext_p.h" @@ -31,29 +13,24 @@ ASMJIT_BEGIN_NAMESPACE //! \{ FuncArgsContext::FuncArgsContext() noexcept { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _workData[group].reset(); + for (RegGroup group : RegGroupVirtValues{}) + _workData[size_t(group)].reset(); } ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, const FuncArgsAssignment& args, const RAConstraints* constraints) noexcept { - // The code has to be updated if this changes. - ASMJIT_ASSERT(BaseReg::kGroupVirt == 4); - - uint32_t i; - - uint32_t arch = frame.arch(); + Arch arch = frame.arch(); const FuncDetail& func = *args.funcDetail(); _archTraits = &ArchTraits::byArch(arch); _constraints = constraints; - _arch = uint8_t(arch); + _arch = arch; // Initialize `_archRegs`. - for (i = 0; i < BaseReg::kGroupVirt; i++) - _workData[i]._archRegs = _constraints->availableRegs(i); + for (RegGroup group : RegGroupVirtValues{}) + _workData[group]._archRegs = _constraints->availableRegs(group); if (frame.hasPreservedFP()) - _workData[BaseReg::kGroupGp]._archRegs &= ~Support::bitMask(archTraits().fpRegId()); + _workData[size_t(RegGroup::kGp)]._archRegs &= ~Support::bitMask(archTraits().fpRegId()); // Extract information from all function arguments/assignments and build Var[] array. uint32_t varId = 0; @@ -73,7 +50,7 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co FuncValue& src = var.cur; FuncValue& dst = var.out; - uint32_t dstGroup = 0xFFFFFFFFu; + RegGroup dstGroup = RegGroup::kMaxValue; uint32_t dstId = BaseReg::kIdBad; WorkData* dstWd = nullptr; @@ -82,18 +59,17 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co return DebugUtils::errored(kErrorInvalidAssignment); if (dst.isReg()) { - uint32_t dstType = dst.regType(); + RegType dstType = dst.regType(); if (ASMJIT_UNLIKELY(!archTraits().hasRegType(dstType))) return DebugUtils::errored(kErrorInvalidRegType); - // Copy TypeId from source if the destination doesn't have it. The RA - // used by BaseCompiler would never leave TypeId undefined, but users - // of FuncAPI can just assign phys regs without specifying the type. + // Copy TypeId from source if the destination doesn't have it. The RA used by BaseCompiler would never + // leave TypeId undefined, but users of FuncAPI can just assign phys regs without specifying the type. if (!dst.hasTypeId()) dst.setTypeId(archTraits().regTypeToTypeId(dst.regType())); dstGroup = archTraits().regTypeToGroup(dstType); - if (ASMJIT_UNLIKELY(dstGroup >= BaseReg::kGroupVirt)) + if (ASMJIT_UNLIKELY(dstGroup > RegGroup::kMaxVirt)) return DebugUtils::errored(kErrorInvalidRegGroup); dstWd = &_workData[dstGroup]; @@ -112,15 +88,15 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co if (!dst.hasTypeId()) dst.setTypeId(src.typeId()); - RegInfo regInfo = getSuitableRegForMemToMemMove(arch, dst.typeId(), src.typeId()); - if (ASMJIT_UNLIKELY(!regInfo.isValid())) + OperandSignature signature = getSuitableRegForMemToMemMove(arch, dst.typeId(), src.typeId()); + if (ASMJIT_UNLIKELY(!signature.isValid())) return DebugUtils::errored(kErrorInvalidState); - _stackDstMask = uint8_t(_stackDstMask | Support::bitMask(regInfo.group())); + _stackDstMask = uint8_t(_stackDstMask | Support::bitMask(signature.regGroup())); } if (src.isReg()) { uint32_t srcId = src.regId(); - uint32_t srcGroup = archTraits().regTypeToGroup(src.regType()); + RegGroup srcGroup = archTraits().regTypeToGroup(src.regType()); if (dstGroup == srcGroup) { dstWd->assign(varId, srcId); @@ -130,10 +106,10 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co var.markDone(); } else { - if (ASMJIT_UNLIKELY(srcGroup >= BaseReg::kGroupVirt)) + if (ASMJIT_UNLIKELY(srcGroup > RegGroup::kMaxVirt)) return DebugUtils::errored(kErrorInvalidState); - WorkData& srcData = _workData[srcGroup]; + WorkData& srcData = _workData[size_t(srcGroup)]; srcData.assign(varId, srcId); } } @@ -148,14 +124,15 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co } // Initialize WorkData::workRegs. - for (i = 0; i < BaseReg::kGroupVirt; i++) { - _workData[i]._workRegs = (_workData[i].archRegs() & (frame.dirtyRegs(i) | ~frame.preservedRegs(i))) | _workData[i].dstRegs() | _workData[i].assignedRegs(); + for (RegGroup group : RegGroupVirtValues{}) { + _workData[group]._workRegs = + (_workData[group].archRegs() & (frame.dirtyRegs(group) | ~frame.preservedRegs(group))) | _workData[group].dstRegs() | _workData[group].assignedRegs(); } // Create a variable that represents `SARegId` if necessary. bool saRegRequired = _hasStackSrc && frame.hasDynamicAlignment() && !frame.hasPreservedFP(); - WorkData& gpRegs = _workData[BaseReg::kGroupGp]; + WorkData& gpRegs = _workData[RegGroup::kGp]; uint32_t saCurRegId = frame.saRegId(); uint32_t saOutRegId = args.saRegId(); @@ -173,8 +150,8 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co } if (saRegRequired) { - uint32_t ptrTypeId = Environment::is32Bit(arch) ? Type::kIdU32 : Type::kIdU64; - uint32_t ptrRegType = Environment::is32Bit(arch) ? BaseReg::kTypeGp32 : BaseReg::kTypeGp64; + TypeId ptrTypeId = Environment::is32Bit(arch) ? TypeId::kUInt32 : TypeId::kUInt64; + RegType ptrRegType = Environment::is32Bit(arch) ? RegType::kGp32 : RegType::kGp64; _saVarId = uint8_t(varId); _hasPreservedFP = frame.hasPreservedFP(); @@ -187,7 +164,7 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co saCurRegId = saOutRegId; } else { - uint32_t availableRegs = gpRegs.availableRegs(); + RegMask availableRegs = gpRegs.availableRegs(); if (!availableRegs) availableRegs = gpRegs.archRegs() & ~gpRegs.workRegs(); @@ -223,7 +200,7 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co uint32_t srcId = var.cur.regId(); uint32_t dstId = var.out.regId(); - uint32_t group = archTraits().regTypeToGroup(var.cur.regType()); + RegGroup group = archTraits().regTypeToGroup(var.cur.regType()); if (group != archTraits().regTypeToGroup(var.out.regType())) continue; @@ -242,12 +219,12 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co } ASMJIT_FAVOR_SIZE Error FuncArgsContext::markDstRegsDirty(FuncFrame& frame) noexcept { - for (uint32_t i = 0; i < BaseReg::kGroupVirt; i++) { - WorkData& wd = _workData[i]; + for (RegGroup group : RegGroupVirtValues{}) { + WorkData& wd = _workData[group]; uint32_t regs = wd.usedRegs() | wd._dstShuf; wd._workRegs |= regs; - frame.addDirtyRegs(i, regs); + frame.addDirtyRegs(group, regs); } return kErrorOk; @@ -260,19 +237,19 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::markScratchRegs(FuncFrame& frame) noexc groupMask |= _stackDstMask; // Handle register swaps. - groupMask |= _regSwapsMask & ~Support::bitMask(BaseReg::kGroupGp); + groupMask |= _regSwapsMask & ~Support::bitMask(RegGroup::kGp); if (!groupMask) return kErrorOk; // Selects one dirty register per affected group that can be used as a scratch register. - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { if (Support::bitTest(groupMask, group)) { WorkData& wd = _workData[group]; // Initially, pick some clobbered or dirty register. - uint32_t workRegs = wd.workRegs(); - uint32_t regs = workRegs & ~(wd.usedRegs() | wd._dstShuf); + RegMask workRegs = wd.workRegs(); + RegMask regs = workRegs & ~(wd.usedRegs() | wd._dstShuf); // If that didn't work out pick some register which is not in 'used'. if (!regs) @@ -288,7 +265,7 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::markScratchRegs(FuncFrame& frame) noexc if (!regs) continue; - uint32_t regMask = Support::blsi(regs); + RegMask regMask = Support::blsi(regs); wd._workRegs |= regMask; frame.addDirtyRegs(group, regMask); } diff --git a/src/asmjit/core/funcargscontext_p.h b/src/asmjit/core/funcargscontext_p.h index 6c4ea6a..1c928eb 100644 --- a/src/asmjit/core/funcargscontext_p.h +++ b/src/asmjit/core/funcargscontext_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED #define ASMJIT_CORE_FUNCARGSCONTEXT_P_H_INCLUDED @@ -37,38 +19,30 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [TODO: Place somewhere else] -// ============================================================================ - -static inline RegInfo getSuitableRegForMemToMemMove(uint32_t arch, uint32_t dstTypeId, uint32_t srcTypeId) noexcept { +static inline OperandSignature getSuitableRegForMemToMemMove(Arch arch, TypeId dstTypeId, TypeId srcTypeId) noexcept { const ArchTraits& archTraits = ArchTraits::byArch(arch); - uint32_t dstSize = Type::sizeOf(dstTypeId); - uint32_t srcSize = Type::sizeOf(srcTypeId); + uint32_t dstSize = TypeUtils::sizeOf(dstTypeId); + uint32_t srcSize = TypeUtils::sizeOf(srcTypeId); uint32_t maxSize = Support::max<uint32_t>(dstSize, srcSize); uint32_t regSize = Environment::registerSizeFromArch(arch); - uint32_t signature = 0; - if (maxSize <= regSize || (Type::isInt(dstTypeId) && Type::isInt(srcTypeId))) - signature = maxSize <= 4 ? archTraits.regTypeToSignature(BaseReg::kTypeGp32) - : archTraits.regTypeToSignature(BaseReg::kTypeGp64); - else if (maxSize <= 8 && archTraits.hasRegType(BaseReg::kTypeVec64)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec64); - else if (maxSize <= 16 && archTraits.hasRegType(BaseReg::kTypeVec128)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec128); - else if (maxSize <= 32 && archTraits.hasRegType(BaseReg::kTypeVec256)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec256); - else if (maxSize <= 64 && archTraits.hasRegType(BaseReg::kTypeVec512)) - signature = archTraits.regTypeToSignature(BaseReg::kTypeVec512); - - return RegInfo { signature }; + OperandSignature signature(0); + if (maxSize <= regSize || (TypeUtils::isInt(dstTypeId) && TypeUtils::isInt(srcTypeId))) + signature = maxSize <= 4 ? archTraits.regTypeToSignature(RegType::kGp32) + : archTraits.regTypeToSignature(RegType::kGp64); + else if (maxSize <= 8 && archTraits.hasRegType(RegType::kVec64)) + signature = archTraits.regTypeToSignature(RegType::kVec64); + else if (maxSize <= 16 && archTraits.hasRegType(RegType::kVec128)) + signature = archTraits.regTypeToSignature(RegType::kVec128); + else if (maxSize <= 32 && archTraits.hasRegType(RegType::kVec256)) + signature = archTraits.regTypeToSignature(RegType::kVec256); + else if (maxSize <= 64 && archTraits.hasRegType(RegType::kVec512)) + signature = archTraits.regTypeToSignature(RegType::kVec512); + + return signature; } -// ============================================================================ -// [asmjit::FuncArgsContext] -// ============================================================================ - class FuncArgsContext { public: enum VarId : uint32_t { @@ -97,17 +71,17 @@ public: struct WorkData { //! All allocable registers provided by the architecture. - uint32_t _archRegs; + RegMask _archRegs; //! All registers that can be used by the shuffler. - uint32_t _workRegs; + RegMask _workRegs; //! Registers used by the shuffler (all). - uint32_t _usedRegs; + RegMask _usedRegs; //! Assigned registers. - uint32_t _assignedRegs; + RegMask _assignedRegs; //! Destination registers assigned to arguments or SA. - uint32_t _dstRegs; + RegMask _dstRegs; //! Destination registers that require shuffling. - uint32_t _dstShuf; + RegMask _dstShuf; //! Number of register swaps. uint8_t _numSwaps; //! Number of stack loads. @@ -173,19 +147,20 @@ public: _assignedRegs ^= Support::bitMask(regId); } - inline uint32_t archRegs() const noexcept { return _archRegs; } - inline uint32_t workRegs() const noexcept { return _workRegs; } - inline uint32_t usedRegs() const noexcept { return _usedRegs; } - inline uint32_t assignedRegs() const noexcept { return _assignedRegs; } - inline uint32_t dstRegs() const noexcept { return _dstRegs; } - inline uint32_t availableRegs() const noexcept { return _workRegs & ~_assignedRegs; } + inline RegMask archRegs() const noexcept { return _archRegs; } + inline RegMask workRegs() const noexcept { return _workRegs; } + inline RegMask usedRegs() const noexcept { return _usedRegs; } + inline RegMask assignedRegs() const noexcept { return _assignedRegs; } + inline RegMask dstRegs() const noexcept { return _dstRegs; } + inline RegMask availableRegs() const noexcept { return _workRegs & ~_assignedRegs; } }; //! Architecture traits. const ArchTraits* _archTraits = nullptr; + //! Architecture constraints. const RAConstraints* _constraints = nullptr; - //! Architecture identifier. - uint8_t _arch = 0; + //! Target architecture. + Arch _arch = Arch::kUnknown; //! Has arguments passed via stack (SRC). bool _hasStackSrc = false; //! Has preserved frame-pointer (FP). @@ -196,13 +171,13 @@ public: uint8_t _regSwapsMask = 0; uint8_t _saVarId = kVarIdNone; uint32_t _varCount = 0; - WorkData _workData[BaseReg::kGroupVirt]; + Support::Array<WorkData, Globals::kNumVirtGroups> _workData; Var _vars[Globals::kMaxFuncArgs * Globals::kMaxValuePack + 1]; FuncArgsContext() noexcept; inline const ArchTraits& archTraits() const noexcept { return *_archTraits; } - inline uint32_t arch() const noexcept { return _arch; } + inline Arch arch() const noexcept { return _arch; } inline uint32_t varCount() const noexcept { return _varCount; } inline size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); } diff --git a/src/asmjit/core/globals.cpp b/src/asmjit/core/globals.cpp index dc5083b..2bbd0c0 100644 --- a/src/asmjit/core/globals.cpp +++ b/src/asmjit/core/globals.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/globals.h" @@ -27,9 +9,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::DebugUtils] -// ============================================================================ +// DebugUtils - Error As String +// ============================ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { #ifndef ASMJIT_NO_TEXT @@ -54,7 +35,6 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { "LabelNameTooLong\0" "InvalidLabelName\0" "InvalidParentLabel\0" - "NonLocalLabelCannotHaveParent\0" "InvalidSection\0" "TooManySections\0" "InvalidSectionName\0" @@ -97,6 +77,7 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { "InvalidUseOfGpq\0" "InvalidUseOfF80\0" "NotConsecutiveRegs\0" + "ConsecutiveRegsAllocation\0" "IllegalVirtReg\0" "TooManyVirtRegs\0" "NoMorePhysRegs\0" @@ -109,10 +90,10 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { static const uint16_t sErrorIndex[] = { 0, 3, 15, 31, 44, 56, 71, 90, 108, 123, 132, 148, 165, 178, 192, 210, 230, - 247, 264, 283, 313, 328, 344, 363, 382, 400, 422, 440, 459, 474, 490, 504, - 518, 538, 563, 581, 603, 625, 642, 659, 675, 691, 707, 724, 739, 754, 774, - 794, 814, 847, 867, 882, 899, 918, 939, 959, 973, 994, 1008, 1026, 1042, - 1058, 1077, 1092, 1108, 1123, 1138, 1168, 1192, 1211, 1239 + 247, 264, 283, 298, 314, 333, 352, 370, 392, 410, 429, 444, 460, 474, 488, + 508, 533, 551, 573, 595, 612, 629, 645, 661, 677, 694, 709, 724, 744, 764, + 784, 817, 837, 852, 869, 888, 909, 929, 943, 964, 978, 996, 1012, 1028, 1047, + 1073, 1088, 1104, 1119, 1134, 1164, 1188, 1207, 1235 }; // @EnumStringEnd@ @@ -124,6 +105,9 @@ ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { #endif } +// DebugUtils - Debug Output +// ========================= + ASMJIT_FAVOR_SIZE void DebugUtils::debugOutput(const char* str) noexcept { #if defined(_WIN32) ::OutputDebugStringA(str); @@ -132,6 +116,9 @@ ASMJIT_FAVOR_SIZE void DebugUtils::debugOutput(const char* str) noexcept { #endif } +// DebugUtils - Fatal Errors +// ========================= + ASMJIT_FAVOR_SIZE void DebugUtils::assertionFailed(const char* file, int line, const char* msg) noexcept { char str[1024]; diff --git a/src/asmjit/core/globals.h b/src/asmjit/core/globals.h index 3b7bfc9..f2d3c6e 100644 --- a/src/asmjit/core/globals.h +++ b/src/asmjit/core/globals.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_GLOBALS_H_INCLUDED #define ASMJIT_CORE_GLOBALS_H_INCLUDED @@ -28,10 +10,6 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Support] -// ============================================================================ - //! \cond INTERNAL //! \addtogroup asmjit_utilities //! \{ @@ -43,21 +21,21 @@ namespace Support { #if defined(ASMJIT_NO_STDCXX) namespace Support { - ASMJIT_INLINE void* operatorNew(size_t n) noexcept { return malloc(n); } - ASMJIT_INLINE void operatorDelete(void* p) noexcept { if (p) free(p); } + ASMJIT_FORCE_INLINE void* operatorNew(size_t n) noexcept { return malloc(n); } + ASMJIT_FORCE_INLINE void operatorDelete(void* p) noexcept { if (p) free(p); } } // {Support} -#define ASMJIT_BASE_CLASS(TYPE) \ - ASMJIT_INLINE void* operator new(size_t n) noexcept { \ - return Support::operatorNew(n); \ - } \ - \ - ASMJIT_INLINE void operator delete(void* p) noexcept { \ - Support::operatorDelete(p); \ - } \ - \ - ASMJIT_INLINE void* operator new(size_t, void* p) noexcept { return p; } \ - ASMJIT_INLINE void operator delete(void*, void*) noexcept {} +#define ASMJIT_BASE_CLASS(TYPE) \ + ASMJIT_FORCE_INLINE void* operator new(size_t n) noexcept { \ + return Support::operatorNew(n); \ + } \ + \ + ASMJIT_FORCE_INLINE void operator delete(void* p) noexcept { \ + Support::operatorDelete(p); \ + } \ + \ + ASMJIT_FORCE_INLINE void* operator new(size_t, void* p) noexcept { return p; } \ + ASMJIT_FORCE_INLINE void operator delete(void*, void*) noexcept {} #else #define ASMJIT_BASE_CLASS(TYPE) #endif @@ -65,20 +43,32 @@ namespace Support { //! \} //! \endcond -// ============================================================================ -// [asmjit::Globals] -// ============================================================================ - //! \addtogroup asmjit_core //! \{ +//! Byte order. +enum class ByteOrder { + //! Little endian. + kLE = 0, + //! Big endian. + kBE = 1, + //! Native byte order of the target architecture. + kNative = ASMJIT_ARCH_LE ? kLE : kBE, + //! Swapped byte order of the target architecture. + kSwapped = ASMJIT_ARCH_LE ? kBE : kLE +}; + +//! A policy that can be used with some `reset()` member functions. +enum class ResetPolicy : uint32_t { + //! Soft reset, doesn't deallocate memory (default). + kSoft = 0, + //! Hard reset, releases all memory used, if any. + kHard = 1 +}; + //! Contains typedefs, constants, and variables used globally by AsmJit. namespace Globals { -// ============================================================================ -// [asmjit::Globals::<global>] -// ============================================================================ - //! Host memory allocator overhead. static constexpr uint32_t kAllocOverhead = uint32_t(sizeof(intptr_t) * 4); @@ -92,13 +82,11 @@ static constexpr uint32_t kGrowThreshold = 1024 * 1024 * 16; //! //! `2 * log2(n + 1)` //! -//! Size of RB node is at least two pointers (without data), -//! so a theoretical architecture limit would be: +//! Size of RB node is at least two pointers (without data), so a theoretical architecture limit would be: //! //! `2 * log2(addressableMemorySize / sizeof(Node) + 1)` //! -//! Which yields 30 on 32-bit arch and 61 on 64-bit arch. -//! The final value was adjusted by +1 for safety reasons. +//! Which yields 30 on 32-bit arch and 61 on 64-bit arch. The final value was adjusted by +1 for safety reasons. static constexpr uint32_t kMaxTreeHeight = (ASMJIT_ARCH_BITS == 32 ? 30 : 61) + 1; //! Maximum number of operands per a single instruction. @@ -135,34 +123,8 @@ static constexpr uint32_t kNotFound = 0xFFFFFFFFu; //! Invalid base address. static constexpr uint64_t kNoBaseAddress = ~uint64_t(0); -// ============================================================================ -// [asmjit::Globals::ResetPolicy] -// ============================================================================ - -//! Reset policy used by most `reset()` functions. -enum ResetPolicy : uint32_t { - //! Soft reset, doesn't deallocate memory (default). - kResetSoft = 0, - //! Hard reset, releases all memory used, if any. - kResetHard = 1 -}; - -// ============================================================================ -// [asmjit::Globals::Link] -// ============================================================================ - -enum Link : uint32_t { - kLinkLeft = 0, - kLinkRight = 1, - - kLinkPrev = 0, - kLinkNext = 1, - - kLinkFirst = 0, - kLinkLast = 1, - - kLinkCount = 2 -}; +//! Number of virtual register groups. +static constexpr uint32_t kNumVirtGroups = 4; struct Init_ {}; struct NoInit_ {}; @@ -172,24 +134,6 @@ static const constexpr NoInit_ NoInit {}; } // {Globals} -// ============================================================================ -// [asmjit::ByteOrder] -// ============================================================================ - -//! Byte order. -namespace ByteOrder { - enum : uint32_t { - kLE = 0, - kBE = 1, - kNative = ASMJIT_ARCH_LE ? kLE : kBE, - kSwapped = ASMJIT_ARCH_LE ? kBE : kLE - }; -} - -// ============================================================================ -// [asmjit::ptr_as_func / func_as_ptr] -// ============================================================================ - template<typename Func> static inline Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl<Func, void*>(func); } @@ -198,10 +142,6 @@ static inline void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_i //! \} -// ============================================================================ -// [asmjit::Error] -// ============================================================================ - //! \addtogroup asmjit_error_handling //! \{ @@ -223,9 +163,8 @@ enum ErrorCode : uint32_t { //! Invalid state. //! - //! If this error is returned it means that either you are doing something - //! wrong or AsmJit caught itself by doing something wrong. This error should - //! never be ignored. + //! If this error is returned it means that either you are doing something wrong or AsmJit caught itself by + //! doing something wrong. This error should never be ignored. kErrorInvalidState, //! Invalid or incompatible architecture. @@ -253,9 +192,8 @@ enum ErrorCode : uint32_t { kErrorInvalidDirective, //! Attempt to use uninitialized label. kErrorInvalidLabel, - //! Label index overflow - a single \ref BaseAssembler instance can hold - //! almost 2^32 (4 billion) labels. If there is an attempt to create more - //! labels then this error is returned. + //! Label index overflow - a single \ref BaseAssembler instance can hold almost 2^32 (4 billion) labels. If + //! there is an attempt to create more labels then this error is returned. kErrorTooManyLabels, //! Label is already bound. kErrorLabelAlreadyBound, @@ -265,10 +203,9 @@ enum ErrorCode : uint32_t { kErrorLabelNameTooLong, //! Label must always be local if it's anonymous (without a name). kErrorInvalidLabelName, - //! Parent id passed to \ref CodeHolder::newNamedLabelEntry() was invalid. + //! Parent id passed to \ref CodeHolder::newNamedLabelEntry() was either invalid or parent is not supported + //! by the requested `LabelType`. kErrorInvalidParentLabel, - //! Parent id specified for a non-local (global) label. - kErrorNonLocalLabelCannotHaveParent, //! Invalid section. kErrorInvalidSection, @@ -356,11 +293,12 @@ enum ErrorCode : uint32_t { kErrorInvalidUseOfGpbHi, //! Invalid use of a 64-bit GPQ register in 32-bit mode. kErrorInvalidUseOfGpq, - //! Invalid use of an 80-bit float (\ref Type::kIdF80). + //! Invalid use of an 80-bit float (\ref TypeId::kFloat80). kErrorInvalidUseOfF80, - //! Some registers in the instruction muse be consecutive (some ARM and AVX512 - //! neural-net instructions). + //! Instruction requires the use of consecutive registers, but registers in operands weren't (AVX512, ASIMD load/store, etc...). kErrorNotConsecutiveRegs, + //! Failed to allocate consecutive registers - allocable registers either too restricted or a bug in RW info. + kErrorConsecutiveRegsAllocation, //! Illegal virtual register - reported by instruction validation. kErrorIllegalVirtReg, @@ -388,23 +326,19 @@ enum ErrorCode : uint32_t { kErrorCount }; -// ============================================================================ -// [asmjit::DebugUtils] -// ============================================================================ - //! Debugging utilities. namespace DebugUtils { //! \cond INTERNAL //! Used to silence warnings about unused arguments or variables. template<typename... Args> -static ASMJIT_INLINE void unused(Args&&...) noexcept {} +static inline void unused(Args&&...) noexcept {} //! \endcond //! Returns the error `err` passed. //! -//! Provided for debugging purposes. Putting a breakpoint inside `errored` can -//! help with tracing the origin of any error reported / returned by AsmJit. +//! Provided for debugging purposes. Putting a breakpoint inside `errored` can help with tracing the origin of any +//! error reported / returned by AsmJit. static constexpr Error errored(Error err) noexcept { return err; } //! Returns a printable version of `asmjit::Error` code. @@ -419,12 +353,10 @@ ASMJIT_API void debugOutput(const char* str) noexcept; //! \param line Line in the source file. //! \param msg Message to display. //! -//! If you have problems with assertion failures a breakpoint can be put -//! at \ref assertionFailed() function (asmjit/core/globals.cpp). A call stack -//! will be available when such assertion failure is triggered. AsmJit always -//! returns errors on failures, assertions are a last resort and usually mean -//! unrecoverable state due to out of range array access or totally invalid -//! arguments like nullptr where a valid pointer should be provided, etc... +//! If you have problems with assertion failures a breakpoint can be put at \ref assertionFailed() function +//! (asmjit/core/globals.cpp). A call stack will be available when such assertion failure is triggered. AsmJit +//! always returns errors on failures, assertions are a last resort and usually mean unrecoverable state due to out +//! of range array access or totally invalid arguments like nullptr where a valid pointer should be provided, etc... ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, const char* msg) noexcept; } // {DebugUtils} @@ -445,9 +377,8 @@ ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, cons //! \def ASMJIT_PROPAGATE(...) //! -//! Propagates a possible `Error` produced by `...` to the caller by returning -//! the error immediately. Used by AsmJit internally, but kept public for users -//! that want to use the same technique to propagate errors to the caller. +//! Propagates a possible `Error` produced by `...` to the caller by returning the error immediately. Used by AsmJit +//! internally, but kept public for users that want to use the same technique to propagate errors to the caller. #define ASMJIT_PROPAGATE(...) \ do { \ ::asmjit::Error _err = __VA_ARGS__; \ diff --git a/src/asmjit/core/inst.cpp b/src/asmjit/core/inst.cpp index b949a60..26f1df9 100644 --- a/src/asmjit/core/inst.cpp +++ b/src/asmjit/core/inst.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/archtraits.h" @@ -35,12 +17,11 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::InstAPI - Text] -// ============================================================================ +// InstAPI - InstId <-> String +// =========================== #ifndef ASMJIT_NO_TEXT -Error InstAPI::instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept { +Error InstAPI::instIdToString(Arch arch, InstId instId, String& output) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) return x86::InstInternal::instIdToString(arch, instId, output); @@ -54,7 +35,7 @@ Error InstAPI::instIdToString(uint32_t arch, uint32_t instId, String& output) no return DebugUtils::errored(kErrorInvalidArch); } -uint32_t InstAPI::stringToInstId(uint32_t arch, const char* s, size_t len) noexcept { +InstId InstAPI::stringToInstId(Arch arch, const char* s, size_t len) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) return x86::InstInternal::stringToInstId(arch, s, len); @@ -69,12 +50,11 @@ uint32_t InstAPI::stringToInstId(uint32_t arch, const char* s, size_t len) noexc } #endif // !ASMJIT_NO_TEXT -// ============================================================================ -// [asmjit::InstAPI - Validate] -// ============================================================================ +// InstAPI - Validate +// ================== #ifndef ASMJIT_NO_VALIDATION -Error InstAPI::validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags) noexcept { +Error InstAPI::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) return x86::InstInternal::validate(arch, inst, operands, opCount, validationFlags); @@ -89,12 +69,11 @@ Error InstAPI::validate(uint32_t arch, const BaseInst& inst, const Operand_* ope } #endif // !ASMJIT_NO_VALIDATION -// ============================================================================ -// [asmjit::InstAPI - QueryRWInfo] -// ============================================================================ +// InstAPI - QueryRWInfo +// ===================== #ifndef ASMJIT_NO_INTROSPECTION -Error InstAPI::queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { +Error InstAPI::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { if (ASMJIT_UNLIKELY(opCount > Globals::kMaxOpCount)) return DebugUtils::errored(kErrorInvalidArgument); @@ -112,12 +91,11 @@ Error InstAPI::queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* } #endif // !ASMJIT_NO_INTROSPECTION -// ============================================================================ -// [asmjit::InstAPI - QueryFeatures] -// ============================================================================ +// InstAPI - QueryFeatures +// ======================= #ifndef ASMJIT_NO_INTROSPECTION -Error InstAPI::queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept { +Error InstAPI::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { #if !defined(ASMJIT_NO_X86) if (Environment::isFamilyX86(arch)) return x86::InstInternal::queryFeatures(arch, inst, operands, opCount, out); diff --git a/src/asmjit/core/inst.h b/src/asmjit/core/inst.h index e803647..0b890d8 100644 --- a/src/asmjit/core/inst.h +++ b/src/asmjit/core/inst.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_INST_H_INCLUDED #define ASMJIT_CORE_INST_H_INCLUDED @@ -34,20 +16,179 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_instruction_db //! \{ -// ============================================================================ -// [asmjit::BaseInst] -// ============================================================================ +//! Describes an instruction. +//! +//! Each architecture has a set of valid instructions indexed from 0. Instruction with 0 id is, however, a special +//! instruction that describes an invalid instruction. Different architectures can share the same instruction id, +//! which would describe a different instruction per architecture. +//! +//! Instruction identifiers listed by architecture: +//! +//! - \ref x86::Inst (X86 and X86_64) +typedef uint32_t InstId; + +//! Instruction options. +//! +//! Instruction options complement instruction identifier and attributes. +enum class InstOptions : uint32_t { + //! No options. + kNone = 0, + + //! Used internally by emitters for handling errors and rare cases. + kReserved = 0x00000001u, + + //! Prevents following a jump during compilation (Compiler). + kUnfollow = 0x00000002u, + + //! Overwrite the destination operand(s) (Compiler). + //! + //! Hint that is important for register liveness analysis. It tells the compiler that the destination operand will + //! be overwritten now or by adjacent instructions. Compiler knows when a register is completely overwritten by a + //! single instruction, for example you don't have to mark "movaps" or "pxor x, x", however, if a pair of + //! instructions is used and the first of them doesn't completely overwrite the content of the destination, + //! Compiler fails to mark that register as dead. + //! + //! X86 Specific + //! ------------ + //! + //! - All instructions that always overwrite at least the size of the register the virtual-register uses, for + //! example "mov", "movq", "movaps" don't need the overwrite option to be used - conversion, shuffle, and + //! other miscellaneous instructions included. + //! + //! - All instructions that clear the destination register if all operands are the same, for example "xor x, x", + //! "pcmpeqb x x", etc... + //! + //! - Consecutive instructions that partially overwrite the variable until there is no old content require + //! `BaseCompiler::overwrite()` to be used. Some examples (not always the best use cases thought): + //! + //! - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa + //! - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa + //! - `mov al, ?` followed by `and ax, 0xFF` + //! - `mov al, ?` followed by `mov ah, al` + //! - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1` + //! + //! - If the allocated virtual register is used temporarily for scalar operations. For example if you allocate a + //! full vector like `x86::Compiler::newXmm()` and then use that vector for scalar operations you should use + //! `overwrite()` directive: + //! + //! - `sqrtss x, y` - only LO element of `x` is changed, if you don't + //! use HI elements, use `compiler.overwrite().sqrtss(x, y)`. + kOverwrite = 0x00000004u, + + //! Emit short-form of the instruction. + kShortForm = 0x00000010u, + //! Emit long-form of the instruction. + kLongForm = 0x00000020u, + + //! Conditional jump is likely to be taken. + kTaken = 0x00000040u, + //! Conditional jump is unlikely to be taken. + kNotTaken = 0x00000080u, + + // X86 & X64 Options + // ----------------- + + //! Use ModMR instead of ModRM if applicable. + kX86_ModMR = 0x00000100u, + //! Use ModRM instead of ModMR if applicable. + kX86_ModRM = 0x00000200u, + //! Use 3-byte VEX prefix if possible (AVX) (must be 0x00000400). + kX86_Vex3 = 0x00000400u, + //! Use VEX prefix when both VEX|EVEX prefixes are available (HINT: AVX_VNNI). + kX86_Vex = 0x00000800u, + //! Use 4-byte EVEX prefix if possible (AVX-512) (must be 0x00001000). + kX86_Evex = 0x00001000u, + + //! LOCK prefix (lock-enabled instructions only). + kX86_Lock = 0x00002000u, + //! REP prefix (string instructions only). + kX86_Rep = 0x00004000u, + //! REPNE prefix (string instructions only). + kX86_Repne = 0x00008000u, + + //! XACQUIRE prefix (only allowed instructions). + kX86_XAcquire = 0x00010000u, + //! XRELEASE prefix (only allowed instructions). + kX86_XRelease = 0x00020000u, + + //! AVX-512: embedded-rounding {er} and implicit {sae}. + kX86_ER = 0x00040000u, + //! AVX-512: suppress-all-exceptions {sae}. + kX86_SAE = 0x00080000u, + //! AVX-512: round-to-nearest (even) {rn-sae} (bits 00). + kX86_RN_SAE = 0x00000000u, + //! AVX-512: round-down (toward -inf) {rd-sae} (bits 01). + kX86_RD_SAE = 0x00200000u, + //! AVX-512: round-up (toward +inf) {ru-sae} (bits 10). + kX86_RU_SAE = 0x00400000u, + //! AVX-512: round-toward-zero (truncate) {rz-sae} (bits 11). + kX86_RZ_SAE = 0x00600000u, + //! AVX-512: Use zeroing {k}{z} instead of merging {k}. + kX86_ZMask = 0x00800000u, + + //! AVX-512: Mask to get embedded rounding bits (2 bits). + kX86_ERMask = kX86_RZ_SAE, + //! AVX-512: Mask of all possible AVX-512 options except EVEX prefix flag. + kX86_AVX512Mask = 0x00FC0000u, + + //! Force REX.B and/or VEX.B field (X64 only). + kX86_OpCodeB = 0x01000000u, + //! Force REX.X and/or VEX.X field (X64 only). + kX86_OpCodeX = 0x02000000u, + //! Force REX.R and/or VEX.R field (X64 only). + kX86_OpCodeR = 0x04000000u, + //! Force REX.W and/or VEX.W field (X64 only). + kX86_OpCodeW = 0x08000000u, + //! Force REX prefix (X64 only). + kX86_Rex = 0x40000000u, + //! Invalid REX prefix (set by X86 or when AH|BH|CH|DH regs are used on X64). + kX86_InvalidRex = 0x80000000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(InstOptions) + +//! Instruction control flow. +enum class InstControlFlow : uint32_t { + //! Regular instruction. + kRegular = 0u, + //! Unconditional jump. + kJump = 1u, + //! Conditional jump (branch). + kBranch = 2u, + //! Function call. + kCall = 3u, + //! Function return. + kReturn = 4u, + + //! Maximum value of `InstType`. + kMaxValue = kReturn +}; + +//! Hint that is used when both input operands to the instruction are the same. +//! +//! Provides hints to the instrution RW query regarding special cases in which two or more operands are the same +//! registers. This is required by instructions such as XOR, AND, OR, SUB, etc... These hints will influence the +//! RW operations query. +enum class InstSameRegHint : uint8_t { + //! No special handling. + kNone = 0, + //! Operands become read-only, the operation doesn't change the content - `X & X` and similar. + kRO = 1, + //! Operands become write-only, the content of the input(s) don't matter - `X ^ X`, `X - X`, and similar. + kWO = 2 +}; -//! Instruction id, options, and extraReg in a single structure. This structure -//! exists mainly to simplify analysis and validation API that requires `BaseInst` -//! and `Operand[]` array. +//! Instruction id, options, and extraReg in a single structure. This structure exists mainly to simplify analysis +//! and validation API that requires `BaseInst` and `Operand[]` array. class BaseInst { public: - //! Instruction id, see \ref BaseInst::Id or {arch-specific}::Inst::Id. - uint32_t _id; - //! Instruction options, see \ref BaseInst::Options or {arch-specific}::Inst::Options. - uint32_t _options; - //! Extra register used by instruction (either REP register or AVX-512 selector). + //! \name Members + //! \{ + + //! Instruction id. + InstId _id; + //! Instruction options. + InstOptions _options; + //! Extra register used by the instruction (either REP register or AVX-512 selector). RegOnly _extraReg; enum Id : uint32_t { @@ -57,110 +198,39 @@ public: kIdAbstract = 0x80000000u }; - enum Options : uint32_t { - //! Used internally by emitters for handling errors and rare cases. - kOptionReserved = 0x00000001u, - - //! Prevents following a jump during compilation (BaseCompiler). - kOptionUnfollow = 0x00000002u, - - //! Overwrite the destination operand(s) (BaseCompiler). - //! - //! Hint that is important for register liveness analysis. It tells the - //! compiler that the destination operand will be overwritten now or by - //! adjacent instructions. BaseCompiler knows when a register is completely - //! overwritten by a single instruction, for example you don't have to - //! mark "movaps" or "pxor x, x", however, if a pair of instructions is - //! used and the first of them doesn't completely overwrite the content - //! of the destination, BaseCompiler fails to mark that register as dead. - //! - //! X86 Specific - //! ------------ - //! - //! - All instructions that always overwrite at least the size of the - //! register the virtual-register uses , for example "mov", "movq", - //! "movaps" don't need the overwrite option to be used - conversion, - //! shuffle, and other miscellaneous instructions included. - //! - //! - All instructions that clear the destination register if all operands - //! are the same, for example "xor x, x", "pcmpeqb x x", etc... - //! - //! - Consecutive instructions that partially overwrite the variable until - //! there is no old content require `BaseCompiler::overwrite()` to be used. - //! Some examples (not always the best use cases thought): - //! - //! - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa - //! - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa - //! - `mov al, ?` followed by `and ax, 0xFF` - //! - `mov al, ?` followed by `mov ah, al` - //! - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1` - //! - //! - If allocated variable is used temporarily for scalar operations. For - //! example if you allocate a full vector like `x86::Compiler::newXmm()` - //! and then use that vector for scalar operations you should use - //! `overwrite()` directive: - //! - //! - `sqrtss x, y` - only LO element of `x` is changed, if you don't - //! use HI elements, use `compiler.overwrite().sqrtss(x, y)`. - kOptionOverwrite = 0x00000004u, - - //! Emit short-form of the instruction. - kOptionShortForm = 0x00000010u, - //! Emit long-form of the instruction. - kOptionLongForm = 0x00000020u, - - //! Conditional jump is likely to be taken. - kOptionTaken = 0x00000040u, - //! Conditional jump is unlikely to be taken. - kOptionNotTaken = 0x00000080u - }; - - //! Control type. - enum ControlType : uint32_t { - //! No control type (doesn't jump). - kControlNone = 0u, - //! Unconditional jump. - kControlJump = 1u, - //! Conditional jump (branch). - kControlBranch = 2u, - //! Function call. - kControlCall = 3u, - //! Function return. - kControlReturn = 4u - }; + //! \} //! \name Construction & Destruction //! \{ //! Creates a new BaseInst instance with `id` and `options` set. //! - //! Default values of `id` and `options` are zero, which means none instruction. - //! Such instruction is guaranteed to never exist for any architecture supported - //! by AsmJit. - inline explicit BaseInst(uint32_t id = 0, uint32_t options = 0) noexcept - : _id(id), + //! Default values of `id` and `options` are zero, which means 'none' instruction. Such instruction is guaranteed + //! to never exist for any architecture supported by AsmJit. + inline explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept + : _id(instId), _options(options), _extraReg() {} - inline BaseInst(uint32_t id, uint32_t options, const RegOnly& extraReg) noexcept - : _id(id), + inline BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept + : _id(instId), _options(options), _extraReg(extraReg) {} - inline BaseInst(uint32_t id, uint32_t options, const BaseReg& extraReg) noexcept - : _id(id), + inline BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept + : _id(instId), _options(options), _extraReg { extraReg.signature(), extraReg.id() } {} //! \} - //! \name Instruction ID + //! \name Instruction Id //! \{ //! Returns the instruction id. - inline uint32_t id() const noexcept { return _id; } + inline InstId id() const noexcept { return _id; } //! Sets the instruction id to the given `id`. - inline void setId(uint32_t id) noexcept { _id = id; } + inline void setId(InstId id) noexcept { _id = id; } //! Resets the instruction id to zero, see \ref kIdNone. inline void resetId() noexcept { _id = 0; } @@ -169,12 +239,12 @@ public: //! \name Instruction Options //! \{ - inline uint32_t options() const noexcept { return _options; } - inline bool hasOption(uint32_t option) const noexcept { return (_options & option) != 0; } - inline void setOptions(uint32_t options) noexcept { _options = options; } - inline void addOptions(uint32_t options) noexcept { _options |= options; } - inline void clearOptions(uint32_t options) noexcept { _options &= ~options; } - inline void resetOptions() noexcept { _options = 0; } + inline InstOptions options() const noexcept { return _options; } + inline bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); } + inline void setOptions(InstOptions options) noexcept { _options = options; } + inline void addOptions(InstOptions options) noexcept { _options |= options; } + inline void clearOptions(InstOptions options) noexcept { _options &= ~options; } + inline void resetOptions() noexcept { _options = InstOptions::kNone; } //! \} @@ -191,20 +261,144 @@ public: //! \} }; -// ============================================================================ -// [asmjit::OpRWInfo] -// ============================================================================ +//! CPU read/write flags used by \ref InstRWInfo. +//! +//! These flags can be used to get a basic overview about CPU specifics flags used by instructions. +enum class CpuRWFlags : uint32_t { + //! No flags. + kNone = 0x00000000u, + + // Common RW Flags (0x000000FF) + // ---------------------------- + + //! Carry flag. + kCF = 0x00000001u, + //! Signed overflow flag. + kOF = 0x00000002u, + //! Sign flag (negative/sign, if set). + kSF = 0x00000004u, + //! Zero and/or equality flag (1 if zero/equal). + kZF = 0x00000008u, + + // X86 Specific RW Flags (0xFFFFFF00) + // ---------------------------------- + + //! Carry flag (X86, X86_64). + kX86_CF = kCF, + //! Overflow flag (X86, X86_64). + kX86_OF = kOF, + //! Sign flag (X86, X86_64). + kX86_SF = kSF, + //! Zero flag (X86, X86_64). + kX86_ZF = kZF, + + //! Adjust flag (X86, X86_64). + kX86_AF = 0x00000100u, + //! Parity flag (X86, X86_64). + kX86_PF = 0x00000200u, + //! Direction flag (X86, X86_64). + kX86_DF = 0x00000400u, + //! Interrupt enable flag (X86, X86_64). + kX86_IF = 0x00000800u, + + //! Alignment check flag (X86, X86_64). + kX86_AC = 0x00001000u, + + //! FPU C0 status flag (X86, X86_64). + kX86_C0 = 0x00010000u, + //! FPU C1 status flag (X86, X86_64). + kX86_C1 = 0x00020000u, + //! FPU C2 status flag (X86, X86_64). + kX86_C2 = 0x00040000u, + //! FPU C3 status flag (X86, X86_64). + kX86_C3 = 0x00080000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(CpuRWFlags) + +//! Operand read/write flags describe how the operand is accessed and some additional features. +enum class OpRWFlags { + //! No flags. + kNone = 0, + + //! Operand is read. + kRead = 0x00000001u, + + //! Operand is written. + kWrite = 0x00000002u, + + //! Operand is both read and written. + kRW = 0x00000003u, + + //! Register operand can be replaced by a memory operand. + kRegMem = 0x00000004u, + + //! The register must be allocated to the index of the previous register + 1. + //! + //! This flag is used by all architectures to describe instructions that use consecutive registers, where only the + //! first one is encoded in the instruction, and the others are just a sequence that starts with the first one. On + //! X86/X86_64 architecture this is used by instructions such as V4FMADDPS, V4FMADDSS, V4FNMADDPS, V4FNMADDSS, + //! VP4DPWSSD, VP4DPWSSDS, VP2INTERSECTD, and VP2INTERSECTQ. On ARM/AArch64 this is used by vector load and store + //! instructions that can load or store multiple registers at once. + kConsecutive = 0x00000008u, + + //! The `extendByteMask()` represents a zero extension. + kZExt = 0x00000010u, + + //! Register operand must use \ref OpRWInfo::physId(). + kRegPhysId = 0x00000100u, + //! Base register of a memory operand must use \ref OpRWInfo::physId(). + kMemPhysId = 0x00000200u, + + //! This memory operand is only used to encode registers and doesn't access memory. + //! + //! X86 Specific + //! ------------ + //! + //! Instructions that use such feature include BNDLDX, BNDSTX, and LEA. + kMemFake = 0x000000400u, + + //! Base register of the memory operand will be read. + kMemBaseRead = 0x00001000u, + //! Base register of the memory operand will be written. + kMemBaseWrite = 0x00002000u, + //! Base register of the memory operand will be read & written. + kMemBaseRW = 0x00003000u, + + //! Index register of the memory operand will be read. + kMemIndexRead = 0x00004000u, + //! Index register of the memory operand will be written. + kMemIndexWrite = 0x00008000u, + //! Index register of the memory operand will be read & written. + kMemIndexRW = 0x0000C000u, + + //! Base register of the memory operand will be modified before the operation. + kMemBasePreModify = 0x00010000u, + //! Base register of the memory operand will be modified after the operation. + kMemBasePostModify = 0x00020000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(OpRWFlags) + +// Don't remove these asserts. Read/Write flags are used extensively +// by Compiler and they must always be compatible with constants below. +static_assert(uint32_t(OpRWFlags::kRead) == 0x1, "OpRWFlags::kRead flag must be 0x1"); +static_assert(uint32_t(OpRWFlags::kWrite) == 0x2, "OpRWFlags::kWrite flag must be 0x2"); +static_assert(uint32_t(OpRWFlags::kRegMem) == 0x4, "OpRWFlags::kRegMem flag must be 0x4"); //! Read/Write information related to a single operand, used by \ref InstRWInfo. struct OpRWInfo { - //! Read/Write flags, see \ref OpRWInfo::Flags. - uint32_t _opFlags; + //! \name Members + //! \{ + + //! Read/Write flags. + OpRWFlags _opFlags; //! Physical register index, if required. uint8_t _physId; //! Size of a possible memory operand that can replace a register operand. uint8_t _rmSize; + //! If non-zero, then this is a consecutive lead register, and the value describes how many registers follow. + uint8_t _consecutiveLeadCount; //! Reserved for future use. - uint8_t _reserved[2]; + uint8_t _reserved[1]; //! Read bit-mask where each bit represents one byte read from Reg/Mem. uint64_t _readByteMask; //! Write bit-mask where each bit represents one byte written to Reg/Mem. @@ -212,61 +406,7 @@ struct OpRWInfo { //! Zero/Sign extend bit-mask where each bit represents one byte written to Reg/Mem. uint64_t _extendByteMask; - //! Flags describe how the operand is accessed and some additional information. - enum Flags : uint32_t { - //! Operand is read. - kRead = 0x00000001u, - - //! Operand is written. - kWrite = 0x00000002u, - - //! Operand is both read and written. - kRW = 0x00000003u, - - //! Register operand can be replaced by a memory operand. - kRegMem = 0x00000004u, - - //! The `extendByteMask()` represents a zero extension. - kZExt = 0x00000010u, - - //! Register operand must use \ref physId(). - kRegPhysId = 0x00000100u, - //! Base register of a memory operand must use \ref physId(). - kMemPhysId = 0x00000200u, - - //! This memory operand is only used to encode registers and doesn't access memory. - //! - //! X86 Specific - //! ------------ - //! - //! Instructions that use such feature include BNDLDX, BNDSTX, and LEA. - kMemFake = 0x000000400u, - - //! Base register of the memory operand will be read. - kMemBaseRead = 0x00001000u, - //! Base register of the memory operand will be written. - kMemBaseWrite = 0x00002000u, - //! Base register of the memory operand will be read & written. - kMemBaseRW = 0x00003000u, - - //! Index register of the memory operand will be read. - kMemIndexRead = 0x00004000u, - //! Index register of the memory operand will be written. - kMemIndexWrite = 0x00008000u, - //! Index register of the memory operand will be read & written. - kMemIndexRW = 0x0000C000u, - - //! Base register of the memory operand will be modified before the operation. - kMemBasePreModify = 0x00010000u, - //! Base register of the memory operand will be modified after the operation. - kMemBasePostModify = 0x00020000u - }; - - // Don't remove these asserts. Read/Write flags are used extensively - // by Compiler and they must always be compatible with constants below. - static_assert(kRead == 0x1, "OpRWInfo::kRead flag must be 0x1"); - static_assert(kWrite == 0x2, "OpRWInfo::kWrite flag must be 0x2"); - static_assert(kRegMem == 0x4, "OpRWInfo::kRegMem flag must be 0x4"); + //! \} //! \name Reset //! \{ @@ -276,20 +416,21 @@ struct OpRWInfo { //! Resets this operand info (resets all members) and set common information //! to the given `opFlags`, `regSize`, and possibly `physId`. - inline void reset(uint32_t opFlags, uint32_t regSize, uint32_t physId = BaseReg::kIdBad) noexcept { + inline void reset(OpRWFlags opFlags, uint32_t regSize, uint32_t physId = BaseReg::kIdBad) noexcept { _opFlags = opFlags; _physId = uint8_t(physId); - _rmSize = uint8_t((opFlags & kRegMem) ? regSize : uint32_t(0)); + _rmSize = Support::test(opFlags, OpRWFlags::kRegMem) ? uint8_t(regSize) : uint8_t(0); + _consecutiveLeadCount = 0; _resetReserved(); uint64_t mask = Support::lsbMask<uint64_t>(regSize); - _readByteMask = opFlags & kRead ? mask : uint64_t(0); - _writeByteMask = opFlags & kWrite ? mask : uint64_t(0); + _readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0); + _writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0); _extendByteMask = 0; } inline void _resetReserved() noexcept { - memset(_reserved, 0, sizeof(_reserved)); + _reserved[0] = 0; } //! \} @@ -297,77 +438,77 @@ struct OpRWInfo { //! \name Operand Flags //! \{ - //! Returns operand flags, see \ref Flags. - inline uint32_t opFlags() const noexcept { return _opFlags; } + //! Returns operand flags. + inline OpRWFlags opFlags() const noexcept { return _opFlags; } //! Tests whether operand flags contain the given `flag`. - inline bool hasOpFlag(uint32_t flag) const noexcept { return (_opFlags & flag) != 0; } + inline bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); } //! Adds the given `flags` to operand flags. - inline void addOpFlags(uint32_t flags) noexcept { _opFlags |= flags; } + inline void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; } //! Removes the given `flags` from operand flags. - inline void clearOpFlags(uint32_t flags) noexcept { _opFlags &= ~flags; } + inline void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; } //! Tests whether this operand is read from. - inline bool isRead() const noexcept { return hasOpFlag(kRead); } + inline bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); } //! Tests whether this operand is written to. - inline bool isWrite() const noexcept { return hasOpFlag(kWrite); } + inline bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); } //! Tests whether this operand is both read and write. - inline bool isReadWrite() const noexcept { return (_opFlags & kRW) == kRW; } + inline bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; } //! Tests whether this operand is read only. - inline bool isReadOnly() const noexcept { return (_opFlags & kRW) == kRead; } + inline bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; } //! Tests whether this operand is write only. - inline bool isWriteOnly() const noexcept { return (_opFlags & kRW) == kWrite; } + inline bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; } + + //! Returns the type of a lead register, which is followed by consecutive registers. + inline uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; } //! Tests whether this operand is Reg/Mem //! //! Reg/Mem operands can use either register or memory. - inline bool isRm() const noexcept { return hasOpFlag(kRegMem); } + inline bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); } //! Tests whether the operand will be zero extended. - inline bool isZExt() const noexcept { return hasOpFlag(kZExt); } + inline bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); } //! \} //! \name Memory Flags //! \{ - //! Tests whether this is a fake memory operand, which is only used, because - //! of encoding. Fake memory operands do not access any memory, they are only - //! used to encode registers. - inline bool isMemFake() const noexcept { return hasOpFlag(kMemFake); } + //! Tests whether this is a fake memory operand, which is only used, because of encoding. Fake memory operands do + //! not access any memory, they are only used to encode registers. + inline bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); } //! Tests whether the instruction's memory BASE register is used. - inline bool isMemBaseUsed() const noexcept { return (_opFlags & kMemBaseRW) != 0; } + inline bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); } //! Tests whether the instruction reads from its BASE registers. - inline bool isMemBaseRead() const noexcept { return hasOpFlag(kMemBaseRead); } + inline bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); } //! Tests whether the instruction writes to its BASE registers. - inline bool isMemBaseWrite() const noexcept { return hasOpFlag(kMemBaseWrite); } + inline bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); } //! Tests whether the instruction reads and writes from/to its BASE registers. - inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseRW; } + inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; } //! Tests whether the instruction only reads from its BASE registers. - inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseRead; } + inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; } //! Tests whether the instruction only writes to its BASE registers. - inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseWrite; } + inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; } - //! Tests whether the instruction modifies the BASE register before it uses - //! it to calculate the target address. - inline bool isMemBasePreModify() const noexcept { return hasOpFlag(kMemBasePreModify); } - //! Tests whether the instruction modifies the BASE register after it uses - //! it to calculate the target address. - inline bool isMemBasePostModify() const noexcept { return hasOpFlag(kMemBasePostModify); } + //! Tests whether the instruction modifies the BASE register before it uses it to calculate the target address. + inline bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); } + //! Tests whether the instruction modifies the BASE register after it uses it to calculate the target address. + inline bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); } //! Tests whether the instruction's memory INDEX register is used. - inline bool isMemIndexUsed() const noexcept { return (_opFlags & kMemIndexRW) != 0; } + inline bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); } //! Tests whether the instruction reads the INDEX registers. - inline bool isMemIndexRead() const noexcept { return hasOpFlag(kMemIndexRead); } + inline bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); } //! Tests whether the instruction writes to its INDEX registers. - inline bool isMemIndexWrite() const noexcept { return hasOpFlag(kMemIndexWrite); } + inline bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); } //! Tests whether the instruction reads and writes from/to its INDEX registers. - inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexRW; } + inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; } //! Tests whether the instruction only reads from its INDEX registers. - inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexRead; } + inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; } //! Tests whether the instruction only writes to its INDEX registers. - inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexWrite; } + inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; } //! \} @@ -415,18 +556,17 @@ struct OpRWInfo { //! \} }; -// ============================================================================ -// [asmjit::InstRWInfo] -// ============================================================================ - //! Read/Write information of an instruction. struct InstRWInfo { + //! \name Members + //! \{ + //! Instruction flags (there are no flags at the moment, this field is reserved). uint32_t _instFlags; - //! Mask of CPU flags read. - uint32_t _readFlags; - //! Mask of CPU flags written. - uint32_t _writeFlags; + //! CPU flags read. + CpuRWFlags _readFlags; + //! CPU flags written. + CpuRWFlags _writeFlags; //! Count of operands. uint8_t _opCount; //! CPU feature required for replacing register operand with memory operand. @@ -438,6 +578,8 @@ struct InstRWInfo { //! Read/Write info of instruction operands. OpRWInfo _operands[Globals::kMaxOpCount]; + //! \} + //! \name Commons //! \{ @@ -446,40 +588,29 @@ struct InstRWInfo { //! \} - //! \name Instruction Flags - //! - //! \{ - - inline uint32_t instFlags() const noexcept { return _instFlags; } - inline bool hasInstFlag(uint32_t flag) const noexcept { return (_instFlags & flag) != 0; } - - //! } - - //! \name CPU Flags Read/Write Information + //! \name CPU Flags Information //! \{ - //! Returns read flags of the instruction. - inline uint32_t readFlags() const noexcept { return _readFlags; } - //! Returns write flags of the instruction. - inline uint32_t writeFlags() const noexcept { return _writeFlags; } + //! Returns a mask of CPU flags read. + inline CpuRWFlags readFlags() const noexcept { return _readFlags; } + //! Returns a mask of CPU flags written. + inline CpuRWFlags writeFlags() const noexcept { return _writeFlags; } //! \} //! \name Reg/Mem Information //! \{ - //! Returns the CPU feature required to replace a register operand with memory - //! operand. If the returned feature is zero (none) then this instruction - //! either doesn't provide memory operand combination or there is no extra - //! CPU feature required. + //! Returns the CPU feature required to replace a register operand with memory operand. If the returned feature is + //! zero (none) then this instruction either doesn't provide memory operand combination or there is no extra CPU + //! feature required. //! //! X86 Specific //! ------------ //! - //! Some AVX+ instructions may require extra features for replacing registers - //! with memory operands, for example VPSLLDQ instruction only supports - //! 'reg/reg/imm' combination on AVX/AVX2 capable CPUs and requires AVX-512 for - //! 'reg/mem/imm' combination. + //! Some AVX+ instructions may require extra features for replacing registers with memory operands, for example + //! VPSLLDQ instruction only supports `vpslldq reg, reg, imm` combination on AVX/AVX2 capable CPUs and requires + //! AVX-512 for `vpslldq reg, mem, imm` combination. inline uint32_t rmFeature() const noexcept { return _rmFeature; } //! \} @@ -505,49 +636,43 @@ struct InstRWInfo { //! \} }; -// ============================================================================ -// [asmjit::InstAPI] -// ============================================================================ - -//! Instruction API. -namespace InstAPI { - //! Validation flags that can be used with \ref InstAPI::validate(). -enum ValidationFlags : uint32_t { +enum class ValidationFlags : uint32_t { + //! No flags. + kNone = 0, //! Allow virtual registers in the instruction. - kValidationFlagVirtRegs = 0x01u + kEnableVirtRegs = 0x01u }; +ASMJIT_DEFINE_ENUM_FLAGS(ValidationFlags) + +//! Instruction API. +namespace InstAPI { #ifndef ASMJIT_NO_TEXT -//! Appends the name of the instruction specified by `instId` and `instOptions` -//! into the `output` string. +//! Appends the name of the instruction specified by `instId` and `instOptions` into the `output` string. //! -//! \note Instruction options would only affect instruction prefix & suffix, -//! other options would be ignored. If `instOptions` is zero then only raw -//! instruction name (without any additional text) will be appended. -ASMJIT_API Error instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept; - -//! Parses an instruction name in the given string `s`. Length is specified -//! by `len` argument, which can be `SIZE_MAX` if `s` is known to be null -//! terminated. +//! \note Instruction options would only affect instruction prefix & suffix, other options would be ignored. +//! If `instOptions` is zero then only raw instruction name (without any additional text) will be appended. +ASMJIT_API Error instIdToString(Arch arch, InstId instId, String& output) noexcept; + +//! Parses an instruction name in the given string `s`. Length is specified by `len` argument, which can be +//! `SIZE_MAX` if `s` is known to be null terminated. //! -//! Returns the parsed instruction id or \ref BaseInst::kIdNone if no such -//! instruction exists. -ASMJIT_API uint32_t stringToInstId(uint32_t arch, const char* s, size_t len) noexcept; +//! Returns the parsed instruction id or \ref BaseInst::kIdNone if no such instruction exists. +ASMJIT_API InstId stringToInstId(Arch arch, const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -//! Validates the given instruction considering the validation `flags`, see -//! \ref ValidationFlags. -ASMJIT_API Error validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags = 0) noexcept; +//! Validates the given instruction considering the given `validationFlags`. +ASMJIT_API Error validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags = ValidationFlags::kNone) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION //! Gets Read/Write information of the given instruction. -ASMJIT_API Error queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; +ASMJIT_API Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; //! Gets CPU features required by the given instruction. -ASMJIT_API Error queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept; +ASMJIT_API Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; #endif // !ASMJIT_NO_INTROSPECTION } // {InstAPI} diff --git a/src/asmjit/core/jitallocator.cpp b/src/asmjit/core/jitallocator.cpp index b576e21..19fbe4b 100644 --- a/src/asmjit/core/jitallocator.cpp +++ b/src/asmjit/core/jitallocator.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_JIT @@ -35,24 +17,24 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::JitAllocator - Constants] -// ============================================================================ +// JitAllocator - Constants +// ======================== -enum JitAllocatorConstants : uint32_t { - //! Number of pools to use when `JitAllocator::kOptionUseMultiplePools` is set. - //! - //! Each pool increases granularity twice to make memory management more - //! efficient. Ideal number of pools appears to be 3 to 4 as it distributes - //! small and large functions properly. - kJitAllocatorMultiPoolCount = 3, +//! Number of pools to use when `JitAllocatorOptions::kUseMultiplePools` is set. +//! +//! Each pool increases granularity twice to make memory management more +//! efficient. Ideal number of pools appears to be 3 to 4 as it distributes +//! small and large functions properly. +static constexpr uint32_t kJitAllocatorMultiPoolCount = 3; - //! Minimum granularity (and the default granularity for pool #0). - kJitAllocatorBaseGranularity = 64, +//! Minimum granularity (and the default granularity for pool #0). +static constexpr uint32_t kJitAllocatorBaseGranularity = 64; - //! Maximum block size (32MB). - kJitAllocatorMaxBlockSize = 1024 * 1024 * 32 -}; +//! Maximum block size (32MB). +static constexpr uint32_t kJitAllocatorMaxBlockSize = 1024 * 1024 * 32; + +// JitAllocator - Fill Pattern +// =========================== static inline uint32_t JitAllocator_defaultFillPattern() noexcept { // X86 and X86_64 - 4x 'int3' instruction. @@ -63,9 +45,8 @@ static inline uint32_t JitAllocator_defaultFillPattern() noexcept { return 0u; } -// ============================================================================ -// [asmjit::BitVectorRangeIterator] -// ============================================================================ +// JitAllocator - BitVectorRangeIterator +// ===================================== template<typename T, uint32_t B> class BitVectorRangeIterator { @@ -78,19 +59,19 @@ public: enum : uint32_t { kBitWordSize = Support::bitSizeOf<T>() }; enum : T { kXorMask = B == 0 ? Support::allOnes<T>() : T(0) }; - ASMJIT_INLINE BitVectorRangeIterator(const T* data, size_t numBitWords) noexcept { + ASMJIT_FORCE_INLINE BitVectorRangeIterator(const T* data, size_t numBitWords) noexcept { init(data, numBitWords); } - ASMJIT_INLINE BitVectorRangeIterator(const T* data, size_t numBitWords, size_t start, size_t end) noexcept { + ASMJIT_FORCE_INLINE BitVectorRangeIterator(const T* data, size_t numBitWords, size_t start, size_t end) noexcept { init(data, numBitWords, start, end); } - ASMJIT_INLINE void init(const T* data, size_t numBitWords) noexcept { + ASMJIT_FORCE_INLINE void init(const T* data, size_t numBitWords) noexcept { init(data, numBitWords, 0, numBitWords * kBitWordSize); } - ASMJIT_INLINE void init(const T* data, size_t numBitWords, size_t start, size_t end) noexcept { + ASMJIT_FORCE_INLINE void init(const T* data, size_t numBitWords, size_t start, size_t end) noexcept { ASMJIT_ASSERT(numBitWords >= (end + kBitWordSize - 1) / kBitWordSize); DebugUtils::unused(numBitWords); @@ -107,7 +88,7 @@ public: _bitWord = bitWord; } - ASMJIT_INLINE bool nextRange(size_t* rangeStart, size_t* rangeEnd, size_t rangeHint = std::numeric_limits<size_t>::max()) noexcept { + ASMJIT_FORCE_INLINE bool nextRange(size_t* rangeStart, size_t* rangeEnd, size_t rangeHint = std::numeric_limits<size_t>::max()) noexcept { // Skip all empty BitWords. while (_bitWord == 0) { _idx += kBitWordSize; @@ -153,9 +134,8 @@ public: } }; -// ============================================================================ -// [asmjit::JitAllocator - Pool] -// ============================================================================ +// JitAllocator - Pool +// =================== class JitAllocatorBlock; @@ -163,6 +143,27 @@ class JitAllocatorPool { public: ASMJIT_NONCOPYABLE(JitAllocatorPool) + //! Double linked list of blocks. + ZoneList<JitAllocatorBlock> blocks; + //! Where to start looking first. + JitAllocatorBlock* cursor; + + //! Count of blocks. + uint32_t blockCount; + //! Allocation granularity. + uint16_t granularity; + //! Log2(granularity). + uint8_t granularityLog2; + //! Count of empty blocks (either 0 or 1 as we won't keep more blocks empty). + uint8_t emptyBlockCount; + + //! Number of bits reserved across all blocks. + size_t totalAreaSize; + //! Number of bits used across all blocks. + size_t totalAreaUsed; + //! Overhead of all blocks (in bytes). + size_t totalOverheadBytes; + inline JitAllocatorPool(uint32_t granularity) noexcept : blocks(), cursor(nullptr), @@ -190,32 +191,10 @@ public: using namespace Support; return alignUp<size_t>(areaSize, kBitWordSizeInBits) / kBitWordSizeInBits; } - - //! Double linked list of blocks. - ZoneList<JitAllocatorBlock> blocks; - //! Where to start looking first. - JitAllocatorBlock* cursor; - - //! Count of blocks. - uint32_t blockCount; - //! Allocation granularity. - uint16_t granularity; - //! Log2(granularity). - uint8_t granularityLog2; - //! Count of empty blocks (either 0 or 1 as we won't keep more blocks empty). - uint8_t emptyBlockCount; - - //! Number of bits reserved across all blocks. - size_t totalAreaSize; - //! Number of bits used across all blocks. - size_t totalAreaUsed; - //! Overhead of all blocks (in bytes). - size_t totalOverheadBytes; }; -// ============================================================================ -// [asmjit::JitAllocator - Block] -// ============================================================================ +// JitAllocator - Block +// ==================== class JitAllocatorBlock : public ZoneTreeNodeT<JitAllocatorBlock>, public ZoneListNode<JitAllocatorBlock> { @@ -280,7 +259,7 @@ public: inline JitAllocatorPool* pool() const noexcept { return _pool; } - inline uint8_t* roPtr() const noexcept { return static_cast<uint8_t*>(_mapping.ro); } + inline uint8_t* rxPtr() const noexcept { return static_cast<uint8_t*>(_mapping.rx); } inline uint8_t* rwPtr() const noexcept { return static_cast<uint8_t*>(_mapping.rw); } inline bool hasFlag(uint32_t f) const noexcept { return (_flags & f) != 0; } @@ -376,30 +355,25 @@ public: } // RBTree default CMP uses '<' and '>' operators. - inline bool operator<(const JitAllocatorBlock& other) const noexcept { return roPtr() < other.roPtr(); } - inline bool operator>(const JitAllocatorBlock& other) const noexcept { return roPtr() > other.roPtr(); } + inline bool operator<(const JitAllocatorBlock& other) const noexcept { return rxPtr() < other.rxPtr(); } + inline bool operator>(const JitAllocatorBlock& other) const noexcept { return rxPtr() > other.rxPtr(); } // Special implementation for querying blocks by `key`, which must be in `[BlockPtr, BlockPtr + BlockSize)` range. - inline bool operator<(const uint8_t* key) const noexcept { return roPtr() + _blockSize <= key; } - inline bool operator>(const uint8_t* key) const noexcept { return roPtr() > key; } + inline bool operator<(const uint8_t* key) const noexcept { return rxPtr() + _blockSize <= key; } + inline bool operator>(const uint8_t* key) const noexcept { return rxPtr() > key; } }; -// ============================================================================ -// [asmjit::JitAllocator - PrivateImpl] -// ============================================================================ +// JitAllocator - PrivateImpl +// ========================== class JitAllocatorPrivateImpl : public JitAllocator::Impl { public: - inline JitAllocatorPrivateImpl(JitAllocatorPool* pools, size_t poolCount) noexcept - : JitAllocator::Impl {}, - pools(pools), - poolCount(poolCount) {} - inline ~JitAllocatorPrivateImpl() noexcept {} - //! Lock for thread safety. mutable Lock lock; //! System page size (also a minimum block size). uint32_t pageSize; + //! Number of active allocations. + size_t allocationCount; //! Blocks from all pools in RBTree. ZoneTree<JitAllocatorBlock> tree; @@ -407,14 +381,21 @@ public: JitAllocatorPool* pools; //! Number of allocator pools. size_t poolCount; + + inline JitAllocatorPrivateImpl(JitAllocatorPool* pools, size_t poolCount) noexcept + : JitAllocator::Impl {}, + pageSize(0), + allocationCount(0), + pools(pools), + poolCount(poolCount) {} + inline ~JitAllocatorPrivateImpl() noexcept {} }; static const JitAllocator::Impl JitAllocatorImpl_none {}; static const JitAllocator::CreateParams JitAllocatorParams_none {}; -// ============================================================================ -// [asmjit::JitAllocator - Utilities] -// ============================================================================ +// JitAllocator - Utilities +// ======================== static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator::CreateParams* params) noexcept { VirtMem::Info vmInfo = VirtMem::info(); @@ -422,14 +403,14 @@ static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator:: if (!params) params = &JitAllocatorParams_none; - uint32_t options = params->options; + JitAllocatorOptions options = params->options; uint32_t blockSize = params->blockSize; uint32_t granularity = params->granularity; uint32_t fillPattern = params->fillPattern; // Setup pool count to [1..3]. size_t poolCount = 1; - if (options & JitAllocator::kOptionUseMultiplePools) + if (Support::test(options, JitAllocatorOptions::kUseMultiplePools)) poolCount = kJitAllocatorMultiPoolCount;; // Setup block size [64kB..256MB]. @@ -441,7 +422,7 @@ static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator:: granularity = kJitAllocatorBaseGranularity; // Setup fill-pattern. - if (!(options & JitAllocator::kOptionCustomFillPattern)) + if (uint32_t(options & JitAllocatorOptions::kCustomFillPattern) == 0) fillPattern = JitAllocator_defaultFillPattern(); size_t size = sizeof(JitAllocatorPrivateImpl) + sizeof(JitAllocatorPool) * poolCount; @@ -533,26 +514,32 @@ static JitAllocatorBlock* JitAllocatorImpl_newBlock(JitAllocatorPrivateImpl* imp uint32_t blockFlags = 0; if (bitWords != nullptr) { - if (impl->options & JitAllocator::kOptionUseDualMapping) { - err = VirtMem::allocDualMapping(&virtMem, blockSize, VirtMem::kAccessRWX); + if (Support::test(impl->options, JitAllocatorOptions::kUseDualMapping)) { + err = VirtMem::allocDualMapping(&virtMem, blockSize, VirtMem::MemoryFlags::kAccessRWX); blockFlags |= JitAllocatorBlock::kFlagDualMapped; } else { - err = VirtMem::alloc(&virtMem.ro, blockSize, VirtMem::kAccessRWX); - virtMem.rw = virtMem.ro; + err = VirtMem::alloc(&virtMem.rx, blockSize, VirtMem::MemoryFlags::kAccessRWX); + virtMem.rw = virtMem.rx; } } // Out of memory. if (ASMJIT_UNLIKELY(!block || !bitWords || err != kErrorOk)) { - if (bitWords) ::free(bitWords); - if (block) ::free(block); + if (bitWords) + ::free(bitWords); + + if (block) + ::free(block); + return nullptr; } // Fill the memory if the secure mode is enabled. - if (impl->options & JitAllocator::kOptionFillUnusedMemory) + if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) { + VirtMem::ProtectJitReadWriteScope scope(virtMem.rw, blockSize); JitAllocatorImpl_fillPattern(virtMem.rw, impl->fillPattern, blockSize); + } memset(bitWords, 0, size_t(numBitWords) * 2 * sizeof(BitWord)); return new(block) JitAllocatorBlock(pool, virtMem, blockSize, blockFlags, bitWords, bitWords + numBitWords, areaSize); @@ -564,7 +551,7 @@ static void JitAllocatorImpl_deleteBlock(JitAllocatorPrivateImpl* impl, JitAlloc if (block->hasFlag(JitAllocatorBlock::kFlagDualMapped)) VirtMem::releaseDualMapping(&block->_mapping, block->blockSize()); else - VirtMem::release(block->roPtr(), block->blockSize()); + VirtMem::release(block->rxPtr(), block->blockSize()); ::free(block->_usedBitVector); ::free(block); @@ -603,26 +590,31 @@ static void JitAllocatorImpl_removeBlock(JitAllocatorPrivateImpl* impl, JitAlloc } static void JitAllocatorImpl_wipeOutBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool(); - if (block->hasFlag(JitAllocatorBlock::kFlagEmpty)) return; + JitAllocatorPool* pool = block->pool(); uint32_t areaSize = block->areaSize(); uint32_t granularity = pool->granularity; size_t numBitWords = pool->bitWordCountFromAreaSize(areaSize); - if (impl->options & JitAllocator::kOptionFillUnusedMemory) { + VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite); + if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) { uint8_t* rwPtr = block->rwPtr(); - for (size_t i = 0; i < numBitWords; i++) { - Support::BitWordIterator<Support::BitWord> it(block->_usedBitVector[i]); - while (it.hasNext()) { - size_t index = it.next(); - JitAllocatorImpl_fillPattern(rwPtr + index * granularity , impl->fillPattern, granularity); - } - rwPtr += Support::bitSizeOf<Support::BitWord>() * granularity; + BitVectorRangeIterator<Support::BitWord, 0> it(block->_usedBitVector, pool->bitWordCountFromAreaSize(block->areaSize())); + + size_t rangeStart; + size_t rangeEnd; + + while (it.nextRange(&rangeStart, &rangeEnd)) { + uint8_t* spanPtr = rwPtr + rangeStart * granularity; + size_t spanSize = (rangeEnd - rangeStart) * granularity; + + JitAllocatorImpl_fillPattern(spanPtr, impl->fillPattern, spanSize); + VirtMem::flushInstructionCache(spanPtr, spanSize); } } + VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute); memset(block->_usedBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); memset(block->_stopBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); @@ -635,9 +627,8 @@ static void JitAllocatorImpl_wipeOutBlock(JitAllocatorPrivateImpl* impl, JitAllo block->clearFlags(JitAllocatorBlock::kFlagDirty); } -// ============================================================================ -// [asmjit::JitAllocator - Construction / Destruction] -// ============================================================================ +// JitAllocator - Construction & Destruction +// ========================================= JitAllocator::JitAllocator(const CreateParams* params) noexcept { _impl = JitAllocatorImpl_new(params); @@ -649,15 +640,14 @@ JitAllocator::~JitAllocator() noexcept { if (_impl == &JitAllocatorImpl_none) return; - reset(Globals::kResetHard); + reset(ResetPolicy::kHard); JitAllocatorImpl_destroy(static_cast<JitAllocatorPrivateImpl*>(_impl)); } -// ============================================================================ -// [asmjit::JitAllocator - Reset] -// ============================================================================ +// JitAllocator - Reset +// ==================== -void JitAllocator::reset(uint32_t resetPolicy) noexcept { +void JitAllocator::reset(ResetPolicy resetPolicy) noexcept { if (_impl == &JitAllocatorImpl_none) return; @@ -670,7 +660,7 @@ void JitAllocator::reset(uint32_t resetPolicy) noexcept { JitAllocatorBlock* block = pool.blocks.first(); JitAllocatorBlock* blockToKeep = nullptr; - if (resetPolicy != Globals::kResetHard && !(impl->options & kOptionImmediateRelease)) { + if (resetPolicy != ResetPolicy::kHard && uint32_t(impl->options & JitAllocatorOptions::kImmediateRelease) == 0) { blockToKeep = block; block = block->next(); } @@ -693,9 +683,8 @@ void JitAllocator::reset(uint32_t resetPolicy) noexcept { } } -// ============================================================================ -// [asmjit::JitAllocator - Statistics] -// ============================================================================ +// JitAllocator - Statistics +// ========================= JitAllocator::Statistics JitAllocator::statistics() const noexcept { Statistics statistics; @@ -713,23 +702,24 @@ JitAllocator::Statistics JitAllocator::statistics() const noexcept { statistics._usedSize += size_t(pool.totalAreaUsed) * pool.granularity; statistics._overheadSize += size_t(pool.totalOverheadBytes); } + + statistics._allocationCount = impl->allocationCount; } return statistics; } -// ============================================================================ -// [asmjit::JitAllocator - Alloc / Release] -// ============================================================================ +// JitAllocator - Alloc & Release +// ============================== -Error JitAllocator::alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcept { +Error JitAllocator::alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcept { if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) return DebugUtils::errored(kErrorNotInitialized); JitAllocatorPrivateImpl* impl = static_cast<JitAllocatorPrivateImpl*>(_impl); constexpr uint32_t kNoIndex = std::numeric_limits<uint32_t>::max(); - *roPtrOut = nullptr; + *rxPtrOut = nullptr; *rwPtrOut = nullptr; // Align to the minimum granularity by default. @@ -815,49 +805,56 @@ Error JitAllocator::alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcep } // Update statistics. + impl->allocationCount++; block->markAllocatedArea(areaIndex, areaIndex + areaSize); // Return a pointer to the allocated memory. size_t offset = pool->byteSizeFromAreaSize(areaIndex); ASMJIT_ASSERT(offset <= block->blockSize() - size); - *roPtrOut = block->roPtr() + offset; + *rxPtrOut = block->rxPtr() + offset; *rwPtrOut = block->rwPtr() + offset; return kErrorOk; } -Error JitAllocator::release(void* roPtr) noexcept { +Error JitAllocator::release(void* rxPtr) noexcept { if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) return DebugUtils::errored(kErrorNotInitialized); - if (ASMJIT_UNLIKELY(!roPtr)) + if (ASMJIT_UNLIKELY(!rxPtr)) return DebugUtils::errored(kErrorInvalidArgument); JitAllocatorPrivateImpl* impl = static_cast<JitAllocatorPrivateImpl*>(_impl); LockGuard guard(impl->lock); - JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(roPtr)); + JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(rxPtr)); if (ASMJIT_UNLIKELY(!block)) return DebugUtils::errored(kErrorInvalidState); // Offset relative to the start of the block. JitAllocatorPool* pool = block->pool(); - size_t offset = (size_t)((uint8_t*)roPtr - block->roPtr()); + size_t offset = (size_t)((uint8_t*)rxPtr - block->rxPtr()); // The first bit representing the allocated area and its size. uint32_t areaIndex = uint32_t(offset >> pool->granularityLog2); uint32_t areaEnd = uint32_t(Support::bitVectorIndexOf(block->_stopBitVector, areaIndex, true)) + 1; uint32_t areaSize = areaEnd - areaIndex; + impl->allocationCount--; block->markReleasedArea(areaIndex, areaEnd); // Fill the released memory if the secure mode is enabled. - if (impl->options & kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern(block->rwPtr() + areaIndex * pool->granularity, impl->fillPattern, areaSize * pool->granularity); + if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) { + uint8_t* spanPtr = block->rwPtr() + areaIndex * pool->granularity; + size_t spanSize = areaSize * pool->granularity; + + VirtMem::ProtectJitReadWriteScope scope(spanPtr, spanSize); + JitAllocatorImpl_fillPattern(spanPtr, impl->fillPattern, spanSize); + } // Release the whole block if it became empty. if (block->areaUsed() == 0) { - if (pool->emptyBlockCount || (impl->options & kOptionImmediateRelease)) { + if (pool->emptyBlockCount || Support::test(impl->options, JitAllocatorOptions::kImmediateRelease)) { JitAllocatorImpl_removeBlock(impl, block); JitAllocatorImpl_deleteBlock(impl, block); } @@ -869,26 +866,26 @@ Error JitAllocator::release(void* roPtr) noexcept { return kErrorOk; } -Error JitAllocator::shrink(void* roPtr, size_t newSize) noexcept { +Error JitAllocator::shrink(void* rxPtr, size_t newSize) noexcept { if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) return DebugUtils::errored(kErrorNotInitialized); - if (ASMJIT_UNLIKELY(!roPtr)) + if (ASMJIT_UNLIKELY(!rxPtr)) return DebugUtils::errored(kErrorInvalidArgument); if (ASMJIT_UNLIKELY(newSize == 0)) - return release(roPtr); + return release(rxPtr); JitAllocatorPrivateImpl* impl = static_cast<JitAllocatorPrivateImpl*>(_impl); LockGuard guard(impl->lock); - JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(roPtr)); + JitAllocatorBlock* block = impl->tree.get(static_cast<uint8_t*>(rxPtr)); if (ASMJIT_UNLIKELY(!block)) return DebugUtils::errored(kErrorInvalidArgument); // Offset relative to the start of the block. JitAllocatorPool* pool = block->pool(); - size_t offset = (size_t)((uint8_t*)roPtr - block->roPtr()); + size_t offset = (size_t)((uint8_t*)rxPtr - block->rxPtr()); // The first bit representing the allocated area and its size. uint32_t areaStart = uint32_t(offset >> pool->granularityLog2); @@ -905,16 +902,15 @@ Error JitAllocator::shrink(void* roPtr, size_t newSize) noexcept { block->markShrunkArea(areaStart + areaShrunkSize, areaEnd); // Fill released memory if the secure mode is enabled. - if (impl->options & kOptionFillUnusedMemory) + if (Support::test(impl->options, JitAllocatorOptions::kFillUnusedMemory)) JitAllocatorImpl_fillPattern(block->rwPtr() + (areaStart + areaShrunkSize) * pool->granularity, fillPattern(), areaDiff * pool->granularity); } return kErrorOk; } -// ============================================================================ -// [asmjit::JitAllocator - Unit] -// ============================================================================ +// JitAllocator - Tests +// ==================== #if defined(ASMJIT_TEST) // A pseudo random number generator based on a paper by Sebastiano Vigna: @@ -1034,14 +1030,14 @@ public: } void* alloc(size_t size) noexcept { - void* roPtr; + void* rxPtr; void* rwPtr; - Error err = _allocator.alloc(&roPtr, &rwPtr, size); + Error err = _allocator.alloc(&rxPtr, &rwPtr, size); EXPECT(err == kErrorOk, "JitAllocator failed to allocate %zu bytes\n", size); - _insert(roPtr, size); - return roPtr; + _insert(rxPtr, size); + return rxPtr; } void release(void* p) noexcept { @@ -1099,7 +1095,7 @@ static void BitVectorRangeIterator_testRandom(Random& rnd, size_t count) noexcep } for (size_t j = 0; j < kPatternSize; j++) { - EXPECT(in[j] == out[j], "Invalid pattern detected at [%zu] (%llX != %llX", j, (unsigned long long)in[j], (unsigned long long)out[j]); + EXPECT(in[j] == out[j], "Invalid pattern detected at [%zu] (%llX != %llX)", j, (unsigned long long)in[j], (unsigned long long)out[j]); } } } @@ -1109,20 +1105,20 @@ UNIT(jit_allocator) { struct TestParams { const char* name; - uint32_t options; + JitAllocatorOptions options; uint32_t blockSize; uint32_t granularity; }; static TestParams testParams[] = { - { "Default", 0, 0, 0 }, - { "16MB blocks", 0, 16 * 1024 * 1024, 0 }, - { "256B granularity", 0, 0, 256 }, - { "kOptionUseDualMapping", JitAllocator::kOptionUseDualMapping, 0, 0 }, - { "kOptionUseMultiplePools", JitAllocator::kOptionUseMultiplePools, 0, 0 }, - { "kOptionFillUnusedMemory", JitAllocator::kOptionFillUnusedMemory, 0, 0 }, - { "kOptionImmediateRelease", JitAllocator::kOptionImmediateRelease, 0, 0 }, - { "kOptionUseDualMapping | kOptionFillUnusedMemory", JitAllocator::kOptionUseDualMapping | JitAllocator::kOptionFillUnusedMemory, 0, 0 } + { "Default", JitAllocatorOptions::kNone, 0, 0 }, + { "16MB blocks", JitAllocatorOptions::kNone, 16 * 1024 * 1024, 0 }, + { "256B granularity", JitAllocatorOptions::kNone, 0, 256 }, + { "kUseDualMapping", JitAllocatorOptions::kUseDualMapping, 0, 0 }, + { "kUseMultiplePools", JitAllocatorOptions::kUseMultiplePools, 0, 0 }, + { "kFillUnusedMemory", JitAllocatorOptions::kFillUnusedMemory, 0, 0 }, + { "kImmediateRelease", JitAllocatorOptions::kImmediateRelease, 0, 0 }, + { "kUseDualMapping | kFillUnusedMemory", JitAllocatorOptions::kUseDualMapping | JitAllocatorOptions::kFillUnusedMemory, 0, 0 } }; INFO("BitVectorRangeIterator<uint32_t>"); diff --git a/src/asmjit/core/jitallocator.h b/src/asmjit/core/jitallocator.h index c9eea2a..e8fe695 100644 --- a/src/asmjit/core/jitallocator.h +++ b/src/asmjit/core/jitallocator.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_JITALLOCATOR_H_INCLUDED #define ASMJIT_CORE_JITALLOCATOR_H_INCLUDED @@ -35,37 +17,67 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_virtual_memory //! \{ -// ============================================================================ -// [asmjit::JitAllocator] -// ============================================================================ +//! Options used by \ref JitAllocator. +enum class JitAllocatorOptions : uint32_t { + //! No options. + kNone = 0, + + //! Enables the use of an anonymous memory-mapped memory that is mapped into two buffers having a different pointer. + //! The first buffer has read and execute permissions and the second buffer has read+write permissions. + //! + //! See \ref VirtMem::allocDualMapping() for more details about this feature. + kUseDualMapping = 0x00000001u, + + //! Enables the use of multiple pools with increasing granularity instead of a single pool. This flag would enable + //! 3 internal pools in total having 64, 128, and 256 bytes granularity. + //! + //! This feature is only recommended for users that generate a lot of code and would like to minimize the overhead + //! of `JitAllocator` itself by having blocks of different allocation granularities. Using this feature only for + //! few allocations won't pay off as the allocator may need to create more blocks initially before it can take the + //! advantage of variable block granularity. + kUseMultiplePools = 0x00000002u, + + //! Always fill reserved memory by a fill-pattern. + //! + //! Causes a new block to be cleared by the fill pattern and freshly released memory to be cleared before making + //! it ready for another use. + kFillUnusedMemory = 0x00000004u, + + //! When this flag is set the allocator would immediately release unused blocks during `release()` or `reset()`. + //! When this flag is not set the allocator would keep one empty block in each pool to prevent excessive virtual + //! memory allocations and deallocations in border cases, which involve constantly allocating and deallocating a + //! single block caused by repetitive calling `alloc()` and `release()` when the allocator has either no blocks + //! or have all blocks fully occupied. + kImmediateRelease = 0x00000008u, + + //! Use a custom fill pattern, must be combined with `kFlagFillUnusedMemory`. + kCustomFillPattern = 0x10000000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(JitAllocatorOptions) //! A simple implementation of memory manager that uses `asmjit::VirtMem` //! functions to manage virtual memory for JIT compiled code. //! //! Implementation notes: //! -//! - Granularity of allocated blocks is different than granularity for a typical -//! C malloc. In addition, the allocator can use several memory pools having a -//! different granularity to minimize the maintenance overhead. Multiple pools +//! - Granularity of allocated blocks is different than granularity for a typical C malloc. In addition, the allocator +//! can use several memory pools having a different granularity to minimize the maintenance overhead. Multiple pools //! feature requires `kFlagUseMultiplePools` flag to be set. //! -//! - The allocator doesn't store any information in executable memory, instead, -//! the implementation uses two bit-vectors to manage allocated memory of each -//! allocator-block. The first bit-vector called 'used' is used to track used -//! memory (where each bit represents memory size defined by granularity) and -//! the second bit vector called 'stop' is used as a sentinel to mark where -//! the allocated area ends. +//! - The allocator doesn't store any information in executable memory, instead, the implementation uses two +//! bit-vectors to manage allocated memory of each allocator-block. The first bit-vector called 'used' is used to +//! track used memory (where each bit represents memory size defined by granularity) and the second bit vector called +//! 'stop' is used as a sentinel to mark where the allocated area ends. //! -//! - Internally, the allocator also uses RB tree to keep track of all blocks -//! across all pools. Each inserted block is added to the tree so it can be -//! matched fast during `release()` and `shrink()`. +//! - Internally, the allocator also uses RB tree to keep track of all blocks across all pools. Each inserted block is +//! added to the tree so it can be matched fast during `release()` and `shrink()`. class JitAllocator { public: ASMJIT_NONCOPYABLE(JitAllocator) struct Impl { - //! Allocator options, see \ref JitAllocator::Options. - uint32_t options; + //! Allocator options. + JitAllocatorOptions options; //! Base block size (0 if the allocator is not initialized). uint32_t blockSize; //! Base granularity (0 if the allocator is not initialized). @@ -77,45 +89,6 @@ public: //! Allocator implementation (private). Impl* _impl; - enum Options : uint32_t { - //! Enables the use of an anonymous memory-mapped memory that is mapped into - //! two buffers having a different pointer. The first buffer has read and - //! execute permissions and the second buffer has read+write permissions. - //! - //! See \ref VirtMem::allocDualMapping() for more details about this feature. - kOptionUseDualMapping = 0x00000001u, - - //! Enables the use of multiple pools with increasing granularity instead of - //! a single pool. This flag would enable 3 internal pools in total having - //! 64, 128, and 256 bytes granularity. - //! - //! This feature is only recommended for users that generate a lot of code - //! and would like to minimize the overhead of `JitAllocator` itself by - //! having blocks of different allocation granularities. Using this feature - //! only for few allocations won't pay off as the allocator may need to - //! create more blocks initially before it can take the advantage of - //! variable block granularity. - kOptionUseMultiplePools = 0x00000002u, - - //! Always fill reserved memory by a fill-pattern. - //! - //! Causes a new block to be cleared by the fill pattern and freshly - //! released memory to be cleared before making it ready for another use. - kOptionFillUnusedMemory = 0x00000004u, - - //! When this flag is set the allocator would immediately release unused - //! blocks during `release()` or `reset()`. When this flag is not set the - //! allocator would keep one empty block in each pool to prevent excessive - //! virtual memory allocations and deallocations in border cases, which - //! involve constantly allocating and deallocating a single block caused - //! by repetitive calling `alloc()` and `release()` when the allocator has - //! either no blocks or have all blocks fully occupied. - kOptionImmediateRelease = 0x00000008u, - - //! Use a custom fill pattern, must be combined with `kFlagFillUnusedMemory`. - kOptionCustomFillPattern = 0x10000000u - }; - //! \name Construction & Destruction //! \{ @@ -132,39 +105,35 @@ public: //! JitAllocator allocator(¶ms); //! ``` struct CreateParams { - //! Allocator options, see \ref JitAllocator::Options. + //! Allocator options. //! //! No options are used by default. - uint32_t options; + JitAllocatorOptions options = JitAllocatorOptions::kNone; //! Base size of a single block in bytes (default 64kB). //! - //! \remarks Block size must be equal or greater to page size and must be - //! power of 2. If the input is not valid then the default block size will - //! be used instead. - uint32_t blockSize; + //! \remarks Block size must be equal to or greater than page size and must be power of 2. If the input is not + //! valid then the default block size will be used instead. + uint32_t blockSize = 0; - //! Base granularity (and also natural alignment) of allocations in bytes - //! (default 64). + //! Base granularity (and also natural alignment) of allocations in bytes (default 64). //! - //! Since the `JitAllocator` uses bit-arrays to mark used memory the - //! granularity also specifies how many bytes correspond to a single bit in - //! such bit-array. Higher granularity means more waste of virtual memory - //! (as it increases the natural alignment), but smaller bit-arrays as less - //! bits would be required per a single block. - uint32_t granularity; + //! Since the `JitAllocator` uses bit-arrays to mark used memory the granularity also specifies how many bytes + //! correspond to a single bit in such bit-array. Higher granularity means more waste of virtual memory (as it + //! increases the natural alignment), but smaller bit-arrays as less bits would be required per a single block. + uint32_t granularity = 0; //! Patter to use to fill unused memory. //! - //! Only used if \ref kOptionCustomFillPattern is set. - uint32_t fillPattern; + //! Only used if \ref JitAllocatorOptions::kCustomFillPattern is set. + uint32_t fillPattern = 0; // Reset the content of `CreateParams`. inline void reset() noexcept { memset(this, 0, sizeof(*this)); } }; //! Creates a `JitAllocator` instance. - explicit ASMJIT_API JitAllocator(const CreateParams* params = nullptr) noexcept; + ASMJIT_API explicit JitAllocator(const CreateParams* params = nullptr) noexcept; //! Destroys the `JitAllocator` instance and release all blocks held. ASMJIT_API ~JitAllocator() noexcept; @@ -172,10 +141,9 @@ public: //! Free all allocated memory - makes all pointers returned by `alloc()` invalid. //! - //! \remarks This function is not thread-safe as it's designed to be used when - //! nobody else is using allocator. The reason is that there is no point of - //1 calling `reset()` when the allocator is still in use. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; + //! \remarks This function is not thread-safe as it's designed to be used when nobody else is using allocator. + //! The reason is that there is no point of calling `reset()` when the allocator is still in use. + ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept; //! \} @@ -183,9 +151,9 @@ public: //! \{ //! Returns allocator options, see `Flags`. - inline uint32_t options() const noexcept { return _impl->options; } + inline JitAllocatorOptions options() const noexcept { return _impl->options; } //! Tests whether the allocator has the given `option` set. - inline bool hasOption(uint32_t option) const noexcept { return (_impl->options & option) != 0; } + inline bool hasOption(JitAllocatorOptions option) const noexcept { return uint32_t(_impl->options & option) != 0; } //! Returns a base block size (a minimum size of block that the allocator would allocate). inline uint32_t blockSize() const noexcept { return _impl->blockSize; } @@ -199,20 +167,31 @@ public: //! \name Alloc & Release //! \{ - //! Allocate `size` bytes of virtual memory. + //! Allocates a new memory block of the requested `size`. //! - //! \remarks This function is thread-safe. - ASMJIT_API Error alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcept; + //! When the function is successful it stores two pointers in `rxPtrOut` and `rwPtrOut`. The pointers will be + //! different only if `kOptionUseDualMapping` was used to setup the allocator (in that case the `rxPtrOut` would + //! point to a Read+Execute region and `rwPtrOut` would point to a Read+Write region of the same memory-mapped block. + ASMJIT_API Error alloc(void** rxPtrOut, void** rwPtrOut, size_t size) noexcept; - //! Release a memory returned by `alloc()`. + //! Releases a memory block returned by `alloc()`. //! //! \remarks This function is thread-safe. - ASMJIT_API Error release(void* roPtr) noexcept; + ASMJIT_API Error release(void* rxPtr) noexcept; - //! Free extra memory allocated with `p` by restricting it to `newSize` size. + //! Frees extra memory allocated with `rxPtr` by shrinking it to the given `newSize`. //! //! \remarks This function is thread-safe. - ASMJIT_API Error shrink(void* roPtr, size_t newSize) noexcept; + ASMJIT_API Error shrink(void* rxPtr, size_t newSize) noexcept; + + //! Queries information about an allocated memory block that contains the given `rxPtr`. + //! + //! The function returns `kErrorOk` when `rxPtr` is matched and fills `rxPtrOut`, `rwPtrOut`, and `sizeOut` output + //! arguments. The returned `rxPtrOut` and `rwPtrOut` pointers point to the beginning of the block, and `sizeOut` + //! describes the total amount of bytes this allocation uses - `sizeOut` will always be aligned to the allocation + //! granularity, so for example if an allocation was 1 byte and the size granularity is 64, the returned `sizeOut` + //! will be 64 bytes, because that's what the allocator sees. + ASMJIT_API Error query(void* rxPtr, void** rxPtrOut, void** rwPtrOut, size_t* sizeOut) const noexcept; //! \} @@ -223,6 +202,8 @@ public: struct Statistics { //! Number of blocks `JitAllocator` maintains. size_t _blockCount; + //! Number of active allocations. + size_t _allocationCount; //! How many bytes are currently used / allocated. size_t _usedSize; //! How many bytes are currently reserved by the allocator. @@ -239,6 +220,8 @@ public: //! Returns count of blocks managed by `JitAllocator` at the moment. inline size_t blockCount() const noexcept { return _blockCount; } + //! Returns the number of active allocations. + inline size_t allocationCount() const noexcept { return _allocationCount; } //! Returns how many bytes are currently used. inline size_t usedSize() const noexcept { return _usedSize; } diff --git a/src/asmjit/core/jitruntime.cpp b/src/asmjit/core/jitruntime.cpp index a2b46d7..85fbdc4 100644 --- a/src/asmjit/core/jitruntime.cpp +++ b/src/asmjit/core/jitruntime.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_JIT @@ -29,44 +11,14 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::JitRuntime - Utilities] -// ============================================================================ - -// Only useful on non-x86 architectures. -static inline void JitRuntime_flushInstructionCache(const void* p, size_t size) noexcept { -#if ASMJIT_ARCH_X86 - DebugUtils::unused(p, size); -#else -# if defined(_WIN32) - // Windows has a built-in support in `kernel32.dll`. - ::FlushInstructionCache(::GetCurrentProcess(), p, size); -# elif defined(__GNUC__) - char* start = static_cast<char*>(const_cast<void*>(p)); - char* end = start + size; - __builtin___clear_cache(start, end); -# else - DebugUtils::unused(p, size); -# endif -#endif -} - -// ============================================================================ -// [asmjit::JitRuntime - Construction / Destruction] -// ============================================================================ - JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept : _allocator(params) { - _environment = hostEnvironment(); - _environment.setFormat(Environment::kFormatJIT); + _environment = Environment::host(); + _environment.setObjectFormat(ObjectFormat::kJIT); } JitRuntime::~JitRuntime() noexcept {} -// ============================================================================ -// [asmjit::JitRuntime - Interface] -// ============================================================================ - Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { *dst = nullptr; @@ -77,14 +29,14 @@ Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { if (ASMJIT_UNLIKELY(estimatedCodeSize == 0)) return DebugUtils::errored(kErrorNoCodeGenerated); - uint8_t* ro; + uint8_t* rx; uint8_t* rw; - ASMJIT_PROPAGATE(_allocator.alloc((void**)&ro, (void**)&rw, estimatedCodeSize)); + ASMJIT_PROPAGATE(_allocator.alloc((void**)&rx, (void**)&rw, estimatedCodeSize)); // Relocate the code. - Error err = code->relocateToBase(uintptr_t((void*)ro)); + Error err = code->relocateToBase(uintptr_t((void*)rx)); if (ASMJIT_UNLIKELY(err)) { - _allocator.release(ro); + _allocator.release(rx); return err; } @@ -92,26 +44,28 @@ Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { // in case that some relocations didn't require records in an address table. size_t codeSize = code->codeSize(); - for (Section* section : code->_sections) { - size_t offset = size_t(section->offset()); - size_t bufferSize = size_t(section->bufferSize()); - size_t virtualSize = size_t(section->virtualSize()); + if (codeSize < estimatedCodeSize) + _allocator.shrink(rx, codeSize); - ASMJIT_ASSERT(offset + bufferSize <= codeSize); - memcpy(rw + offset, section->data(), bufferSize); + { + VirtMem::ProtectJitReadWriteScope rwScope(rx, codeSize); - if (virtualSize > bufferSize) { - ASMJIT_ASSERT(offset + virtualSize <= codeSize); - memset(rw + offset + bufferSize, 0, virtualSize - bufferSize); - } - } + for (Section* section : code->_sections) { + size_t offset = size_t(section->offset()); + size_t bufferSize = size_t(section->bufferSize()); + size_t virtualSize = size_t(section->virtualSize()); - if (codeSize < estimatedCodeSize) - _allocator.shrink(ro, codeSize); + ASMJIT_ASSERT(offset + bufferSize <= codeSize); + memcpy(rw + offset, section->data(), bufferSize); - flush(ro, codeSize); - *dst = ro; + if (virtualSize > bufferSize) { + ASMJIT_ASSERT(offset + virtualSize <= codeSize); + memset(rw + offset + bufferSize, 0, virtualSize - bufferSize); + } + } + } + *dst = rx; return kErrorOk; } @@ -119,10 +73,6 @@ Error JitRuntime::_release(void* p) noexcept { return _allocator.release(p); } -void JitRuntime::flush(const void* p, size_t size) noexcept { - JitRuntime_flushInstructionCache(p, size); -} - ASMJIT_END_NAMESPACE #endif diff --git a/src/asmjit/core/jitruntime.h b/src/asmjit/core/jitruntime.h index 91880e6..6f35e21 100644 --- a/src/asmjit/core/jitruntime.h +++ b/src/asmjit/core/jitruntime.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_JITRUNTIME_H_INCLUDED #define ASMJIT_CORE_JITRUNTIME_H_INCLUDED @@ -38,10 +20,6 @@ class CodeHolder; //! \addtogroup asmjit_virtual_memory //! \{ -// ============================================================================ -// [asmjit::JitRuntime] -// ============================================================================ - //! JIT execution runtime is a special `Target` that is designed to store and //! execute the generated code. class ASMJIT_VIRTAPI JitRuntime : public Target { @@ -55,11 +33,11 @@ public: //! \{ //! Creates a `JitRuntime` instance. - explicit ASMJIT_API JitRuntime(const JitAllocator::CreateParams* params = nullptr) noexcept; + ASMJIT_API explicit JitRuntime(const JitAllocator::CreateParams* params = nullptr) noexcept; //! Destroys the `JitRuntime` instance. ASMJIT_API virtual ~JitRuntime() noexcept; - inline void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept { + inline void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept { _allocator.reset(resetPolicy); } @@ -79,12 +57,10 @@ public: // NOTE: To allow passing function pointers to `add()` and `release()` the // virtual methods are prefixed with `_` and called from templates instead. - //! Allocates memory needed for a code stored in the `CodeHolder` and relocates - //! the code to the pointer allocated. + //! Allocates memory needed for a code stored in the `CodeHolder` and relocates the code to the pointer allocated. //! - //! The beginning of the memory allocated for the function is returned in `dst`. - //! If failed `Error` code is returned and `dst` is explicitly set to `nullptr` - //! (this means that you don't have to set it to null before calling `add()`). + //! The beginning of the memory allocated for the function is returned in `dst`. If failed `Error` code is returned + //! and `dst` is explicitly set to `nullptr` (this means that you don't have to set it to null before calling `add()`). template<typename Func> inline Error add(Func* dst, CodeHolder* code) noexcept { return _add(Support::ptr_cast_impl<void**, Func*>(dst), code); @@ -102,19 +78,6 @@ public: //! Type-unsafe version of `release()`. ASMJIT_API virtual Error _release(void* p) noexcept; - //! Flushes an instruction cache. - //! - //! This member function is called after the code has been copied to the - //! destination buffer. It is only useful for JIT code generation as it - //! causes a flush of the processor's cache. - //! - //! Flushing is basically a NOP under X86, but is needed by architectures - //! that do not have a transparent instruction cache like ARM. - //! - //! This function can also be overridden to improve compatibility with tools - //! such as Valgrind, however, it's not an official part of AsmJit. - ASMJIT_API virtual void flush(const void* p, size_t size) noexcept; - //! \} }; diff --git a/src/asmjit/core/logger.cpp b/src/asmjit/core/logger.cpp index 90b17e3..4567b3c 100644 --- a/src/asmjit/core/logger.cpp +++ b/src/asmjit/core/logger.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_LOGGING @@ -30,18 +12,13 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Logger - Construction / Destruction] -// ============================================================================ +// Logger - Implementation +// ======================= Logger::Logger() noexcept : _options() {} Logger::~Logger() noexcept {} -// ============================================================================ -// [asmjit::Logger - Logging] -// ============================================================================ - Error Logger::logf(const char* fmt, ...) noexcept { Error err; va_list ap; @@ -59,18 +36,13 @@ Error Logger::logv(const char* fmt, va_list ap) noexcept { return log(sb); } -// ============================================================================ -// [asmjit::FileLogger - Construction / Destruction] -// ============================================================================ +// FileLogger - Implementation +// =========================== FileLogger::FileLogger(FILE* file) noexcept : _file(file) {} FileLogger::~FileLogger() noexcept {} -// ============================================================================ -// [asmjit::FileLogger - Logging] -// ============================================================================ - Error FileLogger::_log(const char* data, size_t size) noexcept { if (!_file) return kErrorOk; @@ -82,17 +54,12 @@ Error FileLogger::_log(const char* data, size_t size) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::StringLogger - Construction / Destruction] -// ============================================================================ +// StringLogger - Implementation +// ============================= StringLogger::StringLogger() noexcept {} StringLogger::~StringLogger() noexcept {} -// ============================================================================ -// [asmjit::StringLogger - Logging] -// ============================================================================ - Error StringLogger::_log(const char* data, size_t size) noexcept { return _content.append(data, size); } diff --git a/src/asmjit/core/logger.h b/src/asmjit/core/logger.h index ddc1cfc..d416a50 100644 --- a/src/asmjit/core/logger.h +++ b/src/asmjit/core/logger.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_LOGGING_H_INCLUDED #define ASMJIT_CORE_LOGGING_H_INCLUDED @@ -35,15 +17,10 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_logging //! \{ -// ============================================================================ -// [asmjit::Logger] -// ============================================================================ - //! Logging interface. //! -//! This class can be inherited and reimplemented to fit into your own logging -//! needs. When reimplementing a logger use \ref Logger::_log() method to log -//! customize the output. +//! This class can be inherited and reimplemented to fit into your own logging needs. When reimplementing a logger +//! use \ref Logger::_log() method to log customize the output. //! //! There are two `Logger` implementations offered by AsmJit: //! - \ref FileLogger - logs into a `FILE*`. @@ -73,25 +50,35 @@ public: inline FormatOptions& options() noexcept { return _options; } //! \overload inline const FormatOptions& options() const noexcept { return _options; } + //! Sets formatting options of this Logger to `options`. + inline void setOptions(const FormatOptions& options) noexcept { _options = options; } + //! Resets formatting options of this Logger to defaults. + inline void resetOptions() noexcept { _options.reset(); } - //! Returns formatting flags, see \ref FormatOptions::Flags. - inline uint32_t flags() const noexcept { return _options.flags(); } + //! Returns formatting flags. + inline FormatFlags flags() const noexcept { return _options.flags(); } //! Tests whether the logger has the given `flag` enabled. - inline bool hasFlag(uint32_t flag) const noexcept { return _options.hasFlag(flag); } - //! Sets formatting flags to `flags`, see \ref FormatOptions::Flags. - inline void setFlags(uint32_t flags) noexcept { _options.setFlags(flags); } - //! Enables the given formatting `flags`, see \ref FormatOptions::Flags. - inline void addFlags(uint32_t flags) noexcept { _options.addFlags(flags); } - //! Disables the given formatting `flags`, see \ref FormatOptions::Flags. - inline void clearFlags(uint32_t flags) noexcept { _options.clearFlags(flags); } - - //! Returns indentation of `type`, see \ref FormatOptions::IndentationType. - inline uint32_t indentation(uint32_t type) const noexcept { return _options.indentation(type); } - //! Sets indentation of the given indentation `type` to `n` spaces, see \ref - //! FormatOptions::IndentationType. - inline void setIndentation(uint32_t type, uint32_t n) noexcept { _options.setIndentation(type, n); } - //! Resets indentation of the given indentation `type` to 0 spaces. - inline void resetIndentation(uint32_t type) noexcept { _options.resetIndentation(type); } + inline bool hasFlag(FormatFlags flag) const noexcept { return _options.hasFlag(flag); } + //! Sets formatting flags to `flags`. + inline void setFlags(FormatFlags flags) noexcept { _options.setFlags(flags); } + //! Enables the given formatting `flags`. + inline void addFlags(FormatFlags flags) noexcept { _options.addFlags(flags); } + //! Disables the given formatting `flags`. + inline void clearFlags(FormatFlags flags) noexcept { _options.clearFlags(flags); } + + //! Returns indentation of a given indentation `group`. + inline uint32_t indentation(FormatIndentationGroup type) const noexcept { return _options.indentation(type); } + //! Sets indentation of the given indentation `group` to `n` spaces. + inline void setIndentation(FormatIndentationGroup type, uint32_t n) noexcept { _options.setIndentation(type, n); } + //! Resets indentation of the given indentation `group` to 0 spaces. + inline void resetIndentation(FormatIndentationGroup type) noexcept { _options.resetIndentation(type); } + + //! Returns padding of a given padding `group`. + inline size_t padding(FormatPaddingGroup type) const noexcept { return _options.padding(type); } + //! Sets padding of a given padding `group` to `n`. + inline void setPadding(FormatPaddingGroup type, uint32_t n) noexcept { _options.setPadding(type, n); } + //! Resets padding of a given padding `group` to 0, which means that a default will be used. + inline void resetPadding(FormatPaddingGroup type) noexcept { _options.resetPadding(type); } //! \} @@ -100,9 +87,8 @@ public: //! Logs `str` - must be reimplemented. //! - //! The function can accept either a null terminated string if `size` is - //! `SIZE_MAX` or a non-null terminated string of the given `size`. The - //! function cannot assume that the data is null terminated and must handle + //! The function can accept either a null terminated string if `size` is `SIZE_MAX` or a non-null terminated + //! string of the given `size`. The function cannot assume that the data is null terminated and must handle //! non-null terminated inputs. virtual Error _log(const char* data, size_t size) noexcept = 0; @@ -111,21 +97,15 @@ public: //! Logs content of a string `str`. inline Error log(const String& str) noexcept { return _log(str.data(), str.size()); } - //! Formats the message by using `snprintf()` and then passes the formatted - //! string to \ref _log(). + //! Formats the message by using `snprintf()` and then passes the formatted string to \ref _log(). ASMJIT_API Error logf(const char* fmt, ...) noexcept; - //! Formats the message by using `vsnprintf()` and then passes the formatted - //! string to \ref _log(). + //! Formats the message by using `vsnprintf()` and then passes the formatted string to \ref _log(). ASMJIT_API Error logv(const char* fmt, va_list ap) noexcept; //! \} }; -// ============================================================================ -// [asmjit::FileLogger] -// ============================================================================ - //! Logger that can log to a `FILE*`. class ASMJIT_VIRTAPI FileLogger : public Logger { public: @@ -146,17 +126,14 @@ public: //! \name Accessors //! \{ - //! Returns the logging output stream or null if the logger has no output - //! stream. + //! Returns the logging output stream or null if the logger has no output stream. inline FILE* file() const noexcept { return _file; } //! Sets the logging output stream to `stream` or null. //! - //! \note If the `file` is null the logging will be disabled. When a logger - //! is attached to `CodeHolder` or any emitter the logging API will always - //! be called regardless of the output file. This means that if you really - //! want to disable logging at emitter level you must not attach a logger - //! to it. + //! \note If the `file` is null the logging will be disabled. When a logger is attached to `CodeHolder` or any + //! emitter the logging API will always be called regardless of the output file. This means that if you really + //! want to disable logging at emitter level you must not attach a logger to it. inline void setFile(FILE* file) noexcept { _file = file; } //! \} @@ -164,10 +141,6 @@ public: ASMJIT_API Error _log(const char* data, size_t size = SIZE_MAX) noexcept override; }; -// ============================================================================ -// [asmjit::StringLogger] -// ============================================================================ - //! Logger that stores everything in an internal string buffer. class ASMJIT_VIRTAPI StringLogger : public Logger { public: diff --git a/src/asmjit/core/misc_p.h b/src/asmjit/core/misc_p.h index 225ba6a..5cd934e 100644 --- a/src/asmjit/core/misc_p.h +++ b/src/asmjit/core/misc_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_MISC_P_H_INCLUDED #define ASMJIT_CORE_MISC_P_H_INCLUDED diff --git a/src/asmjit/core/operand.cpp b/src/asmjit/core/operand.cpp index cd5931f..ee02681 100644 --- a/src/asmjit/core/operand.cpp +++ b/src/asmjit/core/operand.cpp @@ -1,36 +1,22 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/operand.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Operand - Unit] -// ============================================================================ +// Operand - Tests +// =============== #if defined(ASMJIT_TEST) +enum class StrongEnumForImmTests : uint32_t { + kValue0, + kValue0xFFFFFFFF = 0xFFFFFFFFu +}; + UNIT(operand) { INFO("Checking operand sizes"); EXPECT(sizeof(Operand) == 16); @@ -65,22 +51,23 @@ UNIT(operand) { EXPECT(dummy.as<BaseReg>().isValid() == false); // Create some register (not specific to any architecture). - uint32_t rSig = Operand::kOpReg | (1 << Operand::kSignatureRegTypeShift ) | - (2 << Operand::kSignatureRegGroupShift) | - (8 << Operand::kSignatureSizeShift ) ; - BaseReg r1 = BaseReg::fromSignatureAndId(rSig, 5); + OperandSignature rSig = OperandSignature::fromOpType(OperandType::kReg) | + OperandSignature::fromRegType(RegType::kVec128) | + OperandSignature::fromRegGroup(RegGroup::kVec) | + OperandSignature::fromSize(8); + BaseReg r1(rSig, 5); EXPECT(r1.isValid() == true); EXPECT(r1.isReg() == true); - EXPECT(r1.isReg(1) == true); + EXPECT(r1.isReg(RegType::kVec128) == true); EXPECT(r1.isPhysReg() == true); EXPECT(r1.isVirtReg() == false); EXPECT(r1.signature() == rSig); - EXPECT(r1.type() == 1); - EXPECT(r1.group() == 2); + EXPECT(r1.type() == RegType::kVec128); + EXPECT(r1.group() == RegGroup::kVec); EXPECT(r1.size() == 8); EXPECT(r1.id() == 5); - EXPECT(r1.isReg(1, 5) == true); // RegType and Id. + EXPECT(r1.isReg(RegType::kVec128, 5) == true); // RegType and Id. EXPECT(r1._data[0] == 0); EXPECT(r1._data[1] == 0); @@ -88,7 +75,7 @@ UNIT(operand) { BaseReg r2(r1, 6); EXPECT(r2.isValid() == true); EXPECT(r2.isReg() == true); - EXPECT(r2.isReg(1) == true); + EXPECT(r2.isReg(RegType::kVec128) == true); EXPECT(r2.isPhysReg() == true); EXPECT(r2.isVirtReg() == false); EXPECT(r2.signature() == rSig); @@ -96,7 +83,7 @@ UNIT(operand) { EXPECT(r2.group() == r1.group()); EXPECT(r2.size() == r1.size()); EXPECT(r2.id() == 6); - EXPECT(r2.isReg(1, 6) == true); + EXPECT(r2.isReg(RegType::kVec128, 6) == true); r1.reset(); EXPECT(!r1.isReg()); @@ -126,17 +113,19 @@ UNIT(operand) { INFO("Checking basic functionality of Imm"); Imm immValue(-42); - EXPECT(immValue.type() == Imm::kTypeInteger); + EXPECT(immValue.type() == ImmType::kInt); EXPECT(Imm(-1).value() == -1); EXPECT(imm(-1).value() == -1); EXPECT(immValue.value() == -42); EXPECT(imm(0xFFFFFFFF).value() == int64_t(0xFFFFFFFF)); Imm immDouble(0.4); - EXPECT(immDouble.type() == Imm::kTypeDouble); + EXPECT(immDouble.type() == ImmType::kDouble); EXPECT(immDouble.valueAs<double>() == 0.4); EXPECT(immDouble == imm(0.4)); + EXPECT(Imm(StrongEnumForImmTests::kValue0).value() == 0); + EXPECT(Imm(StrongEnumForImmTests::kValue0xFFFFFFFF).value() == 0xFFFFFFFFu); } #endif diff --git a/src/asmjit/core/operand.h b/src/asmjit/core/operand.h index 61a81bd..96ef3ba 100644 --- a/src/asmjit/core/operand.h +++ b/src/asmjit/core/operand.h @@ -1,236 +1,466 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_OPERAND_H_INCLUDED #define ASMJIT_CORE_OPERAND_H_INCLUDED #include "../core/archcommons.h" #include "../core/support.h" +#include "../core/type.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [Macros] -// ============================================================================ - -//! Adds a template specialization for `REG_TYPE` into the local `RegTraits`. -#define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \ -template<> \ -struct RegTraits<REG_TYPE> { \ - typedef REG RegT; \ - \ - static constexpr uint32_t kValid = 1; \ - static constexpr uint32_t kCount = COUNT; \ - static constexpr uint32_t kTypeId = TYPE_ID; \ - \ - static constexpr uint32_t kType = REG_TYPE; \ - static constexpr uint32_t kGroup = GROUP; \ - static constexpr uint32_t kSize = SIZE; \ - \ - static constexpr uint32_t kSignature = \ - (Operand::kOpReg << Operand::kSignatureOpTypeShift ) | \ - (kType << Operand::kSignatureRegTypeShift ) | \ - (kGroup << Operand::kSignatureRegGroupShift) | \ - (kSize << Operand::kSignatureSizeShift ) ; \ -} - -//! Adds constructors and member functions to a class that implements abstract -//! register. Abstract register is register that doesn't have type or signature -//! yet, it's a base class like `x86::Reg` or `arm::Reg`. -#define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ -public: \ - /*! Default constructor that only setups basics. */ \ - constexpr REG() noexcept \ - : BASE(SignatureAndId(kSignature, kIdBad)) {} \ - \ - /*! Makes a copy of the `other` register operand. */ \ - constexpr REG(const REG& other) noexcept \ - : BASE(other) {} \ - \ - /*! Makes a copy of the `other` register having id set to `rId` */ \ - constexpr REG(const BaseReg& other, uint32_t rId) noexcept \ - : BASE(other, rId) {} \ - \ - /*! Creates a register based on `signature` and `rId`. */ \ - constexpr explicit REG(const SignatureAndId& sid) noexcept \ - : BASE(sid) {} \ - \ - /*! Creates a completely uninitialized REG register operand (garbage). */ \ - inline explicit REG(Globals::NoInit_) noexcept \ - : BASE(Globals::NoInit) {} \ - \ - /*! Creates a new register from register type and id. */ \ - static inline REG fromTypeAndId(uint32_t rType, uint32_t rId) noexcept { \ - return REG(SignatureAndId(signatureOf(rType), rId)); \ - } \ - \ - /*! Creates a new register from register signature and id. */ \ - static inline REG fromSignatureAndId(uint32_t rSgn, uint32_t rId) noexcept {\ - return REG(SignatureAndId(rSgn, rId)); \ - } \ - \ - /*! Clones the register operand. */ \ - constexpr REG clone() const noexcept { return REG(*this); } \ - \ - inline REG& operator=(const REG& other) noexcept = default; - -//! Adds constructors and member functions to a class that implements final -//! register. Final registers MUST HAVE a valid signature. -#define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \ -public: \ - static constexpr uint32_t kThisType = TRAITS::kType; \ - static constexpr uint32_t kThisGroup = TRAITS::kGroup; \ - static constexpr uint32_t kThisSize = TRAITS::kSize; \ - static constexpr uint32_t kSignature = TRAITS::kSignature; \ - \ - ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ - \ - /*! Creates a register operand having its id set to `rId`. */ \ - constexpr explicit REG(uint32_t rId) noexcept \ - : BASE(SignatureAndId(kSignature, rId)) {} - //! \addtogroup asmjit_assembler //! \{ -// ============================================================================ -// [asmjit::Operand_] -// ============================================================================ +//! Operand type used by \ref Operand_. +enum class OperandType : uint32_t { + //! Not an operand or not initialized. + kNone = 0, + //! Operand is a register. + kReg = 1, + //! Operand is a memory. + kMem = 2, + //! Operand is an immediate value. + kImm = 3, + //! Operand is a label. + kLabel = 4, + + //! Maximum value of `OperandType`. + kMaxValue = kLabel +}; -//! Constructor-less `Operand`. -//! -//! Contains no initialization code and can be used safely to define an array -//! of operands that won't be initialized. This is an `Operand` compatible -//! data structure designed to be statically initialized, static const, or to -//! be used by the user to define an array of operands without having them -//! default initialized. -//! -//! The key difference between `Operand` and `Operand_`: +static_assert(uint32_t(OperandType::kMem) == uint32_t(OperandType::kReg) + 1, + "AsmJit requires that `OperandType::kMem` equals to `OperandType::kReg + 1`"); + +//! Register mask is a convenience typedef that describes a mask where each bit describes a physical register id +//! in the same \ref RegGroup. At the moment 32 bits are enough as AsmJit doesn't support any architecture that +//! would provide more than 32 registers for a register group. +typedef uint32_t RegMask; + +//! Register type. //! -//! ``` -//! Operand_ xArray[10]; // Not initialized, contains garbage. -//! Operand yArray[10]; // All operands initialized to none. -//! ``` -struct Operand_ { - //! Operand's signature that provides operand type and additional information. - uint32_t _signature; - //! Either base id as used by memory operand or any id as used by others. - uint32_t _baseId; +//! Provides a unique type that can be used to identify a register or its view. +enum class RegType : uint8_t { + //! No register - unused, invalid, multiple meanings. + kNone = 0, - //! Data specific to the operand type. + //! This is not a register type. This value is reserved for a \ref Label that used in \ref BaseMem as a base. //! - //! The reason we don't use union is that we have `constexpr` constructors that - //! construct operands and other `constexpr` functions that return whether another - //! Operand or something else. These cannot generally work with unions so we also - //! cannot use `union` if we want to be standard compliant. - uint32_t _data[2]; + //! Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated + //! with any register type. This means that a memory operand's BASE register can be constructed from virtually any + //! operand (register vs. label) by just assigning its type (register type or label-tag) and operand id. + kLabelTag = 1, + + //! Universal type describing program counter (PC) or instruction pointer (IP) register, if the target architecture + //! actually exposes it as a separate register type, which most modern targets do. + kPC = 2, + + //! 8-bit low general purpose register (X86). + kGp8Lo = 3, + //! 8-bit high general purpose register (X86). + kGp8Hi = 4, + //! 16-bit general purpose register (X86). + kGp16 = 5, + //! 32-bit general purpose register (X86|ARM). + kGp32 = 6, + //! 64-bit general purpose register (X86|ARM). + kGp64 = 7, + //! 8-bit view of a vector register (ARM). + kVec8 = 8, + //! 16-bit view of a vector register (ARM). + kVec16 = 9, + //! 32-bit view of a vector register (ARM). + kVec32 = 10, + //! 64-bit view of a vector register (ARM). + //! + //! \note This is never used for MMX registers on X86, MMX registers have its own category. + kVec64 = 11, + //! 128-bit view of a vector register (X86|ARM). + kVec128 = 12, + //! 256-bit view of a vector register (X86). + kVec256 = 13, + //! 512-bit view of a vector register (X86). + kVec512 = 14, + //! 1024-bit view of a vector register (future). + kVec1024 = 15, + //! View of a vector register, which width is implementation specific (AArch64). + kVecNLen = 16, + + //! Mask register (X86). + kMask = 17, + + //! Start of architecture dependent register types. + kExtra = 18, + + // X86 Specific Register Types + // --------------------------- + + //! Instruction pointer (RIP), only addressable in \ref x86::Mem in 64-bit targets. + kX86_Rip = kPC, + //! Low GPB register (AL, BL, CL, DL, ...). + kX86_GpbLo = kGp8Lo, + //! High GPB register (AH, BH, CH, DH only). + kX86_GpbHi = kGp8Hi, + //! GPW register. + kX86_Gpw = kGp16, + //! GPD register. + kX86_Gpd = kGp32, + //! GPQ register (64-bit). + kX86_Gpq = kGp64, + //! XMM register (SSE+). + kX86_Xmm = kVec128, + //! YMM register (AVX+). + kX86_Ymm = kVec256, + //! ZMM register (AVX512+). + kX86_Zmm = kVec512, + //! K register (AVX512+). + kX86_KReg = kMask, + //! MMX register. + kX86_Mm = kExtra + 0, + //! Segment register (None, ES, CS, SS, DS, FS, GS). + kX86_SReg = kExtra + 1, + //! Control register (CR). + kX86_CReg = kExtra + 2, + //! Debug register (DR). + kX86_DReg = kExtra + 3, + //! FPU (x87) register. + kX86_St = kExtra + 4, + //! Bound register (BND). + kX86_Bnd = kExtra + 5, + //! TMM register (AMX_TILE) + kX86_Tmm = kExtra + 6, + + //! Maximum value of `RegType`. + kMaxValue = 31 +}; +ASMJIT_DEFINE_ENUM_COMPARE(RegType) - //! Indexes to `_data` array. - enum DataIndex : uint32_t { - kDataMemIndexId = 0, - kDataMemOffsetLo = 1, +//! Register group. +//! +//! Provides a unique value that identifies groups of registers and their views. +enum class RegGroup : uint8_t { + //! General purpose register group compatible with all backends. + kGp = 0, + //! Vector register group compatible with all backends. + //! + //! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers. + kVec = 1, + + //! Extra virtual group #2 that can be used by Compiler for register allocation. + kExtraVirt2 = 2, + //! Extra virtual group #3 that can be used by Compiler for register allocation. + kExtraVirt3 = 3, + + //! Program counter group. + kPC = 4, + + //! Extra non-virtual group that can be used by registers not managed by Compiler. + kExtraNonVirt = 5, + + // X86 Specific Register Groups + // ---------------------------- + + //! K register group (KReg) - maps to \ref RegGroup::kExtraVirt2 (X86, X86_64). + kX86_K = kExtraVirt2, + //! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64). + kX86_MM = kExtraVirt3, + + //! Instruction pointer (X86, X86_64). + kX86_Rip = kPC, + //! Segment register group (X86, X86_64). + kX86_SReg = kExtraNonVirt + 0, + //! CR register group (X86, X86_64). + kX86_CReg = kExtraNonVirt + 1, + //! DR register group (X86, X86_64). + kX86_DReg = kExtraNonVirt + 2, + //! FPU register group (X86, X86_64). + kX86_St = kExtraNonVirt + 3, + //! BND register group (X86, X86_64). + kX86_Bnd = kExtraNonVirt + 4, + //! TMM register group (X86, X86_64). + kX86_Tmm = kExtraNonVirt + 5, + + //! First group - only used in loops. + k0 = 0, + //! Last value of a virtual register that is managed by \ref BaseCompiler. + kMaxVirt = Globals::kNumVirtGroups - 1, + //! Maximum value of `RegGroup`. + kMaxValue = 15 +}; +ASMJIT_DEFINE_ENUM_COMPARE(RegGroup) - kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1, - kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0 - }; +typedef Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kMaxVirt> RegGroupVirtValues; - //! Operand types that can be encoded in `Operand`. - enum OpType : uint32_t { - //! Not an operand or not initialized. - kOpNone = 0, - //! Operand is a register. - kOpReg = 1, - //! Operand is a memory. - kOpMem = 2, - //! Operand is an immediate value. - kOpImm = 3, - //! Operand is a label. - kOpLabel = 4 - }; - static_assert(kOpMem == kOpReg + 1, "asmjit::Operand requires `kOpMem` to be `kOpReg+1`."); - - //! Label tag. - enum LabelTag { - //! Label tag is used as a sub-type, forming a unique signature across all - //! operand types as 0x1 is never associated with any register type. This - //! means that a memory operand's BASE register can be constructed from - //! virtually any operand (register vs. label) by just assigning its type - //! (register type or label-tag) and operand id. - kLabelTag = 0x1 - }; +//! Operand signature is a 32-bit number describing \ref Operand and some of its payload. +//! +//! In AsmJit operand signature is used to store additional payload of register, memory, and immediate operands. +//! In practice the biggest pressure on OperandSignature is from \ref BaseMem and architecture specific memory +//! operands that need to store additional payload that cannot be stored elsewhere as values of all other members +//! are fully specified by \ref BaseMem. +struct OperandSignature { + //! \name Constants + //! \{ - // \cond INTERNAL - enum SignatureBits : uint32_t { + enum : uint32_t { // Operand type (3 least significant bits). // |........|........|........|.....XXX| - kSignatureOpTypeShift = 0, - kSignatureOpTypeMask = 0x07u << kSignatureOpTypeShift, + kOpTypeShift = 0, + kOpTypeMask = 0x07u << kOpTypeShift, // Register type (5 bits). // |........|........|........|XXXXX...| - kSignatureRegTypeShift = 3, - kSignatureRegTypeMask = 0x1Fu << kSignatureRegTypeShift, + kRegTypeShift = 3, + kRegTypeMask = 0x1Fu << kRegTypeShift, // Register group (4 bits). // |........|........|....XXXX|........| - kSignatureRegGroupShift = 8, - kSignatureRegGroupMask = 0x0Fu << kSignatureRegGroupShift, + kRegGroupShift = 8, + kRegGroupMask = 0x0Fu << kRegGroupShift, // Memory base type (5 bits). // |........|........|........|XXXXX...| - kSignatureMemBaseTypeShift = 3, - kSignatureMemBaseTypeMask = 0x1Fu << kSignatureMemBaseTypeShift, + kMemBaseTypeShift = 3, + kMemBaseTypeMask = 0x1Fu << kMemBaseTypeShift, // Memory index type (5 bits). // |........|........|...XXXXX|........| - kSignatureMemIndexTypeShift = 8, - kSignatureMemIndexTypeMask = 0x1Fu << kSignatureMemIndexTypeShift, + kMemIndexTypeShift = 8, + kMemIndexTypeMask = 0x1Fu << kMemIndexTypeShift, // Memory base+index combined (10 bits). // |........|........|...XXXXX|XXXXX...| - kSignatureMemBaseIndexShift = 3, - kSignatureMemBaseIndexMask = 0x3FFu << kSignatureMemBaseIndexShift, + kMemBaseIndexShift = 3, + kMemBaseIndexMask = 0x3FFu << kMemBaseIndexShift, // This memory operand represents a home-slot or stack (Compiler) (1 bit). // |........|........|..X.....|........| - kSignatureMemRegHomeShift = 13, - kSignatureMemRegHomeFlag = 0x01u << kSignatureMemRegHomeShift, + kMemRegHomeShift = 13, + kMemRegHomeFlag = 0x01u << kMemRegHomeShift, // Immediate type (1 bit). // |........|........|........|....X...| - kSignatureImmTypeShift = 4, - kSignatureImmTypeMask = 0x01u << kSignatureImmTypeShift, + kImmTypeShift = 3, + kImmTypeMask = 0x01u << kImmTypeShift, // Predicate used by either registers or immediate values (4 bits). // |........|XXXX....|........|........| - kSignaturePredicateShift = 20, - kSignaturePredicateMask = 0x0Fu << kSignaturePredicateShift, + kPredicateShift = 20, + kPredicateMask = 0x0Fu << kPredicateShift, // Operand size (8 most significant bits). // |XXXXXXXX|........|........|........| - kSignatureSizeShift = 24, - kSignatureSizeMask = 0xFFu << kSignatureSizeShift + kSizeShift = 24, + kSizeMask = 0xFFu << kSizeShift + }; + + //! \} + + //! \name Members + //! \{ + + uint32_t _bits; + + //! \} + + //! \name Construction & Destruction + //! \{ + + inline OperandSignature() noexcept = default; + inline constexpr OperandSignature(const OperandSignature& other) noexcept = default; + inline constexpr explicit OperandSignature(uint32_t bits) noexcept : _bits(bits) {} + + //! \{ + + //! \name Overloaded Operators + //! + //! Overloaded operators make `OperandSignature` behave like regular integer. + //! + //! \{ + + inline constexpr bool operator!() const noexcept { return _bits != 0; } + inline constexpr explicit operator bool() const noexcept { return _bits != 0; } + + inline OperandSignature& operator=(uint32_t x) noexcept { _bits = x; return *this; } + inline OperandSignature& operator|=(uint32_t x) noexcept { _bits |= x; return *this; } + inline OperandSignature& operator&=(uint32_t x) noexcept { _bits &= x; return *this; } + inline OperandSignature& operator^=(uint32_t x) noexcept { _bits ^= x; return *this; } + + inline OperandSignature& operator=(const OperandSignature& other) noexcept { return operator=(other._bits); } + inline OperandSignature& operator|=(const OperandSignature& other) noexcept { return operator|=(other._bits); } + inline OperandSignature& operator&=(const OperandSignature& other) noexcept { return operator&=(other._bits); } + inline OperandSignature& operator^=(const OperandSignature& other) noexcept { return operator^=(other._bits); } + + inline constexpr OperandSignature operator~() const noexcept { return OperandSignature(~_bits); } + + inline constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature(_bits | x); } + inline constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature(_bits & x); } + inline constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature(_bits ^ x); } + + inline constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature(_bits | other._bits); } + inline constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature(_bits & other._bits); } + inline constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature(_bits ^ other._bits); } + + inline constexpr bool operator==(uint32_t x) const noexcept { return _bits == x; } + inline constexpr bool operator!=(uint32_t x) const noexcept { return _bits != x; } + + inline constexpr bool operator==(const OperandSignature& other) const noexcept { return _bits == other._bits; } + inline constexpr bool operator!=(const OperandSignature& other) const noexcept { return _bits != other._bits; } + + //! \} + + //! \name Accessors + //! \{ + + inline void reset() noexcept { _bits = 0; } + + inline constexpr uint32_t bits() const noexcept { return _bits; } + inline void setBits(uint32_t bits) noexcept { _bits = bits; } + + template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> + inline constexpr bool hasField() const noexcept { + return (_bits & kFieldMask) != 0; + } + + template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> + inline constexpr bool hasField(uint32_t value) const noexcept { + return (_bits & kFieldMask) != value << kFieldShift; + } + + template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> + inline constexpr uint32_t getField() const noexcept { + return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift); + } + + template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value> + inline void setField(uint32_t value) noexcept { + ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0); + _bits = (_bits & ~kFieldMask) | (value << kFieldShift); + } + + inline constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature(_bits & mask); } + + template<uint32_t kFieldMask> + inline constexpr bool matchesSignature(const OperandSignature& signature) const noexcept { + return (_bits & kFieldMask) == signature._bits; + } + + template<uint32_t kFieldMask> + inline constexpr bool matchesFields(uint32_t bits) const noexcept { + return (_bits & kFieldMask) == bits; + } + + template<uint32_t kFieldMask> + inline constexpr bool matchesFields(const OperandSignature& fields) const noexcept { + return (_bits & kFieldMask) == fields._bits; + } + + inline constexpr bool isValid() const noexcept { return _bits != 0; } + + inline constexpr OperandType opType() const noexcept { return (OperandType)getField<kOpTypeMask>(); } + + inline constexpr RegType regType() const noexcept { return (RegType)getField<kRegTypeMask>(); } + inline constexpr RegGroup regGroup() const noexcept { return (RegGroup)getField<kRegGroupMask>(); } + + inline constexpr RegType memBaseType() const noexcept { return (RegType)getField<kMemBaseTypeMask>(); } + inline constexpr RegType memIndexType() const noexcept { return (RegType)getField<kMemIndexTypeMask>(); } + + inline constexpr uint32_t predicate() const noexcept { return getField<kPredicateMask>(); } + inline constexpr uint32_t size() const noexcept { return getField<kSizeMask>(); } + + inline void setOpType(OperandType opType) noexcept { setField<kOpTypeMask>(uint32_t(opType)); } + inline void setRegType(RegType regType) noexcept { setField<kRegTypeMask>(uint32_t(regType)); } + inline void setRegGroup(RegGroup regGroup) noexcept { setField<kRegGroupMask>(uint32_t(regGroup)); } + + inline void setMemBaseType(RegGroup baseType) noexcept { setField<kMemBaseTypeMask>(uint32_t(baseType)); } + inline void setMemIndexType(RegGroup indexType) noexcept { setField<kMemIndexTypeMask>(uint32_t(indexType)); } + + inline void setPredicate(uint32_t predicate) noexcept { setField<kPredicateMask>(predicate); } + inline void setSize(uint32_t size) noexcept { setField<kSizeMask>(size); } + + //! \} + + //! \name Static Constructors + //! \{ + + static inline constexpr OperandSignature fromBits(uint32_t bits) noexcept { + return OperandSignature(bits); + } + + template<uint32_t kFieldMask, typename T> + static inline constexpr OperandSignature fromValue(const T& value) noexcept { + return OperandSignature(uint32_t(value) << Support::ConstCTZ<kFieldMask>::value); + } + + static inline constexpr OperandSignature fromOpType(OperandType opType) noexcept { + return OperandSignature(uint32_t(opType) << kOpTypeShift); + } + + static inline constexpr OperandSignature fromRegType(RegType regType) noexcept { + return OperandSignature(uint32_t(regType) << kRegTypeShift); + } + + static inline constexpr OperandSignature fromRegGroup(RegGroup regGroup) noexcept { + return OperandSignature(uint32_t(regGroup) << kRegGroupShift); + } + + static inline constexpr OperandSignature fromRegTypeAndGroup(RegType regType, RegGroup regGroup) noexcept { + return fromRegType(regType) | fromRegGroup(regGroup); + } + + static inline constexpr OperandSignature fromMemBaseType(RegType baseType) noexcept { + return OperandSignature(uint32_t(baseType) << kMemBaseTypeShift); + } + + static inline constexpr OperandSignature fromMemIndexType(RegType indexType) noexcept { + return OperandSignature(uint32_t(indexType) << kMemIndexTypeShift); + } + + static inline constexpr OperandSignature fromPredicate(uint32_t predicate) noexcept { + return OperandSignature(predicate << kPredicateShift); + } + + static inline constexpr OperandSignature fromSize(uint32_t size) noexcept { + return OperandSignature(size << kSizeShift); + } + + //! \} +}; + +//! Base class representing an operand in AsmJit (non-default constructed version). +//! +//! Contains no initialization code and can be used safely to define an array of operands that won't be initialized. +//! This is a \ref Operand base structure designed to be statically initialized, static const, or to be used by user +//! code to define an array of operands without having them default initialized at construction time. +//! +//! The key difference between \ref Operand and \ref Operand_ is: +//! +//! ``` +//! Operand_ xArray[10]; // Not initialized, contains garbage. +//! Operand_ yArray[10] {}; // All operands initialized to none explicitly (zero initialized). +//! Operand yArray[10]; // All operands initialized to none implicitly (zero initialized). +//! ``` +struct Operand_ { + //! \name Types + //! \{ + + typedef OperandSignature Signature; + + //! \} + + //! \name Constants + //! \{ + + // Indexes to `_data` array. + enum DataIndex : uint32_t { + kDataMemIndexId = 0, + kDataMemOffsetLo = 1, + + kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1, + kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0 }; - //! \endcond //! Constants useful for VirtId <-> Index translation. enum VirtIdConstants : uint32_t { @@ -242,22 +472,40 @@ struct Operand_ { kVirtIdCount = uint32_t(kVirtIdMax - kVirtIdMin + 1) }; - //! Tests whether the given `id` is a valid virtual register id. Since AsmJit - //! supports both physical and virtual registers it must be able to distinguish - //! between these two. The idea is that physical registers are always limited - //! in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`. - static ASMJIT_INLINE bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); } + //! \} + + //! \name Members + //! \{ + + //! Provides operand type and additional payload. + Signature _signature; + //! Either base id as used by memory operand or any id as used by others. + uint32_t _baseId; + + //! Data specific to the operand type. + //! + //! The reason we don't use union is that we have `constexpr` constructors that construct operands and other + //!`constexpr` functions that return whether another Operand or something else. These cannot generally work with + //! unions so we also cannot use `union` if we want to be standard compliant. + uint32_t _data[2]; + + //! \} + + //! Tests whether the given `id` is a valid virtual register id. Since AsmJit supports both physical and virtual + //! registers it must be able to distinguish between these two. The idea is that physical registers are always + //! limited in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`. + static inline bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); } //! Converts a real-id into a packed-id that can be stored in Operand. - static ASMJIT_INLINE uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; } + static inline uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; } //! Converts a packed-id back to real-id. - static ASMJIT_INLINE uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; } + static inline uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; } //! \name Construction & Destruction //! \{ //! \cond INTERNAL //! Initializes a `BaseReg` operand from `signature` and register `id`. - inline void _initReg(uint32_t signature, uint32_t id) noexcept { + inline void _initReg(const Signature& signature, uint32_t id) noexcept { _signature = signature; _baseId = id; _data[0] = 0; @@ -271,14 +519,13 @@ struct Operand_ { //! Resets the `Operand` to none. //! //! None operand is defined the following way: - //! - Its signature is zero (kOpNone, and the rest zero as well). + //! - Its signature is zero (OperandType::kNone, and the rest zero as well). //! - Its id is `0`. //! - The reserved8_4 field is set to `0`. //! - The reserved12_4 field is set to zero. //! - //! In other words, reset operands have all members set to zero. Reset operand - //! must match the Operand state right after its construction. Alternatively, - //! if you have an array of operands, you can simply use `memset()`. + //! In other words, reset operands have all members set to zero. Reset operand must match the Operand state + //! right after its construction. Alternatively, if you have an array of operands, you can simply use `memset()`. //! //! ``` //! using namespace asmjit; @@ -305,13 +552,13 @@ struct Operand_ { //! \} - //! \name Operator Overloads + //! \name Overloaded Operators //! \{ //! Tests whether this operand is the same as `other`. - constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); } + inline constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); } //! Tests whether this operand is not the same as `other`. - constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); } + inline constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); } //! \} @@ -331,153 +578,116 @@ struct Operand_ { //! \name Accessors //! \{ - //! Tests whether the operand's signature matches the given signature `sign`. - constexpr bool hasSignature(uint32_t signature) const noexcept { return _signature == signature; } //! Tests whether the operand's signature matches the signature of the `other` operand. - constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other.signature(); } + inline constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other._signature; } + //! Tests whether the operand's signature matches the given signature `sign`. + inline constexpr bool hasSignature(const Signature& other) const noexcept { return _signature == other; } //! Returns operand signature as unsigned 32-bit integer. //! - //! Signature is first 4 bytes of the operand data. It's used mostly for - //! operand checking as it's much faster to check 4 bytes at once than having - //! to check these bytes individually. - constexpr uint32_t signature() const noexcept { return _signature; } + //! Signature is first 4 bytes of the operand data. It's used mostly for operand checking as it's + //! much faster to check packed 4 bytes at once than having to check these bytes individually. + inline constexpr Signature signature() const noexcept { return _signature; } //! Sets the operand signature, see `signature()`. //! //! \note Improper use of `setSignature()` can lead to hard-to-debug errors. - inline void setSignature(uint32_t signature) noexcept { _signature = signature; } - - //! \cond INTERNAL - template<uint32_t mask> - constexpr bool _hasSignaturePart() const noexcept { - return (_signature & mask) != 0; - } - - template<uint32_t mask> - constexpr bool _hasSignaturePart(uint32_t signature) const noexcept { - return (_signature & mask) == signature; - } - - template<uint32_t mask> - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - - template<uint32_t mask> - inline void _setSignaturePart(uint32_t value) noexcept { - ASMJIT_ASSERT((value & ~(mask >> Support::constCtz(mask))) == 0); - _signature = (_signature & ~mask) | (value << Support::constCtz(mask)); - } - //! \endcond + inline void setSignature(const Signature& signature) noexcept { _signature = signature; } //! Returns the type of the operand, see `OpType`. - constexpr uint32_t opType() const noexcept { return _getSignaturePart<kSignatureOpTypeMask>(); } - //! Tests whether the operand is none (`kOpNone`). - constexpr bool isNone() const noexcept { return _signature == 0; } - //! Tests whether the operand is a register (`kOpReg`). - constexpr bool isReg() const noexcept { return opType() == kOpReg; } - //! Tests whether the operand is a memory location (`kOpMem`). - constexpr bool isMem() const noexcept { return opType() == kOpMem; } - //! Tests whether the operand is an immediate (`kOpImm`). - constexpr bool isImm() const noexcept { return opType() == kOpImm; } - //! Tests whether the operand is a label (`kOpLabel`). - constexpr bool isLabel() const noexcept { return opType() == kOpLabel; } + inline constexpr OperandType opType() const noexcept { return _signature.opType(); } + //! Tests whether the operand is none (`OperandType::kNone`). + inline constexpr bool isNone() const noexcept { return _signature == Signature::fromBits(0); } + //! Tests whether the operand is a register (`OperandType::kReg`). + inline constexpr bool isReg() const noexcept { return opType() == OperandType::kReg; } + //! Tests whether the operand is a memory location (`OperandType::kMem`). + inline constexpr bool isMem() const noexcept { return opType() == OperandType::kMem; } + //! Tests whether the operand is an immediate (`OperandType::kImm`). + inline constexpr bool isImm() const noexcept { return opType() == OperandType::kImm; } + //! Tests whether the operand is a label (`OperandType::kLabel`). + inline constexpr bool isLabel() const noexcept { return opType() == OperandType::kLabel; } //! Tests whether the operand is a physical register. - constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; } + inline constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; } //! Tests whether the operand is a virtual register. - constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; } + inline constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; } //! Tests whether the operand specifies a size (i.e. the size is not zero). - constexpr bool hasSize() const noexcept { return _hasSignaturePart<kSignatureSizeMask>(); } + inline constexpr bool hasSize() const noexcept { return _signature.hasField<Signature::kSizeMask>(); } //! Tests whether the size of the operand matches `size`. - constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } + inline constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } //! Returns the size of the operand in bytes. //! //! The value returned depends on the operand type: //! * None - Should always return zero size. - //! * Reg - Should always return the size of the register. If the register - //! size depends on architecture (like `x86::CReg` and `x86::DReg`) - //! the size returned should be the greatest possible (so it should - //! return 64-bit size in such case). + //! * Reg - Should always return the size of the register. If the register size depends on architecture + //! (like `x86::CReg` and `x86::DReg`) the size returned should be the greatest possible (so it + //! should return 64-bit size in such case). //! * Mem - Size is optional and will be in most cases zero. //! * Imm - Should always return zero size. //! * Label - Should always return zero size. - constexpr uint32_t size() const noexcept { return _getSignaturePart<kSignatureSizeMask>(); } + inline constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); } //! Returns the operand id. //! //! The value returned should be interpreted accordingly to the operand type: //! * None - Should be `0`. //! * Reg - Physical or virtual register id. - //! * Mem - Multiple meanings - BASE address (register or label id), or - //! high value of a 64-bit absolute address. + //! * Mem - Multiple meanings - BASE address (register or label id), or high value of a 64-bit absolute address. //! * Imm - Should be `0`. - //! * Label - Label id if it was created by using `newLabel()` or - //! `Globals::kInvalidId` if the label is invalid or not - //! initialized. - constexpr uint32_t id() const noexcept { return _baseId; } + //! * Label - Label id if it was created by using `newLabel()` or `Globals::kInvalidId` if the label is invalid or + //! not initialized. + inline constexpr uint32_t id() const noexcept { return _baseId; } //! Tests whether the operand is 100% equal to `other` operand. //! //! \note This basically performs a binary comparison, if aby bit is //! different the operands are not equal. - constexpr bool equals(const Operand_& other) const noexcept { + inline constexpr bool equals(const Operand_& other) const noexcept { return (_signature == other._signature) & (_baseId == other._baseId ) & (_data[0] == other._data[0] ) & (_data[1] == other._data[1] ) ; } -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use equals() instead") - constexpr bool isEqual(const Operand_& other) const noexcept { return equals(other); } -#endif //!ASMJIT_NO_DEPRECATED - - //! Tests whether the operand is a register matching `rType`. - constexpr bool isReg(uint32_t rType) const noexcept { - return (_signature & (kSignatureOpTypeMask | kSignatureRegTypeMask)) == - ((kOpReg << kSignatureOpTypeShift) | (rType << kSignatureRegTypeShift)); + //! Tests whether the operand is a register matching the given register `type`. + inline constexpr bool isReg(RegType type) const noexcept { + return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type)); } - //! Tests whether the operand is register and of `rType` and `rId`. - constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { - return isReg(rType) && id() == rId; + //! Tests whether the operand is register and of register `type` and `id`. + inline constexpr bool isReg(RegType type, uint32_t id) const noexcept { + return isReg(type) && this->id() == id; } //! Tests whether the operand is a register or memory. - constexpr bool isRegOrMem() const noexcept { - return Support::isBetween<uint32_t>(opType(), kOpReg, kOpMem); + inline constexpr bool isRegOrMem() const noexcept { + return Support::isBetween<uint32_t>(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kMem)); } //! \} }; -// ============================================================================ -// [asmjit::Operand] -// ============================================================================ - -//! Operand can contain register, memory location, immediate, or label. +//! Base class representing an operand in AsmJit (default constructed version). class Operand : public Operand_ { public: //! \name Construction & Destruction //! \{ //! Creates `kOpNone` operand having all members initialized to zero. - constexpr Operand() noexcept - : Operand_{ kOpNone, 0u, { 0u, 0u }} {} + inline constexpr Operand() noexcept + : Operand_{ Signature::fromOpType(OperandType::kNone), 0u, { 0u, 0u }} {} //! Creates a cloned `other` operand. - constexpr Operand(const Operand& other) noexcept = default; + inline constexpr Operand(const Operand& other) noexcept = default; //! Creates a cloned `other` operand. - constexpr explicit Operand(const Operand_& other) + inline constexpr explicit Operand(const Operand_& other) : Operand_(other) {} //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values. - constexpr Operand(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept + inline constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept : Operand_{ u0, u1, { u2, u3 }} {} //! Creates an uninitialized operand (dangerous). @@ -485,7 +695,7 @@ public: //! \} - //! \name Operator Overloads + //! \name Overloaded Operators //! \{ inline Operand& operator=(const Operand& other) noexcept = default; @@ -493,26 +703,21 @@ public: //! \} - //! \name Utilities + //! \name Clone //! \{ //! Clones this operand and returns its copy. - constexpr Operand clone() const noexcept { return Operand(*this); } + inline constexpr Operand clone() const noexcept { return Operand(*this); } //! \} }; static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes long"); -// ============================================================================ -// [asmjit::Label] -// ============================================================================ - //! Label (jump target or data location). //! -//! Label represents a location in code typically used as a jump target, but -//! may be also a reference to some data or a static variable. Label has to be -//! explicitly created by BaseEmitter. +//! Label represents a location in code typically used as a jump target, but may be also a reference to some data or +//! a static variable. Label has to be explicitly created by BaseEmitter. //! //! Example of using labels: //! @@ -535,41 +740,27 @@ static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes l //! ``` class Label : public Operand { public: - //! Type of the Label. - enum LabelType : uint32_t { - //! Anonymous (unnamed) label. - kTypeAnonymous = 0, - //! Local label (always has parentId). - kTypeLocal = 1, - //! Global label (never has parentId). - kTypeGlobal = 2, - //! External label (references an external symbol). - kTypeExternal = 3, - //! Number of label types. - kTypeCount = 4 - }; - //! \name Construction & Destruction //! \{ //! Creates a label operand without ID (you must set the ID to make it valid). - constexpr Label() noexcept - : Operand(Globals::Init, kOpLabel, Globals::kInvalidId, 0, 0) {} + inline constexpr Label() noexcept + : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), Globals::kInvalidId, 0, 0) {} //! Creates a cloned label operand of `other`. - constexpr Label(const Label& other) noexcept + inline constexpr Label(const Label& other) noexcept : Operand(other) {} //! Creates a label operand of the given `id`. - constexpr explicit Label(uint32_t id) noexcept - : Operand(Globals::Init, kOpLabel, id, 0, 0) {} + inline constexpr explicit Label(uint32_t id) noexcept + : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), id, 0, 0) {} inline explicit Label(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`. inline void reset() noexcept { - _signature = kOpLabel; + _signature = Signature::fromOpType(OperandType::kLabel); _baseId = Globals::kInvalidId; _data[0] = 0; _data[1] = 0; @@ -588,190 +779,81 @@ public: //! \{ //! Tests whether the label was created by CodeHolder and/or an attached emitter. - constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; } + inline constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; } //! Sets the label `id`. inline void setId(uint32_t id) noexcept { _baseId = id; } //! \} }; -// ============================================================================ -// [asmjit::BaseRegTraits] -// ============================================================================ - //! \cond INTERNAL //! Default register traits. struct BaseRegTraits { - //! RegType is not valid by default. - static constexpr uint32_t kValid = 0; - //! Count of registers (0 if none). - static constexpr uint32_t kCount = 0; - //! Everything is void by default. - static constexpr uint32_t kTypeId = 0; - - //! Zero type by default. - static constexpr uint32_t kType = 0; - //! Zero group by default. - static constexpr uint32_t kGroup = 0; - //! No size by default. - static constexpr uint32_t kSize = 0; - - //! Empty signature by default (not even having operand type set to register). - static constexpr uint32_t kSignature = 0; + enum : uint32_t { + //! \ref TypeId representing this register type, could be \ref TypeId::kVoid if such type doesn't exist. + kTypeId = uint32_t(TypeId::kVoid), + //! RegType is not valid by default. + kValid = 0, + //! Count of registers (0 if none). + kCount = 0, + + //! Zero type by default (defeaults to None). + kType = uint32_t(RegType::kNone), + //! Zero group by default (defaults to GP). + kGroup = uint32_t(RegGroup::kGp), + //! No size by default. + kSize = 0, + + //! Empty signature by default (not even having operand type set to register). + kSignature = 0 + }; }; //! \endcond -// ============================================================================ -// [asmjit::BaseReg] -// ============================================================================ - -//! Structure that allows to extract a register information based on the signature. -//! -//! This information is compatible with operand's signature (32-bit integer) -//! and `RegInfo` just provides easy way to access it. -struct RegInfo { - inline void reset(uint32_t signature = 0) noexcept { _signature = signature; } - inline void setSignature(uint32_t signature) noexcept { _signature = signature; } - - template<uint32_t mask> - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - - constexpr bool isValid() const noexcept { return _signature != 0; } - constexpr uint32_t signature() const noexcept { return _signature; } - constexpr uint32_t opType() const noexcept { return _getSignaturePart<Operand::kSignatureOpTypeMask>(); } - constexpr uint32_t group() const noexcept { return _getSignaturePart<Operand::kSignatureRegGroupMask>(); } - constexpr uint32_t type() const noexcept { return _getSignaturePart<Operand::kSignatureRegTypeMask>(); } - constexpr uint32_t size() const noexcept { return _getSignaturePart<Operand::kSignatureSizeMask>(); } - - uint32_t _signature; -}; - //! Physical or virtual register operand. class BaseReg : public Operand { public: - static constexpr uint32_t kBaseSignature = - kSignatureOpTypeMask | - kSignatureRegTypeMask | - kSignatureRegGroupMask | - kSignatureSizeMask ; - - //! Architecture neutral register types. - //! - //! These must be reused by any platform that contains that types. All GP - //! and VEC registers are also allowed by design to be part of a BASE|INDEX - //! of a memory operand. - enum RegType : uint32_t { - //! No register - unused, invalid, multiple meanings. - kTypeNone = 0, - - // (1 is used as a LabelTag) - - //! 8-bit low general purpose register (X86). - kTypeGp8Lo = 2, - //! 8-bit high general purpose register (X86). - kTypeGp8Hi = 3, - //! 16-bit general purpose register (X86). - kTypeGp16 = 4, - //! 32-bit general purpose register (X86|ARM). - kTypeGp32 = 5, - //! 64-bit general purpose register (X86|ARM). - kTypeGp64 = 6, - //! 8-bit view of a vector register (ARM). - kTypeVec8 = 7, - //! 16-bit view of a vector register (ARM). - kTypeVec16 = 8, - //! 32-bit view of a vector register (ARM). - kTypeVec32 = 9, - //! 64-bit view of a vector register (ARM). - kTypeVec64 = 10, - //! 128-bit view of a vector register (X86|ARM). - kTypeVec128 = 11, - //! 256-bit view of a vector register (X86). - kTypeVec256 = 12, - //! 512-bit view of a vector register (X86). - kTypeVec512 = 13, - //! 1024-bit view of a vector register (future). - kTypeVec1024 = 14, - //! Other0 register, should match `kOther0` group. - kTypeOther0 = 15, - //! Other1 register, should match `kOther1` group. - kTypeOther1 = 16, - //! Universal id of IP/PC register (if separate). - kTypeIP = 17, - //! Start of platform dependent register types. - kTypeCustom = 18, - //! Maximum possible register type value. - kTypeMax = 31 - }; - - //! Register group (architecture neutral), and some limits. - enum RegGroup : uint32_t { - //! General purpose register group compatible with all backends. - kGroupGp = 0, - //! Vector register group compatible with all backends. - kGroupVec = 1, - //! Group that is architecture dependent. - kGroupOther0 = 2, - //! Group that is architecture dependent. - kGroupOther1 = 3, - //! Count of register groups used by physical and virtual registers. - kGroupVirt = 4, - //! Count of register groups used by physical registers only. - kGroupCount = 16 - }; + //! \name Constants + //! \{ - enum Id : uint32_t { + enum : uint32_t { //! None or any register (mostly internal). - kIdBad = 0xFFu - }; + kIdBad = 0xFFu, - //! A helper used by constructors. - struct SignatureAndId { - uint32_t _signature; - uint32_t _id; + kBaseSignatureMask = + Signature::kOpTypeMask | + Signature::kRegTypeMask | + Signature::kRegGroupMask | + Signature::kSizeMask, - inline SignatureAndId() noexcept = default; - constexpr SignatureAndId(const SignatureAndId& other) noexcept = default; - - constexpr explicit SignatureAndId(uint32_t signature, uint32_t id) noexcept - : _signature(signature), - _id(id) {} - - constexpr uint32_t signature() const noexcept { return _signature; } - constexpr uint32_t id() const noexcept { return _id; } + kTypeNone = uint32_t(RegType::kNone), + kSignature = Signature::fromOpType(OperandType::kReg).bits() }; - static constexpr uint32_t kSignature = kOpReg; + //! \} //! \name Construction & Destruction //! \{ //! Creates a dummy register operand. - constexpr BaseReg() noexcept - : Operand(Globals::Init, kSignature, kIdBad, 0, 0) {} + inline constexpr BaseReg() noexcept + : Operand(Globals::Init, Signature::fromOpType(OperandType::kReg), kIdBad, 0, 0) {} //! Creates a new register operand which is the same as `other` . - constexpr BaseReg(const BaseReg& other) noexcept + inline constexpr BaseReg(const BaseReg& other) noexcept : Operand(other) {} - //! Creates a new register operand compatible with `other`, but with a different `rId`. - constexpr BaseReg(const BaseReg& other, uint32_t rId) noexcept - : Operand(Globals::Init, other._signature, rId, 0, 0) {} + //! Creates a new register operand compatible with `other`, but with a different `id`. + inline constexpr BaseReg(const BaseReg& other, uint32_t id) noexcept + : Operand(Globals::Init, other._signature, id, 0, 0) {} - //! Creates a register initialized to `signature` and `rId`. - constexpr explicit BaseReg(const SignatureAndId& sid) noexcept - : Operand(Globals::Init, sid._signature, sid._id, 0, 0) {} + //! Creates a register initialized to the given `signature` and `id`. + inline constexpr BaseReg(const Signature& signature, uint32_t id) noexcept + : Operand(Globals::Init, signature, id, 0, 0) {} inline explicit BaseReg(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} - /*! Creates a new register from register signature `rSgn` and id. */ - static inline BaseReg fromSignatureAndId(uint32_t rSgn, uint32_t rId) noexcept { - return BaseReg(SignatureAndId(rSgn, rId)); - } - //! \} //! \name Overloaded Operators @@ -786,103 +868,100 @@ public: //! Returns base signature of the register associated with each register type. //! - //! Base signature only contains the operand type, register type, register - //! group, and register size. It doesn't contain element type, predicate, or - //! other architecture-specific data. Base signature is a signature that is + //! Base signature only contains the operand type, register type, register group, and register size. It doesn't + //! contain element type, predicate, or other architecture-specific data. Base signature is a signature that is //! provided by architecture-specific `RegTraits`, like \ref x86::RegTraits. - constexpr uint32_t baseSignature() const noexcept { - return _signature & (kBaseSignature); - } + inline constexpr OperandSignature baseSignature() const noexcept { return _signature & kBaseSignatureMask; } //! Tests whether the operand's base signature matches the given signature `sign`. - constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; } + inline constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; } + //! Tests whether the operand's base signature matches the given signature `sign`. + inline constexpr bool hasBaseSignature(const OperandSignature& signature) const noexcept { return baseSignature() == signature; } //! Tests whether the operand's base signature matches the base signature of the `other` operand. - constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); } + inline constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); } //! Tests whether this register is the same as `other`. //! - //! This is just an optimization. Registers by default only use the first - //! 8 bytes of Operand data, so this method takes advantage of this knowledge - //! and only compares these 8 bytes. If both operands were created correctly - //! both \ref equals() and \ref isSame() should give the same answer, however, - //! if any of these two contains garbage or other metadata in the upper 8 - //! bytes then \ref isSame() may return `true` in cases in which \ref equals() + //! This is just an optimization. Registers by default only use the first 8 bytes of Operand data, so this method + //! takes advantage of this knowledge and only compares these 8 bytes. If both operands were created correctly + //! both \ref equals() and \ref isSame() should give the same answer, however, if any of these two contains garbage + //! or other metadata in the upper 8 bytes then \ref isSame() may return `true` in cases in which \ref equals() //! returns false. - constexpr bool isSame(const BaseReg& other) const noexcept { + inline constexpr bool isSame(const BaseReg& other) const noexcept { return (_signature == other._signature) & (_baseId == other._baseId); } //! Tests whether the register is valid (either virtual or physical). - constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); } + inline constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); } //! Tests whether this is a physical register. - constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } + inline constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } //! Tests whether this is a virtual register. - constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; } + inline constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; } //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience. - constexpr bool isType(uint32_t type) const noexcept { return (_signature & kSignatureRegTypeMask) == (type << kSignatureRegTypeShift); } + inline constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); } //! Tests whether the register group matches `group`. - constexpr bool isGroup(uint32_t group) const noexcept { return (_signature & kSignatureRegGroupMask) == (group << kSignatureRegGroupShift); } + inline constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); } //! Tests whether the register is a general purpose register (any size). - constexpr bool isGp() const noexcept { return isGroup(kGroupGp); } + inline constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); } //! Tests whether the register is a vector register. - constexpr bool isVec() const noexcept { return isGroup(kGroupVec); } + inline constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); } using Operand_::isReg; //! Same as `isType()`, provided for convenience. - constexpr bool isReg(uint32_t rType) const noexcept { return isType(rType); } - //! Tests whether the register type matches `type` and register id matches `rId`. - constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { return isType(rType) && id() == rId; } + inline constexpr bool isReg(RegType rType) const noexcept { return isType(rType); } + //! Tests whether the register type matches `type` and register id matches `id`. + inline constexpr bool isReg(RegType rType, uint32_t id) const noexcept { return isType(rType) && this->id() == id; } - //! Returns the type of the register. - constexpr uint32_t type() const noexcept { return _getSignaturePart<kSignatureRegTypeMask>(); } + //! Returns the register type. + inline constexpr RegType type() const noexcept { return _signature.regType(); } //! Returns the register group. - constexpr uint32_t group() const noexcept { return _getSignaturePart<kSignatureRegGroupMask>(); } + inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); } //! Returns operation predicate of the register (ARM/AArch64). //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the register. - constexpr uint32_t predicate() const noexcept { return _getSignaturePart<kSignaturePredicateMask>(); } + //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp + //! of the register. + inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); } //! Sets operation predicate of the register to `predicate` (ARM/AArch64). //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the register. - inline void setPredicate(uint32_t predicate) noexcept { _setSignaturePart<kSignaturePredicateMask>(predicate); } + //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp + //! of the register. + inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); } //! Resets shift operation type of the register to the default value (ARM/AArch64). - inline void resetPredicate() noexcept { _setSignaturePart<kSignaturePredicateMask>(0); } + inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); } //! Clones the register operand. - constexpr BaseReg clone() const noexcept { return BaseReg(*this); } + inline constexpr BaseReg clone() const noexcept { return BaseReg(*this); } //! Casts this register to `RegT` by also changing its signature. //! //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. template<typename RegT> - constexpr RegT cloneAs() const noexcept { return RegT(RegT::kSignature, id()); } + inline constexpr RegT cloneAs() const noexcept { return RegT(Signature(RegT::kSignature), id()); } //! Casts this register to `other` by also changing its signature. //! //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. template<typename RegT> - constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(SignatureAndId(other.signature(), id())); } + inline constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(other.signature(), id()); } - //! Sets the register id to `rId`. - inline void setId(uint32_t rId) noexcept { _baseId = rId; } + //! Sets the register id to `id`. + inline void setId(uint32_t id) noexcept { _baseId = id; } //! Sets a 32-bit operand signature based on traits of `RegT`. template<typename RegT> inline void setSignatureT() noexcept { _signature = RegT::kSignature; } - //! Sets the register `signature` and `rId`. - inline void setSignatureAndId(uint32_t signature, uint32_t rId) noexcept { + //! Sets the register `signature` and `id`. + inline void setSignatureAndId(const OperandSignature& signature, uint32_t id) noexcept { _signature = signature; - _baseId = rId; + _baseId = id; } //! \} @@ -893,39 +972,36 @@ public: //! Tests whether the `op` operand is a general purpose register. static inline bool isGp(const Operand_& op) noexcept { // Check operand type and register group. Not interested in register type and size. - const uint32_t kSgn = (kOpReg << kSignatureOpTypeShift ) | - (kGroupGp << kSignatureRegGroupShift) ; - return (op.signature() & (kSignatureOpTypeMask | kSignatureRegGroupMask)) == kSgn; + return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp)); } //! Tests whether the `op` operand is a vector register. static inline bool isVec(const Operand_& op) noexcept { // Check operand type and register group. Not interested in register type and size. - const uint32_t kSgn = (kOpReg << kSignatureOpTypeShift ) | - (kGroupVec << kSignatureRegGroupShift) ; - return (op.signature() & (kSignatureOpTypeMask | kSignatureRegGroupMask)) == kSgn; + return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kVec)); } - //! Tests whether the `op` is a general purpose register of the given `rId`. - static inline bool isGp(const Operand_& op, uint32_t rId) noexcept { return isGp(op) & (op.id() == rId); } - //! Tests whether the `op` is a vector register of the given `rId`. - static inline bool isVec(const Operand_& op, uint32_t rId) noexcept { return isVec(op) & (op.id() == rId); } + //! Tests whether the `op` is a general purpose register of the given `id`. + static inline bool isGp(const Operand_& op, uint32_t id) noexcept { return isGp(op) & (op.id() == id); } + //! Tests whether the `op` is a vector register of the given `id`. + static inline bool isVec(const Operand_& op, uint32_t id) noexcept { return isVec(op) & (op.id() == id); } //! \} }; -// ============================================================================ -// [asmjit::RegOnly] -// ============================================================================ - -//! RegOnly is 8-byte version of `BaseReg` that allows to store either register -//! or nothing. +//! RegOnly is 8-byte version of `BaseReg` that allows to store either register or nothing. //! -//! This class was designed to decrease the space consumed by each extra "operand" -//! in `BaseEmitter` and `InstNode` classes. +//! It's designed to decrease the space consumed by an extra "operand" in \ref BaseEmitter and \ref InstNode. struct RegOnly { - //! Type of the operand, either `kOpNone` or `kOpReg`. - uint32_t _signature; + //! \name Types + //! \{ + + typedef OperandSignature Signature; + + //! \} + + //! Operand signature - only \ref OperandType::kNone and \ref OperandType::kReg are supported. + Signature _signature; //! Physical or virtual register id. uint32_t _id; @@ -933,7 +1009,7 @@ struct RegOnly { //! \{ //! Initializes the `RegOnly` instance to hold register `signature` and `id`. - inline void init(uint32_t signature, uint32_t id) noexcept { + inline void init(const OperandSignature& signature, uint32_t id) noexcept { _signature = signature; _id = id; } @@ -942,7 +1018,7 @@ struct RegOnly { inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); } //! Resets the `RegOnly` members to zeros (none). - inline void reset() noexcept { init(0, 0); } + inline void reset() noexcept { init(Signature::fromBits(0), 0); } //! \} @@ -950,40 +1026,30 @@ struct RegOnly { //! \{ //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`). - constexpr bool isNone() const noexcept { return _signature == 0; } + inline constexpr bool isNone() const noexcept { return _signature == 0; } //! Tests whether the register is valid (either virtual or physical). - constexpr bool isReg() const noexcept { return _signature != 0; } + inline constexpr bool isReg() const noexcept { return _signature != 0; } //! Tests whether this is a physical register. - constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; } + inline constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; } //! Tests whether this is a virtual register (used by `BaseCompiler`). - constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; } + inline constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; } //! Returns the register signature or 0 if no register is assigned. - constexpr uint32_t signature() const noexcept { return _signature; } + inline constexpr OperandSignature signature() const noexcept { return _signature; } //! Returns the register id. //! - //! \note Always check whether the register is assigned before using the - //! returned identifier as non-assigned `RegOnly` instance would return - //! zero id, which is still a valid register id. - constexpr uint32_t id() const noexcept { return _id; } + //! \note Always check whether the register is assigned before using the returned identifier as + //! non-assigned `RegOnly` instance would return zero id, which is still a valid register id. + inline constexpr uint32_t id() const noexcept { return _id; } //! Sets the register id. inline void setId(uint32_t id) noexcept { _id = id; } - //! \cond INTERNAL - //! - //! Extracts information from operand's signature. - template<uint32_t mask> - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - //! \endcond - - //! Returns the type of the register. - constexpr uint32_t type() const noexcept { return _getSignaturePart<Operand::kSignatureRegTypeMask>(); } + //! Returns the register type. + inline constexpr RegType type() const noexcept { return _signature.regType(); } //! Returns the register group. - constexpr uint32_t group() const noexcept { return _getSignaturePart<Operand::kSignatureRegGroupMask>(); } + inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); } //! \} @@ -992,94 +1058,132 @@ struct RegOnly { //! Converts this ExtraReg to a real `RegT` operand. template<typename RegT> - constexpr RegT toReg() const noexcept { return RegT(BaseReg::SignatureAndId(_signature, _id)); } + inline constexpr RegT toReg() const noexcept { return RegT(_signature, _id); } //! \} }; -// ============================================================================ -// [asmjit::BaseMem] -// ============================================================================ +//! \cond INTERNAL +//! Adds a template specialization for `REG_TYPE` into the local `RegTraits`. +#define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \ +template<> \ +struct RegTraits<REG_TYPE> { \ + typedef REG RegT; \ + \ + enum : uint32_t { \ + kValid = uint32_t(true), \ + kCount = uint32_t(COUNT), \ + kType = uint32_t(REG_TYPE), \ + kGroup = uint32_t(GROUP), \ + kSize = uint32_t(SIZE), \ + kTypeId = uint32_t(TYPE_ID), \ + \ + kSignature = (OperandSignature::fromOpType(OperandType::kReg) | \ + OperandSignature::fromRegType(REG_TYPE) | \ + OperandSignature::fromRegGroup(GROUP) | \ + OperandSignature::fromSize(kSize)).bits(), \ + }; \ +} + +//! Adds constructors and member functions to a class that implements abstract register. Abstract register is register +//! that doesn't have type or signature yet, it's a base class like `x86::Reg` or `arm::Reg`. +#define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ +public: \ + /*! Default constructor that only setups basics. */ \ + inline constexpr REG() noexcept \ + : BASE(Signature(kSignature), kIdBad) {} \ + \ + /*! Makes a copy of the `other` register operand. */ \ + inline constexpr REG(const REG& other) noexcept \ + : BASE(other) {} \ + \ + /*! Makes a copy of the `other` register having id set to `id` */ \ + inline constexpr REG(const BaseReg& other, uint32_t id) noexcept \ + : BASE(other, id) {} \ + \ + /*! Creates a register based on `signature` and `id`. */ \ + inline constexpr REG(const OperandSignature& sgn, uint32_t id) noexcept \ + : BASE(sgn, id) {} \ + \ + /*! Creates a completely uninitialized REG register operand (garbage). */ \ + inline explicit REG(Globals::NoInit_) noexcept \ + : BASE(Globals::NoInit) {} \ + \ + /*! Creates a new register from register type and id. */ \ + static inline REG fromTypeAndId(RegType type, uint32_t id) noexcept { \ + return REG(signatureOf(type), id); \ + } \ + \ + /*! Clones the register operand. */ \ + inline constexpr REG clone() const noexcept { return REG(*this); } \ + \ + inline REG& operator=(const REG& other) noexcept = default; + +//! Adds constructors and member functions to a class that implements final register. Final registers MUST HAVE a valid +//! signature. +#define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \ +public: \ + enum : uint32_t { \ + kThisType = TRAITS::kType, \ + kThisGroup = TRAITS::kGroup, \ + kThisSize = TRAITS::kSize, \ + kSignature = TRAITS::kSignature \ + }; \ + \ + ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ + \ + /*! Creates a register operand having its id set to `id`. */ \ + inline constexpr explicit REG(uint32_t id) noexcept \ + : BASE(Signature(kSignature), id) {} +//! \endcond //! Base class for all memory operands. //! -//! \note It's tricky to pack all possible cases that define a memory operand -//! into just 16 bytes. The `BaseMem` splits data into the following parts: +//! The data is split into the following parts: //! -//! - BASE - Base register or label - requires 36 bits total. 4 bits are used -//! to encode the type of the BASE operand (label vs. register type) and the -//! remaining 32 bits define the BASE id, which can be a physical or virtual -//! register index. If BASE type is zero, which is never used as a register -//! type and label doesn't use it as well then BASE field contains a high -//! DWORD of a possible 64-bit absolute address, which is possible on X64. +//! - BASE - Base register or label - requires 36 bits total. 4 bits are used to encode the type of the BASE operand +//! (label vs. register type) and the remaining 32 bits define the BASE id, which can be a physical or virtual +//! register index. If BASE type is zero, which is never used as a register type and label doesn't use it as well +//! then BASE field contains a high DWORD of a possible 64-bit absolute address, which is possible on X64. //! -//! - INDEX - Index register (or theoretically Label, which doesn't make sense). -//! Encoding is similar to BASE - it also requires 36 bits and splits the -//! encoding to INDEX type (4 bits defining the register type) and id (32-bits). +//! - INDEX - Index register (or theoretically Label, which doesn't make sense). Encoding is similar to BASE - it +//! also requires 36 bits and splits the encoding to INDEX type (4 bits defining the register type) and 32-bit id. //! -//! - OFFSET - A relative offset of the address. Basically if BASE is specified -//! the relative displacement adjusts BASE and an optional INDEX. if BASE is -//! not specified then the OFFSET should be considered as ABSOLUTE address (at -//! least on X86). In that case its low 32 bits are stored in DISPLACEMENT -//! field and the remaining high 32 bits are stored in BASE. +//! - OFFSET - A relative offset of the address. Basically if BASE is specified the relative displacement adjusts +//! BASE and an optional INDEX. if BASE is not specified then the OFFSET should be considered as ABSOLUTE address +//! (at least on X86). In that case its low 32 bits are stored in DISPLACEMENT field and the remaining high 32 +//! bits are stored in BASE. //! -//! - OTHER - There is rest 8 bits that can be used for whatever purpose. For -//! example \ref x86::Mem operand uses these bits to store segment override -//! prefix and index shift (or scale). +//! - OTHER - There is rest 8 bits that can be used for whatever purpose. For example \ref x86::Mem operand uses +//! these bits to store segment override prefix and index shift (or scale). class BaseMem : public Operand { public: - //! \cond INTERNAL - //! Used internally to construct `BaseMem` operand from decomposed data. - struct Decomposed { - uint32_t baseType; - uint32_t baseId; - uint32_t indexType; - uint32_t indexId; - int32_t offset; - uint32_t size; - uint32_t flags; - }; - //! \endcond - //! \name Construction & Destruction //! \{ //! Creates a default `BaseMem` operand, that points to [0]. - constexpr BaseMem() noexcept - : Operand(Globals::Init, kOpMem, 0, 0, 0) {} + inline constexpr BaseMem() noexcept + : Operand(Globals::Init, Signature::fromOpType(OperandType::kMem), 0, 0, 0) {} //! Creates a `BaseMem` operand that is a clone of `other`. - constexpr BaseMem(const BaseMem& other) noexcept + inline constexpr BaseMem(const BaseMem& other) noexcept : Operand(other) {} //! Creates a `BaseMem` operand from `baseReg` and `offset`. //! - //! \note This is an architecture independent constructor that can be used to - //! create an architecture independent memory operand to be used in portable - //! code that can handle multiple architectures. - constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept + //! \note This is an architecture independent constructor that can be used to create an architecture + //! independent memory operand to be used in portable code that can handle multiple architectures. + inline constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept : Operand(Globals::Init, - kOpMem | (baseReg.type() << kSignatureMemBaseTypeShift), + Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(baseReg.type()), baseReg.id(), 0, uint32_t(offset)) {} //! \cond INTERNAL - //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct. - constexpr BaseMem(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand(Globals::Init, u0, u1, u2, u3) {} - - constexpr BaseMem(const Decomposed& d) noexcept - : Operand(Globals::Init, - kOpMem | (d.baseType << kSignatureMemBaseTypeShift ) - | (d.indexType << kSignatureMemIndexTypeShift) - | (d.size << kSignatureSizeShift ) - | d.flags, - d.baseId, - d.indexId, - uint32_t(d.offset)) {} - + inline constexpr BaseMem(const OperandSignature& u0, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept + : Operand(Globals::Init, u0, baseId, indexId, uint32_t(offset)) {} //! \endcond //! Creates a completely uninitialized `BaseMem` operand. @@ -1088,7 +1192,7 @@ public: //! Resets the memory operand - after the reset the memory points to [0]. inline void reset() noexcept { - _signature = kOpMem; + _signature = Signature::fromOpType(OperandType::kMem); _baseId = 0; _data[0] = 0; _data[1] = 0; @@ -1107,7 +1211,7 @@ public: //! \{ //! Clones the memory operand. - constexpr BaseMem clone() const noexcept { return BaseMem(*this); } + inline constexpr BaseMem clone() const noexcept { return BaseMem(*this); } //! Creates a new copy of this memory operand adjusted by `off`. inline BaseMem cloneAdjusted(int64_t off) const noexcept { @@ -1117,57 +1221,72 @@ public: } //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler) - constexpr bool isRegHome() const noexcept { return _hasSignaturePart<kSignatureMemRegHomeFlag>(); } + inline constexpr bool isRegHome() const noexcept { return _signature.hasField<Signature::kMemRegHomeFlag>(); } //! Mark this memory operand as register home (only used by \ref asmjit_compiler). - inline void setRegHome() noexcept { _signature |= kSignatureMemRegHomeFlag; } + inline void setRegHome() noexcept { _signature |= Signature::kMemRegHomeFlag; } //! Marks this operand to not be a register home (only used by \ref asmjit_compiler). - inline void clearRegHome() noexcept { _signature &= ~kSignatureMemRegHomeFlag; } + inline void clearRegHome() noexcept { _signature &= ~Signature::kMemRegHomeFlag; } //! Tests whether the memory operand has a BASE register or label specified. - constexpr bool hasBase() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0; } + inline constexpr bool hasBase() const noexcept { + return (_signature & Signature::kMemBaseTypeMask) != 0; + } + //! Tests whether the memory operand has an INDEX register specified. - constexpr bool hasIndex() const noexcept { return (_signature & kSignatureMemIndexTypeMask) != 0; } + inline constexpr bool hasIndex() const noexcept { + return (_signature & Signature::kMemIndexTypeMask) != 0; + } + //! Tests whether the memory operand has BASE or INDEX register. - constexpr bool hasBaseOrIndex() const noexcept { return (_signature & kSignatureMemBaseIndexMask) != 0; } + inline constexpr bool hasBaseOrIndex() const noexcept { + return (_signature & Signature::kMemBaseIndexMask) != 0; + } + //! Tests whether the memory operand has BASE and INDEX register. - constexpr bool hasBaseAndIndex() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0 && (_signature & kSignatureMemIndexTypeMask) != 0; } + inline constexpr bool hasBaseAndIndex() const noexcept { + return (_signature & Signature::kMemBaseTypeMask) != 0 && (_signature & Signature::kMemIndexTypeMask) != 0; + } - //! Tests whether the BASE operand is a register (registers start after `kLabelTag`). - constexpr bool hasBaseReg() const noexcept { return (_signature & kSignatureMemBaseTypeMask) > (Label::kLabelTag << kSignatureMemBaseTypeShift); } //! Tests whether the BASE operand is a label. - constexpr bool hasBaseLabel() const noexcept { return (_signature & kSignatureMemBaseTypeMask) == (Label::kLabelTag << kSignatureMemBaseTypeShift); } - //! Tests whether the INDEX operand is a register (registers start after `kLabelTag`). - constexpr bool hasIndexReg() const noexcept { return (_signature & kSignatureMemIndexTypeMask) > (Label::kLabelTag << kSignatureMemIndexTypeShift); } + inline constexpr bool hasBaseLabel() const noexcept { + return _signature.subset(Signature::kMemBaseTypeMask) == Signature::fromMemBaseType(RegType::kLabelTag); + } - //! Returns the type of the BASE register (0 if this memory operand doesn't - //! use the BASE register). + //! Tests whether the BASE operand is a register (registers start after `RegType::kLabelTag`). + inline constexpr bool hasBaseReg() const noexcept { + return _signature.subset(Signature::kMemBaseTypeMask).bits() > Signature::fromMemBaseType(RegType::kLabelTag).bits(); + } + + //! Tests whether the INDEX operand is a register (registers start after `RegType::kLabelTag`). + inline constexpr bool hasIndexReg() const noexcept { + return _signature.subset(Signature::kMemIndexTypeMask).bits() > Signature::fromMemIndexType(RegType::kLabelTag).bits(); + } + + //! Returns the type of the BASE register (0 if this memory operand doesn't use the BASE register). //! - //! \note If the returned type is one (a value never associated to a register - //! type) the BASE is not register, but it's a label. One equals to `kLabelTag`. - //! You should always check `hasBaseLabel()` before using `baseId()` result. - constexpr uint32_t baseType() const noexcept { return _getSignaturePart<kSignatureMemBaseTypeMask>(); } + //! \note If the returned type is one (a value never associated to a register type) the BASE is not register, but it + //! is a label. One equals to `kLabelTag`. You should always check `hasBaseLabel()` before using `baseId()` result. + inline constexpr RegType baseType() const noexcept { return _signature.memBaseType(); } //! Returns the type of an INDEX register (0 if this memory operand doesn't //! use the INDEX register). - constexpr uint32_t indexType() const noexcept { return _getSignaturePart<kSignatureMemIndexTypeMask>(); } + inline constexpr RegType indexType() const noexcept { return _signature.memIndexType(); } //! This is used internally for BASE+INDEX validation. - constexpr uint32_t baseAndIndexTypes() const noexcept { return _getSignaturePart<kSignatureMemBaseIndexMask>(); } + inline constexpr uint32_t baseAndIndexTypes() const noexcept { return _signature.getField<Signature::kMemBaseIndexMask>(); } - //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a - //! single value. + //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a single value. //! - //! \remarks Returns id of the BASE register or label (if the BASE was - //! specified as label). - constexpr uint32_t baseId() const noexcept { return _baseId; } + //! \remarks Returns id of the BASE register or label (if the BASE was specified as label). + inline constexpr uint32_t baseId() const noexcept { return _baseId; } //! Returns the id of the INDEX register. - constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; } + inline constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; } //! Sets the id of the BASE register (without modifying its type). - inline void setBaseId(uint32_t rId) noexcept { _baseId = rId; } + inline void setBaseId(uint32_t id) noexcept { _baseId = id; } //! Sets the id of the INDEX register (without modifying its type). - inline void setIndexId(uint32_t rId) noexcept { _data[kDataMemIndexId] = rId; } + inline void setIndexId(uint32_t id) noexcept { _data[kDataMemIndexId] = id; } //! Sets the base register to type and id of the given `base` operand. inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); } @@ -1175,56 +1294,54 @@ public: inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); } //! \cond INTERNAL - inline void _setBase(uint32_t rType, uint32_t rId) noexcept { - _setSignaturePart<kSignatureMemBaseTypeMask>(rType); - _baseId = rId; + inline void _setBase(RegType type, uint32_t id) noexcept { + _signature.setField<Signature::kMemBaseTypeMask>(uint32_t(type)); + _baseId = id; } - inline void _setIndex(uint32_t rType, uint32_t rId) noexcept { - _setSignaturePart<kSignatureMemIndexTypeMask>(rType); - _data[kDataMemIndexId] = rId; + inline void _setIndex(RegType type, uint32_t id) noexcept { + _signature.setField<Signature::kMemIndexTypeMask>(uint32_t(type)); + _data[kDataMemIndexId] = id; } //! \endcond //! Resets the memory operand's BASE register or label. - inline void resetBase() noexcept { _setBase(0, 0); } + inline void resetBase() noexcept { _setBase(RegType::kNone, 0); } //! Resets the memory operand's INDEX register. - inline void resetIndex() noexcept { _setIndex(0, 0); } + inline void resetIndex() noexcept { _setIndex(RegType::kNone, 0); } //! Sets the memory operand size (in bytes). - inline void setSize(uint32_t size) noexcept { _setSignaturePart<kSignatureSizeMask>(size); } + inline void setSize(uint32_t size) noexcept { _signature.setField<Signature::kSizeMask>(size); } //! Tests whether the memory operand has a 64-bit offset or absolute address. //! //! If this is true then `hasBase()` must always report false. - constexpr bool isOffset64Bit() const noexcept { return baseType() == 0; } + inline constexpr bool isOffset64Bit() const noexcept { return baseType() == RegType::kNone; } //! Tests whether the memory operand has a non-zero offset or absolute address. - constexpr bool hasOffset() const noexcept { + inline constexpr bool hasOffset() const noexcept { return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool<uint32_t>(isOffset64Bit()))) != 0; } //! Returns either relative offset or absolute address as 64-bit integer. - constexpr int64_t offset() const noexcept { + inline constexpr int64_t offset() const noexcept { return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32)) : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset. } //! Returns a 32-bit low part of a 64-bit offset or absolute address. - constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); } + inline constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); } //! Returns a 32-but high part of a 64-bit offset or absolute address. //! //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()` //! returns false. Never use it blindly without checking it first. - constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); } + inline constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); } //! Sets a 64-bit offset or an absolute address to `offset`. //! - //! \note This functions attempts to set both high and low parts of a 64-bit - //! offset, however, if the operand has a BASE register it will store only the - //! low 32 bits of the offset / address as there is no way to store both BASE - //! and 64-bit offset, and there is currently no architecture that has such - //! capability targeted by AsmJit. + //! \note This functions attempts to set both high and low parts of a 64-bit offset, however, if the operand has + //! a BASE register it will store only the low 32 bits of the offset / address as there is no way to store both + //! BASE and 64-bit offset, and there is currently no architecture that has such capability targeted by AsmJit. inline void setOffset(int64_t offset) noexcept { uint32_t lo = uint32_t(uint64_t(offset) & 0xFFFFFFFFu); uint32_t hi = uint32_t(uint64_t(offset) >> 32); @@ -1238,9 +1355,8 @@ public: //! Adjusts the offset by `offset`. //! - //! \note This is a fast function that doesn't use the HI 32-bits of a - //! 64-bit offset. Use it only if you know that there is a BASE register - //! and the offset is only 32 bits anyway. + //! \note This is a fast function that doesn't use the HI 32-bits of a 64-bit offset. Use it only if you know that + //! there is a BASE register and the offset is only 32 bits anyway. //! Adjusts the memory operand offset by a `offset`. inline void addOffset(int64_t offset) noexcept { @@ -1254,48 +1370,49 @@ public: } } - //! Adds `offset` to a low 32-bit offset part (don't use without knowing how - //! BaseMem works). + //! Adds `offset` to a low 32-bit offset part (don't use without knowing how BaseMem works). inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); } //! Resets the memory offset to zero. inline void resetOffset() noexcept { setOffset(0); } - //! Resets the lo part of the memory offset to zero (don't use without knowing - //! how BaseMem works). + //! Resets the lo part of the memory offset to zero (don't use without knowing how BaseMem works). inline void resetOffsetLo32() noexcept { setOffsetLo32(0); } //! \} }; -// ============================================================================ -// [asmjit::Imm] -// ============================================================================ +//! Type of the an immediate value. +enum class ImmType : uint32_t { + //! Immediate is integer. + kInt = 0, + //! Immediate is a floating point stored as double-precision. + kDouble = 1 +}; -//! Immediate operand. -//! -//! Immediate operand is usually part of instruction itself. It's inlined after -//! or before the instruction opcode. Immediates can be only signed or unsigned -//! integers. -//! -//! To create an immediate operand use `asmjit::imm()` helper, which can be used -//! with any type, not just the default 64-bit int. +//! Immediate operands are encoded with instruction data. class Imm : public Operand { public: - //! Type of the immediate. - enum Type : uint32_t { - //! Immediate is integer. - kTypeInteger = 0, - //! Immediate is a floating point stored as double-precision. - kTypeDouble = 1 - }; + //! \cond INTERNAL + template<typename T> + struct IsConstexprConstructibleAsImmType + : public std::integral_constant<bool, std::is_enum<T>::value || + std::is_pointer<T>::value || + std::is_integral<T>::value || + std::is_function<T>::value> {}; + + template<typename T> + struct IsConvertibleToImmType + : public std::integral_constant<bool, IsConstexprConstructibleAsImmType<T>::value || + std::is_floating_point<T>::value> {}; + //! \endcond //! \name Construction & Destruction //! \{ //! Creates a new immediate value (initial value is 0). inline constexpr Imm() noexcept - : Operand(Globals::Init, kOpImm, 0, 0, 0) {} + : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm), 0, 0, 0) {} //! Creates a new immediate value from `other`. inline constexpr Imm(const Imm& other) noexcept @@ -1303,27 +1420,37 @@ public: //! Creates a new immediate value from ARM/AArch64 specific `shift`. inline constexpr Imm(const arm::Shift& shift) noexcept - : Operand(Globals::Init, kOpImm | (shift.op() << kSignaturePredicateShift), + : Operand(Globals::Init, + Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(uint32_t(shift.op())), 0, Support::unpackU32At0(shift.value()), Support::unpackU32At1(shift.value())) {} - //! Creates a new signed immediate value, assigning the value to `val` and - //! an architecture-specific predicate to `predicate`. + //! Creates a new signed immediate value, assigning the value to `val` and an architecture-specific predicate + //! to `predicate`. //! //! \note Predicate is currently only used by ARM architectures. - template<typename T> + template<typename T, typename = typename std::enable_if<IsConstexprConstructibleAsImmType<typename std::decay<T>::type>::value>::type> inline constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept - : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), + : Operand(Globals::Init, + Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate), 0, Support::unpackU32At0(int64_t(val)), Support::unpackU32At1(int64_t(val))) {} inline Imm(const float& val, const uint32_t predicate = 0) noexcept - : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), 0, 0, 0) { setValue(val); } + : Operand(Globals::Init, + Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate), + 0, + 0, + 0) { setValue(val); } inline Imm(const double& val, const uint32_t predicate = 0) noexcept - : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), 0, 0, 0) { setValue(val); } + : Operand(Globals::Init, + Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate), + 0, + 0, + 0) { setValue(val); } inline explicit Imm(Globals::NoInit_) noexcept : Operand(Globals::NoInit) {} @@ -1341,75 +1468,74 @@ public: //! \name Accessors //! \{ - //! Returns immediate type, see \ref Type. - constexpr uint32_t type() const noexcept { return _getSignaturePart<kSignatureImmTypeMask>(); } - //! Sets the immediate type to `type`, see \ref Type. - inline void setType(uint32_t type) noexcept { _setSignaturePart<kSignatureImmTypeMask>(type); } - //! Resets immediate type to `kTypeInteger`. - inline void resetType() noexcept { setType(kTypeInteger); } + //! Returns immediate type. + inline constexpr ImmType type() const noexcept { return (ImmType)_signature.getField<Signature::kImmTypeMask>(); } + //! Sets the immediate type to `type`. + inline void setType(ImmType type) noexcept { _signature.setField<Signature::kImmTypeMask>(uint32_t(type)); } + //! Resets immediate type to \ref ImmType::kInt. + inline void resetType() noexcept { setType(ImmType::kInt); } //! Returns operation predicate of the immediate. //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the immediate. - constexpr uint32_t predicate() const noexcept { return _getSignaturePart<kSignaturePredicateMask>(); } + //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp + //! of the immediate. + inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); } //! Sets operation predicate of the immediate to `predicate`. //! - //! The meaning depends on architecture, for example on ARM hardware this - //! describes \ref arm::Predicate::ShiftOp of the immediate. - inline void setPredicate(uint32_t predicate) noexcept { _setSignaturePart<kSignaturePredicateMask>(predicate); } + //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp + //! of the immediate. + inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); } //! Resets the shift operation type of the immediate to the default value (no operation). - inline void resetPredicate() noexcept { _setSignaturePart<kSignaturePredicateMask>(0); } + inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); } //! Returns the immediate value as `int64_t`, which is the internal format Imm uses. - constexpr int64_t value() const noexcept { + inline constexpr int64_t value() const noexcept { return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]); } //! Tests whether this immediate value is integer of any size. - constexpr uint32_t isInteger() const noexcept { return type() == kTypeInteger; } + inline constexpr uint32_t isInt() const noexcept { return type() == ImmType::kInt; } //! Tests whether this immediate value is a double precision floating point value. - constexpr uint32_t isDouble() const noexcept { return type() == kTypeDouble; } + inline constexpr uint32_t isDouble() const noexcept { return type() == ImmType::kDouble; } //! Tests whether the immediate can be casted to 8-bit signed integer. - constexpr bool isInt8() const noexcept { return type() == kTypeInteger && Support::isInt8(value()); } + inline constexpr bool isInt8() const noexcept { return type() == ImmType::kInt && Support::isInt8(value()); } //! Tests whether the immediate can be casted to 8-bit unsigned integer. - constexpr bool isUInt8() const noexcept { return type() == kTypeInteger && Support::isUInt8(value()); } + inline constexpr bool isUInt8() const noexcept { return type() == ImmType::kInt && Support::isUInt8(value()); } //! Tests whether the immediate can be casted to 16-bit signed integer. - constexpr bool isInt16() const noexcept { return type() == kTypeInteger && Support::isInt16(value()); } + inline constexpr bool isInt16() const noexcept { return type() == ImmType::kInt && Support::isInt16(value()); } //! Tests whether the immediate can be casted to 16-bit unsigned integer. - constexpr bool isUInt16() const noexcept { return type() == kTypeInteger && Support::isUInt16(value()); } + inline constexpr bool isUInt16() const noexcept { return type() == ImmType::kInt && Support::isUInt16(value()); } //! Tests whether the immediate can be casted to 32-bit signed integer. - constexpr bool isInt32() const noexcept { return type() == kTypeInteger && Support::isInt32(value()); } + inline constexpr bool isInt32() const noexcept { return type() == ImmType::kInt && Support::isInt32(value()); } //! Tests whether the immediate can be casted to 32-bit unsigned integer. - constexpr bool isUInt32() const noexcept { return type() == kTypeInteger && _data[kDataImmValueHi] == 0; } + inline constexpr bool isUInt32() const noexcept { return type() == ImmType::kInt && _data[kDataImmValueHi] == 0; } //! Returns the immediate value casted to `T`. //! - //! The value is masked before it's casted to `T` so the returned value is - //! simply the representation of `T` considering the original value's lowest - //! bits. + //! The value is masked before it's casted to `T` so the returned value is simply the representation of `T` + //! considering the original value's lowest bits. template<typename T> inline T valueAs() const noexcept { return Support::immediateToT<T>(value()); } //! Returns low 32-bit signed integer. - constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); } + inline constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); } //! Returns high 32-bit signed integer. - constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); } + inline constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); } //! Returns low 32-bit signed integer. - constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; } + inline constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; } //! Returns high 32-bit signed integer. - constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; } + inline constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; } //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer. template<typename T> inline void setValue(const T& val) noexcept { - _setValueInternal(Support::immediateFromT(val), std::is_floating_point<T>::value ? kTypeDouble : kTypeInteger); + _setValueInternal(Support::immediateFromT(val), std::is_floating_point<T>::value ? ImmType::kDouble : ImmType::kInt); } - inline void _setValueInternal(int64_t val, uint32_t type) noexcept { + inline void _setValueInternal(int64_t val, ImmType type) noexcept { setType(type); _data[kDataImmValueHi] = uint32_t(uint64_t(val) >> 32); _data[kDataImmValueLo] = uint32_t(uint64_t(val) & 0xFFFFFFFFu); @@ -1421,7 +1547,7 @@ public: //! \{ //! Clones the immediate operand. - constexpr Imm clone() const noexcept { return Imm(*this); } + inline constexpr Imm clone() const noexcept { return Imm(*this); } inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs<int8_t>())); } inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs<int16_t>())); } @@ -1432,65 +1558,14 @@ public: inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; } //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use valueAs<int8_t>() instead") - inline int8_t i8() const noexcept { return valueAs<int8_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<uint8_t>() instead") - inline uint8_t u8() const noexcept { return valueAs<uint8_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<int16_t>() instead") - inline int16_t i16() const noexcept { return valueAs<int16_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<uint16_t>() instead") - inline uint16_t u16() const noexcept { return valueAs<uint16_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<int32_t>() instead") - inline int32_t i32() const noexcept { return valueAs<int32_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<uint32_t>() instead") - inline uint32_t u32() const noexcept { return valueAs<uint32_t>(); } - - ASMJIT_DEPRECATED("Use value() instead") - inline int64_t i64() const noexcept { return value(); } - - ASMJIT_DEPRECATED("Use valueAs<uint64_t>() instead") - inline uint64_t u64() const noexcept { return valueAs<uint64_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<intptr_t>() instead") - inline intptr_t iptr() const noexcept { return valueAs<intptr_t>(); } - - ASMJIT_DEPRECATED("Use valueAs<uintptr_t>() instead") - inline uintptr_t uptr() const noexcept { return valueAs<uintptr_t>(); } - - ASMJIT_DEPRECATED("Use int32Lo() instead") - inline int32_t i32Lo() const noexcept { return int32Lo(); } - - ASMJIT_DEPRECATED("Use uint32Lo() instead") - inline uint32_t u32Lo() const noexcept { return uint32Lo(); } - - ASMJIT_DEPRECATED("Use int32Hi() instead") - inline int32_t i32Hi() const noexcept { return int32Hi(); } - - ASMJIT_DEPRECATED("Use uint32Hi() instead") - inline uint32_t u32Hi() const noexcept { return uint32Hi(); } -#endif // !ASMJIT_NO_DEPRECATED }; //! Creates a new immediate operand. -//! -//! Using `imm(x)` is much nicer than using `Imm(x)` as this is a template -//! which can accept any integer including pointers and function pointers. template<typename T> -static constexpr Imm imm(const T& val) noexcept { return Imm(val); } +static inline constexpr Imm imm(const T& val) noexcept { return Imm(val); } //! \} -// ============================================================================ -// [asmjit::Globals::none] -// ============================================================================ - namespace Globals { //! \ingroup asmjit_assembler //! @@ -1498,31 +1573,25 @@ namespace Globals { static constexpr const Operand none; } -// ============================================================================ -// [asmjit::Support::ForwardOp] -// ============================================================================ - //! \cond INTERNAL namespace Support { -template<typename T, bool IsIntegral> +template<typename T, bool kIsImm> struct ForwardOpImpl { - static ASMJIT_INLINE const T& forward(const T& value) noexcept { return value; } + static inline const T& forward(const T& value) noexcept { return value; } }; template<typename T> struct ForwardOpImpl<T, true> { - static ASMJIT_INLINE Imm forward(const T& value) noexcept { return Imm(value); } + static inline Imm forward(const T& value) noexcept { return Imm(value); } }; -//! Either forwards operand T or returns a new operand for T if T is a type -//! convertible to operand. At the moment this is only used to convert integers -//! to \ref Imm operands. +//! Either forwards operand T or returns a new operand that wraps it if T is a type convertible to operand. +//! At the moment this is only used to convert integers, floats, and enumarations to \ref Imm operands. template<typename T> -struct ForwardOp : public ForwardOpImpl<T, std::is_integral<typename std::decay<T>::type>::value> {}; - -} +struct ForwardOp : public ForwardOpImpl<T, Imm::IsConvertibleToImmType<typename std::decay<T>::type>::value> {}; +} // {Support} //! \endcond ASMJIT_END_NAMESPACE diff --git a/src/asmjit/core/osutils.cpp b/src/asmjit/core/osutils.cpp index e2f34ef..fa900bf 100644 --- a/src/asmjit/core/osutils.cpp +++ b/src/asmjit/core/osutils.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/osutils.h" @@ -36,10 +18,6 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::OSUtils - GetTickCount] -// ============================================================================ - uint32_t OSUtils::getTickCount() noexcept { #if defined(_WIN32) enum HiResStatus : uint32_t { diff --git a/src/asmjit/core/osutils.h b/src/asmjit/core/osutils.h index a469129..3c5c3d9 100644 --- a/src/asmjit/core/osutils.h +++ b/src/asmjit/core/osutils.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_OSUTILS_H_INCLUDED #define ASMJIT_CORE_OSUTILS_H_INCLUDED @@ -31,22 +13,14 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_utilities //! \{ -// ============================================================================ -// [asmjit::OSUtils] -// ============================================================================ - //! Operating system utilities. namespace OSUtils { //! Gets the current CPU tick count, used for benchmarking (1ms resolution). ASMJIT_API uint32_t getTickCount() noexcept; }; -// ============================================================================ -// [asmjit::Lock] -// ============================================================================ //! \cond INTERNAL - //! Lock. //! //! Lock is internal, it cannot be used outside of AsmJit, however, its internal @@ -72,11 +46,11 @@ public: Handle _handle; #endif - inline Lock() noexcept; - inline ~Lock() noexcept; + ASMJIT_FORCE_INLINE Lock() noexcept; + ASMJIT_FORCE_INLINE ~Lock() noexcept; - inline void lock() noexcept; - inline void unlock() noexcept; + ASMJIT_FORCE_INLINE void lock() noexcept; + ASMJIT_FORCE_INLINE void unlock() noexcept; }; //! \endcond diff --git a/src/asmjit/core/osutils_p.h b/src/asmjit/core/osutils_p.h index 31db308..fd87e73 100644 --- a/src/asmjit/core/osutils_p.h +++ b/src/asmjit/core/osutils_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_OSUTILS_P_H_INCLUDED #define ASMJIT_CORE_OSUTILS_P_H_INCLUDED @@ -32,47 +14,39 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_utilities //! \{ -// ============================================================================ -// [asmjit::Lock] -// ============================================================================ - #if defined(_WIN32) // Windows implementation. static_assert(sizeof(Lock::Handle) == sizeof(CRITICAL_SECTION), "asmjit::Lock::Handle layout must match CRITICAL_SECTION"); static_assert(alignof(Lock::Handle) == alignof(CRITICAL_SECTION), "asmjit::Lock::Handle alignment must match CRITICAL_SECTION"); -inline Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } -inline Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } -inline void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } -inline void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_FORCE_INLINE Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_FORCE_INLINE Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_FORCE_INLINE void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } +ASMJIT_FORCE_INLINE void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); } #elif !defined(__EMSCRIPTEN__) // PThread implementation. #ifdef PTHREAD_MUTEX_INITIALIZER -inline Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {} +ASMJIT_FORCE_INLINE Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {} #else -inline Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); } +ASMJIT_FORCE_INLINE Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); } #endif -inline Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); } -inline void Lock::lock() noexcept { pthread_mutex_lock(&_handle); } -inline void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); } +ASMJIT_FORCE_INLINE Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); } +ASMJIT_FORCE_INLINE void Lock::lock() noexcept { pthread_mutex_lock(&_handle); } +ASMJIT_FORCE_INLINE void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); } #else // Dummy implementation - Emscripten or other unsupported platform. -inline Lock::Lock() noexcept {} -inline Lock::~Lock() noexcept {} -inline void Lock::lock() noexcept {} -inline void Lock::unlock() noexcept {} +ASMJIT_FORCE_INLINE Lock::Lock() noexcept {} +ASMJIT_FORCE_INLINE Lock::~Lock() noexcept {} +ASMJIT_FORCE_INLINE void Lock::lock() noexcept {} +ASMJIT_FORCE_INLINE void Lock::unlock() noexcept {} #endif -// ============================================================================ -// [asmjit::LockGuard] -// ============================================================================ - //! Scoped lock. class LockGuard { public: diff --git a/src/asmjit/core/raassignment_p.h b/src/asmjit/core/raassignment_p.h index 6b5df54..22a97e2 100644 --- a/src/asmjit/core/raassignment_p.h +++ b/src/asmjit/core/raassignment_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED #define ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED @@ -35,10 +17,12 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [asmjit::RAAssignment] -// ============================================================================ - +//! Holds the current register assignment. +//! +//! Has two purposes: +//! +//! 1. Holds register assignment of a local register allocator (see \ref RALocalAllocator). +//! 2. Holds register assignment of the entry of basic blocks (see \ref RABlock). class RAAssignment { public: ASMJIT_NONCOPYABLE(RAAssignment) @@ -120,6 +104,9 @@ public: } }; + //! \name Members + //! \{ + //! Physical registers layout. Layout _layout; //! WorkReg to PhysReg mapping. @@ -127,7 +114,9 @@ public: //! PhysReg to WorkReg mapping and assigned/dirty bits. PhysToWorkMap* _physToWorkMap; //! Optimization to translate PhysRegs to WorkRegs faster. - uint32_t* _physToWorkIds[BaseReg::kGroupVirt]; + Support::Array<uint32_t*, Globals::kNumVirtGroups> _physToWorkIds; + + //! \} //! \name Construction & Destruction //! \{ @@ -137,31 +126,30 @@ public: resetMaps(); } - inline void initLayout(const RARegCount& physCount, const RAWorkRegs& workRegs) noexcept { + ASMJIT_FORCE_INLINE void initLayout(const RARegCount& physCount, const RAWorkRegs& workRegs) noexcept { // Layout must be initialized before data. ASMJIT_ASSERT(_physToWorkMap == nullptr); ASMJIT_ASSERT(_workToPhysMap == nullptr); _layout.physIndex.buildIndexes(physCount); _layout.physCount = physCount; - _layout.physTotal = uint32_t(_layout.physIndex[BaseReg::kGroupVirt - 1]) + - uint32_t(_layout.physCount[BaseReg::kGroupVirt - 1]) ; + _layout.physTotal = uint32_t(_layout.physIndex[RegGroup::kMaxVirt]) + + uint32_t(_layout.physCount[RegGroup::kMaxVirt]) ; _layout.workCount = workRegs.size(); _layout.workRegs = &workRegs; } - inline void initMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { + ASMJIT_FORCE_INLINE void initMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { _physToWorkMap = physToWorkMap; _workToPhysMap = workToPhysMap; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) + for (RegGroup group : RegGroupVirtValues{}) _physToWorkIds[group] = physToWorkMap->workIds + _layout.physIndex.get(group); } - inline void resetMaps() noexcept { + ASMJIT_FORCE_INLINE void resetMaps() noexcept { _physToWorkMap = nullptr; _workToPhysMap = nullptr; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _physToWorkIds[group] = nullptr; + _physToWorkIds.fill(nullptr); } //! \} @@ -174,30 +162,30 @@ public: inline RARegMask& assigned() noexcept { return _physToWorkMap->assigned; } inline const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; } - inline uint32_t assigned(uint32_t group) const noexcept { return _physToWorkMap->assigned[group]; } + inline uint32_t assigned(RegGroup group) const noexcept { return _physToWorkMap->assigned[group]; } inline RARegMask& dirty() noexcept { return _physToWorkMap->dirty; } inline const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; } - inline uint32_t dirty(uint32_t group) const noexcept { return _physToWorkMap->dirty[group]; } + inline RegMask dirty(RegGroup group) const noexcept { return _physToWorkMap->dirty[group]; } - inline uint32_t workToPhysId(uint32_t group, uint32_t workId) const noexcept { + inline uint32_t workToPhysId(RegGroup group, uint32_t workId) const noexcept { DebugUtils::unused(group); ASMJIT_ASSERT(workId != kWorkNone); ASMJIT_ASSERT(workId < _layout.workCount); return _workToPhysMap->physIds[workId]; } - inline uint32_t physToWorkId(uint32_t group, uint32_t physId) const noexcept { + inline uint32_t physToWorkId(RegGroup group, uint32_t physId) const noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); return _physToWorkIds[group][physId]; } - inline bool isPhysAssigned(uint32_t group, uint32_t physId) const noexcept { + inline bool isPhysAssigned(RegGroup group, uint32_t physId) const noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); return Support::bitTest(_physToWorkMap->assigned[group], physId); } - inline bool isPhysDirty(uint32_t group, uint32_t physId) const noexcept { + inline bool isPhysDirty(RegGroup group, uint32_t physId) const noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); return Support::bitTest(_physToWorkMap->dirty[group], physId); } @@ -205,15 +193,15 @@ public: //! \} //! \name Assignment + //! + //! These are low-level allocation helpers that are used to update the current mappings between physical and + //! virt/work registers and also to update masks that represent allocated and dirty registers. These functions + //! don't emit any code; they are only used to update and keep all mappings in sync. + //! //! \{ - // These are low-level allocation helpers that are used to update the current - // mappings between physical and virt/work registers and also to update masks - // that represent allocated and dirty registers. These functions don't emit - // any code; they are only used to update and keep all mappings in sync. - //! Assign [VirtReg/WorkReg] to a physical register. - ASMJIT_INLINE void assign(uint32_t group, uint32_t workId, uint32_t physId, uint32_t dirty) noexcept { + inline void assign(RegGroup group, uint32_t workId, uint32_t physId, bool dirty) noexcept { ASMJIT_ASSERT(workToPhysId(group, workId) == kPhysNone); ASMJIT_ASSERT(physToWorkId(group, physId) == kWorkNone); ASMJIT_ASSERT(!isPhysAssigned(group, physId)); @@ -222,15 +210,15 @@ public: _workToPhysMap->physIds[workId] = uint8_t(physId); _physToWorkIds[group][physId] = workId; - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->assigned[group] |= regMask; - _physToWorkMap->dirty[group] |= regMask & Support::bitMaskFromBool<uint32_t>(dirty); + _physToWorkMap->dirty[group] |= regMask & Support::bitMaskFromBool<RegMask>(dirty); verify(); } //! Reassign [VirtReg/WorkReg] to `dstPhysId` from `srcPhysId`. - ASMJIT_INLINE void reassign(uint32_t group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { + inline void reassign(RegGroup group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { ASMJIT_ASSERT(dstPhysId != srcPhysId); ASMJIT_ASSERT(workToPhysId(group, workId) == srcPhysId); ASMJIT_ASSERT(physToWorkId(group, srcPhysId) == workId); @@ -241,19 +229,19 @@ public: _physToWorkIds[group][srcPhysId] = kWorkNone; _physToWorkIds[group][dstPhysId] = workId; - uint32_t srcMask = Support::bitMask(srcPhysId); - uint32_t dstMask = Support::bitMask(dstPhysId); + RegMask srcMask = Support::bitMask(srcPhysId); + RegMask dstMask = Support::bitMask(dstPhysId); - uint32_t dirty = (_physToWorkMap->dirty[group] & srcMask) != 0; - uint32_t regMask = dstMask | srcMask; + bool dirty = (_physToWorkMap->dirty[group] & srcMask) != 0; + RegMask regMask = dstMask | srcMask; _physToWorkMap->assigned[group] ^= regMask; - _physToWorkMap->dirty[group] ^= regMask & Support::bitMaskFromBool<uint32_t>(dirty); + _physToWorkMap->dirty[group] ^= regMask & Support::bitMaskFromBool<RegMask>(dirty); verify(); } - ASMJIT_INLINE void swap(uint32_t group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { + inline void swap(RegGroup group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { ASMJIT_ASSERT(aPhysId != bPhysId); ASMJIT_ASSERT(workToPhysId(group, aWorkId) == aPhysId); ASMJIT_ASSERT(workToPhysId(group, bWorkId) == bPhysId); @@ -267,21 +255,17 @@ public: _physToWorkIds[group][aPhysId] = bWorkId; _physToWorkIds[group][bPhysId] = aWorkId; - uint32_t aMask = Support::bitMask(aPhysId); - uint32_t bMask = Support::bitMask(bPhysId); - - uint32_t flipMask = Support::bitMaskFromBool<uint32_t>( - ((_physToWorkMap->dirty[group] & aMask) != 0) ^ - ((_physToWorkMap->dirty[group] & bMask) != 0)); - - uint32_t regMask = aMask | bMask; + RegMask aMask = Support::bitMask(aPhysId); + RegMask bMask = Support::bitMask(bPhysId); + RegMask flipMask = Support::bitMaskFromBool<RegMask>(((_physToWorkMap->dirty[group] & aMask) != 0) ^ ((_physToWorkMap->dirty[group] & bMask) != 0)); + RegMask regMask = aMask | bMask; _physToWorkMap->dirty[group] ^= regMask & flipMask; verify(); } //! Unassign [VirtReg/WorkReg] from a physical register. - ASMJIT_INLINE void unassign(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline void unassign(RegGroup group, uint32_t workId, uint32_t physId) noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); ASMJIT_ASSERT(workToPhysId(group, workId) == physId); ASMJIT_ASSERT(physToWorkId(group, physId) == workId); @@ -290,22 +274,22 @@ public: _workToPhysMap->physIds[workId] = kPhysNone; _physToWorkIds[group][physId] = kWorkNone; - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->assigned[group] &= ~regMask; _physToWorkMap->dirty[group] &= ~regMask; verify(); } - inline void makeClean(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline void makeClean(RegGroup group, uint32_t workId, uint32_t physId) noexcept { DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->dirty[group] &= ~regMask; } - inline void makeDirty(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline void makeDirty(RegGroup group, uint32_t workId, uint32_t physId) noexcept { DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->dirty[group] |= regMask; } @@ -314,12 +298,10 @@ public: //! \name Utilities //! \{ - inline void swap(RAAssignment& other) noexcept { + ASMJIT_FORCE_INLINE void swap(RAAssignment& other) noexcept { std::swap(_workToPhysMap, other._workToPhysMap); std::swap(_physToWorkMap, other._physToWorkMap); - - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - std::swap(_physToWorkIds[group], other._physToWorkIds[group]); + _physToWorkIds.swap(other._physToWorkIds); } inline void copyFrom(const PhysToWorkMap* physToWorkMap, const WorkToPhysMap* workToPhysMap) noexcept { @@ -373,7 +355,7 @@ public: uint32_t physId = _workToPhysMap->physIds[workId]; if (physId != kPhysNone) { const RAWorkReg* workReg = _layout.workRegs->at(workId); - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); ASMJIT_ASSERT(_physToWorkIds[group][physId] == workId); } } @@ -381,7 +363,7 @@ public: // Verify PhysToWorkMap. { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { uint32_t physCount = _layout.physCount[group]; for (uint32_t physId = 0; physId < physCount; physId++) { uint32_t workId = _physToWorkIds[group][physId]; diff --git a/src/asmjit/core/rabuilders_p.h b/src/asmjit/core/rabuilders_p.h index 3d387a0..1b76303 100644 --- a/src/asmjit/core/rabuilders_p.h +++ b/src/asmjit/core/rabuilders_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RABUILDERS_P_H_INCLUDED #define ASMJIT_CORE_RABUILDERS_P_H_INCLUDED @@ -36,13 +18,22 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [asmjit::RACFGBuilderT] -// ============================================================================ - template<typename This> class RACFGBuilderT { public: + enum : uint32_t { + kRootIndentation = 2, + kCodeIndentation = 4, + + // NOTE: This is a bit hacky. There are some nodes which are processed twice (see `onBeforeInvoke()` and + // `onBeforeRet()`) as they can insert some nodes around them. Since we don't have any flags to mark these + // we just use their position that is [at that time] unassigned. + kNodePositionDidOnBefore = 0xFFFFFFFFu + }; + + //! \name Members + //! \{ + BaseRAPass* _pass = nullptr; BaseCompiler* _cc = nullptr; RABlock* _curBlock = nullptr; @@ -58,38 +49,30 @@ public: #ifndef ASMJIT_NO_LOGGING Logger* _logger = nullptr; - uint32_t _logFlags = FormatOptions::kFlagPositions; + FormatOptions _formatOptions {}; StringTmp<512> _sb; #endif - static constexpr uint32_t kRootIndentation = 2; - static constexpr uint32_t kCodeIndentation = 4; - - // NOTE: This is a bit hacky. There are some nodes which are processed twice - // (see `onBeforeInvoke()` and `onBeforeRet()`) as they can insert some nodes - // around them. Since we don't have any flags to mark these we just use their - // position that is [at that time] unassigned. - static constexpr uint32_t kNodePositionDidOnBefore = 0xFFFFFFFFu; + //! \} inline RACFGBuilderT(BaseRAPass* pass) noexcept : _pass(pass), _cc(pass->cc()) { #ifndef ASMJIT_NO_LOGGING - _logger = _pass->debugLogger(); + _logger = _pass->hasDiagnosticOption(DiagnosticOptions::kRADebugCFG) ? _pass->logger() : nullptr; if (_logger) - _logFlags |= _logger->flags(); + _formatOptions = _logger->options(); #endif } inline BaseCompiler* cc() const noexcept { return _cc; } - // -------------------------------------------------------------------------- - // [Run] - // -------------------------------------------------------------------------- + //! \name Run + //! \{ //! Called per function by an architecture-specific CFG builder. Error run() noexcept { - log("[RAPass::BuildCFG]\n"); + log("[BuildCFG]\n"); ASMJIT_PROPAGATE(prepare()); logNode(_funcNode, kRootIndentation); @@ -114,12 +97,11 @@ public: // Instruction | Jump | Invoke | Return // ------------------------------------ - // Handle `InstNode`, `InvokeNode`, and `FuncRetNode`. All of them - // share the same interface that provides operands that have read/write - // semantics. + // Handle `InstNode`, `InvokeNode`, and `FuncRetNode`. All of them share the same interface that provides + // operands that have read/write semantics. if (ASMJIT_UNLIKELY(!_curBlock)) { - // Unreachable code has to be removed, we cannot allocate registers - // in such code as we cannot do proper liveness analysis in such case. + // Unreachable code has to be removed, we cannot allocate registers in such code as we cannot do proper + // liveness analysis in such case. removeNode(node); node = next; continue; @@ -129,15 +111,13 @@ public: if (node->isInvoke() || node->isFuncRet()) { if (node->position() != kNodePositionDidOnBefore) { - // Call and Reg are complicated as they may insert some surrounding - // code around them. The simplest approach is to get the previous - // node, call the `onBefore()` handlers and then check whether - // anything changed and restart if so. By restart we mean that the - // current `node` would go back to the first possible inserted node - // by `onBeforeInvoke()` or `onBeforeRet()`. + // Call and Reg are complicated as they may insert some surrounding code around them. The simplest + // approach is to get the previous node, call the `onBefore()` handlers and then check whether + // anything changed and restart if so. By restart we mean that the current `node` would go back to + // the first possible inserted node by `onBeforeInvoke()` or `onBeforeRet()`. BaseNode* prev = node->prev(); - if (node->type() == BaseNode::kNodeInvoke) + if (node->type() == NodeType::kInvoke) ASMJIT_PROPAGATE(static_cast<This*>(this)->onBeforeInvoke(node->as<InvokeNode>())); else ASMJIT_PROPAGATE(static_cast<This*>(this)->onBeforeRet(node->as<FuncRetNode>())); @@ -167,9 +147,9 @@ public: InstNode* inst = node->as<InstNode>(); logNode(inst, kCodeIndentation); - uint32_t controlType = BaseInst::kControlNone; + InstControlFlow cf = InstControlFlow::kRegular; ib.reset(); - ASMJIT_PROPAGATE(static_cast<This*>(this)->onInst(inst, controlType, ib)); + ASMJIT_PROPAGATE(static_cast<This*>(this)->onInst(inst, cf, ib)); if (node->isInvoke()) { ASMJIT_PROPAGATE(static_cast<This*>(this)->onInvoke(inst->as<InvokeNode>(), ib)); @@ -177,20 +157,20 @@ public: if (node->isFuncRet()) { ASMJIT_PROPAGATE(static_cast<This*>(this)->onRet(inst->as<FuncRetNode>(), ib)); - controlType = BaseInst::kControlReturn; + cf = InstControlFlow::kReturn; } - if (controlType == BaseInst::kControlJump) { + if (cf == InstControlFlow::kJump) { uint32_t fixedRegCount = 0; for (RATiedReg& tiedReg : ib) { RAWorkReg* workReg = _pass->workRegById(tiedReg.workId()); - if (workReg->group() == BaseReg::kGroupGp) { + if (workReg->group() == RegGroup::kGp) { uint32_t useId = tiedReg.useId(); if (useId == BaseReg::kIdBad) { useId = _pass->_scratchRegIndexes[fixedRegCount++]; tiedReg.setUseId(useId); } - _curBlock->addExitScratchGpRegs(Support::bitMask<uint32_t>(useId)); + _curBlock->addExitScratchGpRegs(Support::bitMask(useId)); } } } @@ -198,14 +178,14 @@ public: ASMJIT_PROPAGATE(_pass->assignRAInst(inst, _curBlock, ib)); _blockRegStats.combineWith(ib._stats); - if (controlType != BaseInst::kControlNone) { + if (cf != InstControlFlow::kRegular) { // Support for conditional and unconditional jumps. - if (controlType == BaseInst::kControlJump || controlType == BaseInst::kControlBranch) { + if (cf == InstControlFlow::kJump || cf == InstControlFlow::kBranch) { _curBlock->setLast(node); - _curBlock->addFlags(RABlock::kFlagHasTerminator); + _curBlock->addFlags(RABlockFlags::kHasTerminator); _curBlock->makeConstructed(_blockRegStats); - if (!(inst->instOptions() & BaseInst::kOptionUnfollow)) { + if (!inst->hasOption(InstOptions::kUnfollow)) { // Jmp/Jcc/Call/Loop/etc... uint32_t opCount = inst->opCount(); const Operand* opArray = inst->operands(); @@ -227,14 +207,13 @@ public: ASMJIT_PROPAGATE(_curBlock->appendSuccessor(targetBlock)); } else { - // Not a label - could be jump with reg/mem operand, which - // means that it can go anywhere. Such jumps must either be - // annotated so the CFG can be properly constructed, otherwise - // we assume the worst case - can jump to any basic block. + // Not a label - could be jump with reg/mem operand, which means that it can go anywhere. Such jumps + // must either be annotated so the CFG can be properly constructed, otherwise we assume the worst case + // - can jump to any basic block. JumpAnnotation* jumpAnnotation = nullptr; - _curBlock->addFlags(RABlock::kFlagHasJumpTable); + _curBlock->addFlags(RABlockFlags::kHasJumpTable); - if (inst->type() == BaseNode::kNodeJump) + if (inst->type() == NodeType::kJump) jumpAnnotation = inst->as<JumpNode>()->annotation(); if (jumpAnnotation) { @@ -262,13 +241,11 @@ public: } } - if (controlType == BaseInst::kControlJump) { - // Unconditional jump makes the code after the jump unreachable, - // which will be removed instantly during the CFG construction; - // as we cannot allocate registers for instructions that are not - // part of any block. Of course we can leave these instructions - // as they are, however, that would only postpone the problem as - // assemblers can't encode instructions that use virtual registers. + if (cf == InstControlFlow::kJump) { + // Unconditional jump makes the code after the jump unreachable, which will be removed instantly during + // the CFG construction; as we cannot allocate registers for instructions that are not part of any block. + // Of course we can leave these instructions as they are, however, that would only postpone the problem + // as assemblers can't encode instructions that use virtual registers. _curBlock = nullptr; } else { @@ -277,7 +254,7 @@ public: return DebugUtils::errored(kErrorInvalidState); RABlock* consecutiveBlock; - if (node->type() == BaseNode::kNodeLabel) { + if (node->type() == NodeType::kLabel) { if (node->hasPassData()) { consecutiveBlock = node->passData<RABlock>(); } @@ -294,7 +271,7 @@ public: return DebugUtils::errored(kErrorOutOfMemory); } - _curBlock->addFlags(RABlock::kFlagHasConsecutive); + _curBlock->addFlags(RABlockFlags::kHasConsecutive); ASMJIT_PROPAGATE(_curBlock->prependSuccessor(consecutiveBlock)); _curBlock = consecutiveBlock; @@ -310,7 +287,7 @@ public: } } - if (controlType == BaseInst::kControlReturn) { + if (cf == InstControlFlow::kReturn) { _curBlock->setLast(node); _curBlock->makeConstructed(_blockRegStats); ASMJIT_PROPAGATE(_curBlock->appendSuccessor(_retBlock)); @@ -319,19 +296,18 @@ public: } } } - else if (node->type() == BaseNode::kNodeLabel) { + else if (node->type() == NodeType::kLabel) { // Label - Basic-Block Management // ------------------------------ if (!_curBlock) { - // If the current code is unreachable the label makes it reachable - // again. We may remove the whole block in the future if it's not - // referenced though. + // If the current code is unreachable the label makes it reachable again. We may remove the whole block in + // the future if it's not referenced though. _curBlock = node->passData<RABlock>(); if (_curBlock) { - // If the label has a block assigned we can either continue with - // it or skip it if the block has been constructed already. + // If the label has a block assigned we can either continue with it or skip it if the block has been + // constructed already. if (_curBlock->isConstructed()) break; } @@ -354,20 +330,18 @@ public: consecutive->makeTargetable(); if (_curBlock == consecutive) { - // The label currently processed is part of the current block. This - // is only possible for multiple labels that are right next to each - // other or labels that are separated by non-code nodes like directives - // and comments. + // The label currently processed is part of the current block. This is only possible for multiple labels + // that are right next to each other or labels that are separated by non-code nodes like directives and + // comments. if (ASMJIT_UNLIKELY(_hasCode)) return DebugUtils::errored(kErrorInvalidState); } else { - // Label makes the current block constructed. There is a chance that the - // Label is not used, but we don't know that at this point. In the worst - // case there would be two blocks next to each other, it's just fine. + // Label makes the current block constructed. There is a chance that the Label is not used, but we don't + // know that at this point. In the worst case there would be two blocks next to each other, it's just fine. ASMJIT_ASSERT(_curBlock->last() != node); _curBlock->setLast(node->prev()); - _curBlock->addFlags(RABlock::kFlagHasConsecutive); + _curBlock->addFlags(RABlockFlags::kHasConsecutive); _curBlock->makeConstructed(_blockRegStats); ASMJIT_PROPAGATE(_curBlock->appendSuccessor(consecutive)); @@ -381,12 +355,11 @@ public: else { // First time we see this label. if (_hasCode || _curBlock == entryBlock) { - // Cannot continue the current block if it already contains some - // code or it's a block entry. We need to create a new block and - // make it a successor. + // Cannot continue the current block if it already contains some code or it's a block entry. We need to + // create a new block and make it a successor. ASMJIT_ASSERT(_curBlock->last() != node); _curBlock->setLast(node->prev()); - _curBlock->addFlags(RABlock::kFlagHasConsecutive); + _curBlock->addFlags(RABlockFlags::kHasConsecutive); _curBlock->makeConstructed(_blockRegStats); RABlock* consecutive = _pass->newBlock(node); @@ -425,7 +398,7 @@ public: logNode(node, kCodeIndentation); - if (node->type() == BaseNode::kNodeSentinel) { + if (node->type() == NodeType::kSentinel) { if (node == _funcNode->endNode()) { // Make sure we didn't flow here if this is the end of the function sentinel. if (ASMJIT_UNLIKELY(_curBlock)) @@ -433,7 +406,7 @@ public: break; } } - else if (node->type() == BaseNode::kNodeFunc) { + else if (node->type() == NodeType::kFunc) { // RAPass can only compile a single function at a time. If we // encountered a function it must be the current one, bail if not. if (ASMJIT_UNLIKELY(node != _funcNode)) @@ -448,10 +421,9 @@ public: // Advance to the next node. node = next; - // NOTE: We cannot encounter a NULL node, because every function must be - // terminated by a sentinel (`stop`) node. If we encountered a NULL node it - // means that something went wrong and this node list is corrupted; bail in - // such case. + // NOTE: We cannot encounter a NULL node, because every function must be terminated by a sentinel (`stop`) + // node. If we encountered a NULL node it means that something went wrong and this node list is corrupted; + // bail in such case. if (ASMJIT_UNLIKELY(!node)) return DebugUtils::errored(kErrorInvalidState); } @@ -465,9 +437,10 @@ public: return _pass->initSharedAssignments(_sharedAssignmentsMap); } - // -------------------------------------------------------------------------- - // [Prepare] - // -------------------------------------------------------------------------- + //! \} + + //! \name Prepare + //! \{ //! Prepares the CFG builder of the current function. Error prepare() noexcept { @@ -504,9 +477,10 @@ public: return _pass->addBlock(_curBlock); } - // -------------------------------------------------------------------------- - // [Utilities] - // -------------------------------------------------------------------------- + //! \} + + //! \name Utilities + //! \{ //! Called when a `node` is removed, e.g. because of a dead code elimination. void removeNode(BaseNode* node) noexcept { @@ -516,9 +490,8 @@ public: //! Handles block with unknown jump, which could be a jump to a jump table. //! - //! If we encounter such block we basically insert all existing blocks as - //! successors except the function entry block and a natural successor, if - //! such block exists. + //! If we encounter such block we basically insert all existing blocks as successors except the function entry + //! block and a natural successor, if such block exists. Error handleBlockWithUnknownJump(RABlock* block) noexcept { RABlocks& blocks = _pass->blocks(); size_t blockCount = blocks.size(); @@ -570,9 +543,10 @@ public: return kErrorOk; } - // -------------------------------------------------------------------------- - // [Logging] - // -------------------------------------------------------------------------- + //! \} + + //! \name Logging + //! \{ #ifndef ASMJIT_NO_LOGGING template<typename... Args> @@ -606,7 +580,7 @@ public: _sb.append(action); _sb.append(' '); } - Formatter::formatNode(_sb, _logFlags, cc(), node); + Formatter::formatNode(_sb, _formatOptions, cc(), node); _sb.append('\n'); _logger->log(_sb); } @@ -625,6 +599,8 @@ public: DebugUtils::unused(node, indentation, action); } #endif + + //! \} }; //! \} diff --git a/src/asmjit/core/radefs_p.h b/src/asmjit/core/radefs_p.h index 53d2c71..426ac29 100644 --- a/src/asmjit/core/radefs_p.h +++ b/src/asmjit/core/radefs_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RADEFS_P_H_INCLUDED #define ASMJIT_CORE_RADEFS_P_H_INCLUDED @@ -40,10 +22,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [Logging] -// ============================================================================ - #ifndef ASMJIT_NO_LOGGING # define ASMJIT_RA_LOG_FORMAT(...) \ do { \ @@ -61,10 +39,6 @@ ASMJIT_BEGIN_NAMESPACE # define ASMJIT_RA_LOG_COMPLEX(...) ((void)0) #endif -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class BaseRAPass; class RABlock; class BaseNode; @@ -73,33 +47,36 @@ struct RAStackSlot; typedef ZoneVector<RABlock*> RABlocks; typedef ZoneVector<RAWorkReg*> RAWorkRegs; -// ============================================================================ -// [asmjit::RAConstraints] -// ============================================================================ +//! Maximum number of consecutive registers aggregated from all supported backends. +static constexpr uint32_t kMaxConsecutiveRegs = 4; +//! Provides architecture constraints used by register allocator. class RAConstraints { public: - uint32_t _availableRegs[BaseReg::kGroupVirt] {}; + //! \name Members + //! \{ + + Support::Array<RegMask, Globals::kNumVirtGroups> _availableRegs {}; - inline RAConstraints() noexcept {} + //! \} - ASMJIT_NOINLINE Error init(uint32_t arch) noexcept { + ASMJIT_NOINLINE Error init(Arch arch) noexcept { switch (arch) { - case Environment::kArchX86: - case Environment::kArchX64: { - uint32_t registerCount = arch == Environment::kArchX86 ? 8 : 16; - _availableRegs[BaseReg::kGroupGp] = Support::lsbMask<uint32_t>(registerCount) & ~Support::bitMask(4u); - _availableRegs[BaseReg::kGroupVec] = Support::lsbMask<uint32_t>(registerCount); - _availableRegs[BaseReg::kGroupOther0] = Support::lsbMask<uint32_t>(8); - _availableRegs[BaseReg::kGroupOther1] = Support::lsbMask<uint32_t>(8); + case Arch::kX86: + case Arch::kX64: { + uint32_t registerCount = arch == Arch::kX86 ? 8 : 16; + _availableRegs[RegGroup::kGp] = Support::lsbMask<RegMask>(registerCount) & ~Support::bitMask(4u); + _availableRegs[RegGroup::kVec] = Support::lsbMask<RegMask>(registerCount); + _availableRegs[RegGroup::kExtraVirt2] = Support::lsbMask<RegMask>(8); + _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<RegMask>(8); return kErrorOk; } - case Environment::kArchAArch64: { - _availableRegs[BaseReg::kGroupGp] = 0xFFFFFFFFu & ~Support::bitMask(18, 31u); - _availableRegs[BaseReg::kGroupVec] = 0xFFFFFFFFu; - _availableRegs[BaseReg::kGroupOther0] = 0; - _availableRegs[BaseReg::kGroupOther1] = 0; + case Arch::kAArch64: { + _availableRegs[RegGroup::kGp] = 0xFFFFFFFFu & ~Support::bitMask(18, 31u); + _availableRegs[RegGroup::kVec] = 0xFFFFFFFFu; + _availableRegs[RegGroup::kExtraVirt2] = 0; + _availableRegs[RegGroup::kExtraVirt3] = 0; return kErrorOk; } @@ -108,48 +85,70 @@ public: } } - inline uint32_t availableRegs(uint32_t group) const noexcept { return _availableRegs[group]; } + inline RegMask availableRegs(RegGroup group) const noexcept { return _availableRegs[group]; } }; -// ============================================================================ -// [asmjit::RAStrategy] -// ============================================================================ +enum class RAStrategyType : uint8_t { + kSimple = 0, + kComplex = 1 +}; +ASMJIT_DEFINE_ENUM_COMPARE(RAStrategyType) + +enum class RAStrategyFlags : uint8_t { + kNone = 0 +}; +ASMJIT_DEFINE_ENUM_FLAGS(RAStrategyFlags) +//! Register allocation strategy. +//! +//! The idea is to select the best register allocation strategy for each virtual register group based on the +//! complexity of the code. struct RAStrategy { - uint8_t _type; + //! \name Members + //! \{ - enum StrategyType : uint32_t { - kStrategySimple = 0, - kStrategyComplex = 1 - }; + RAStrategyType _type = RAStrategyType::kSimple; + RAStrategyFlags _flags = RAStrategyFlags::kNone; - inline RAStrategy() noexcept { reset(); } - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } + //! \} - inline uint32_t type() const noexcept { return _type; } - inline void setType(uint32_t type) noexcept { _type = uint8_t(type); } + //! \name Accessors + //! \{ - inline bool isSimple() const noexcept { return _type == kStrategySimple; } - inline bool isComplex() const noexcept { return _type >= kStrategyComplex; } -}; + inline void reset() noexcept { + _type = RAStrategyType::kSimple; + _flags = RAStrategyFlags::kNone; + } + inline RAStrategyType type() const noexcept { return _type; } + inline void setType(RAStrategyType type) noexcept { _type = type; } -// ============================================================================ -// [asmjit::RARegCount] -// ============================================================================ + inline bool isSimple() const noexcept { return _type == RAStrategyType::kSimple; } + inline bool isComplex() const noexcept { return _type >= RAStrategyType::kComplex; } + + inline RAStrategyFlags flags() const noexcept { return _flags; } + inline bool hasFlag(RAStrategyFlags flag) const noexcept { return Support::test(_flags, flag); } + inline void addFlags(RAStrategyFlags flags) noexcept { _flags |= flags; } + + //! \} +}; //! Count of virtual or physical registers per group. //! -//! \note This class uses 8-bit integers to represent counters, it's only used -//! in places where this is sufficient - for example total count of machine's -//! physical registers, count of virtual registers per instruction, etc. There -//! is also `RALiveCount`, which uses 32-bit integers and is indeed much safer. +//! \note This class uses 8-bit integers to represent counters, it's only used in places where this is sufficient, +//! for example total count of machine's physical registers, count of virtual registers per instruction, etc... +//! There is also `RALiveCount`, which uses 32-bit integers and is indeed much safer. struct RARegCount { + //! \name Members + //! \{ + union { uint8_t _regs[4]; uint32_t _packed; }; + //! \} + //! \name Construction & Destruction //! \{ @@ -161,62 +160,57 @@ struct RARegCount { //! \name Overloaded Operators //! \{ - inline uint8_t& operator[](uint32_t index) noexcept { - ASMJIT_ASSERT(index < BaseReg::kGroupVirt); - return _regs[index]; + inline uint8_t& operator[](RegGroup group) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + return _regs[size_t(group)]; } - inline const uint8_t& operator[](uint32_t index) const noexcept { - ASMJIT_ASSERT(index < BaseReg::kGroupVirt); - return _regs[index]; + inline const uint8_t& operator[](RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + return _regs[size_t(group)]; } - inline RARegCount& operator=(const RARegCount& other) noexcept = default; - inline bool operator==(const RARegCount& other) const noexcept { return _packed == other._packed; } inline bool operator!=(const RARegCount& other) const noexcept { return _packed != other._packed; } //! \} - //! \name Utilities + //! \name Accessors //! \{ //! Returns the count of registers by the given register `group`. - inline uint32_t get(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline uint32_t get(RegGroup group) const noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); - uint32_t shift = Support::byteShiftOfDWordStruct(group); + uint32_t shift = Support::byteShiftOfDWordStruct(uint32_t(group)); return (_packed >> shift) & uint32_t(0xFF); } //! Sets the register count by a register `group`. - inline void set(uint32_t group, uint32_t n) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline void set(RegGroup group, uint32_t n) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); ASMJIT_ASSERT(n <= 0xFF); - uint32_t shift = Support::byteShiftOfDWordStruct(group); + uint32_t shift = Support::byteShiftOfDWordStruct(uint32_t(group)); _packed = (_packed & ~uint32_t(0xFF << shift)) + (n << shift); } //! Adds the register count by a register `group`. - inline void add(uint32_t group, uint32_t n = 1) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - ASMJIT_ASSERT(0xFF - uint32_t(_regs[group]) >= n); + inline void add(RegGroup group, uint32_t n = 1) noexcept { + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); + ASMJIT_ASSERT(0xFF - uint32_t(_regs[size_t(group)]) >= n); - uint32_t shift = Support::byteShiftOfDWordStruct(group); + uint32_t shift = Support::byteShiftOfDWordStruct(uint32_t(group)); _packed += n << shift; } //! \} }; -// ============================================================================ -// [asmjit::RARegIndex] -// ============================================================================ - +//! Provides mapping that can be used to fast index architecture register groups. struct RARegIndex : public RARegCount { //! Build register indexes based on the given `count` of registers. - inline void buildIndexes(const RARegCount& count) noexcept { + ASMJIT_FORCE_INLINE void buildIndexes(const RARegCount& count) noexcept { uint32_t x = uint32_t(count._regs[0]); uint32_t y = uint32_t(count._regs[1]) + x; uint32_t z = uint32_t(count._regs[2]) + y; @@ -227,55 +221,35 @@ struct RARegIndex : public RARegCount { } }; -// ============================================================================ -// [asmjit::RARegMask] -// ============================================================================ - //! Registers mask. struct RARegMask { - uint32_t _masks[BaseReg::kGroupVirt]; + //! \name Members + //! \{ + + Support::Array<RegMask, Globals::kNumVirtGroups> _masks; + + //! \} //! \name Construction & Destruction //! \{ - inline void init(const RARegMask& other) noexcept { - for (uint32_t i = 0; i < BaseReg::kGroupVirt; i++) - _masks[i] = other._masks[i]; - } - + inline void init(const RARegMask& other) noexcept { _masks = other._masks; } //! Reset all register masks to zero. - inline void reset() noexcept { - for (uint32_t i = 0; i < BaseReg::kGroupVirt; i++) - _masks[i] = 0; - } + inline void reset() noexcept { _masks.fill(0); } //! \} //! \name Overloaded Operators //! \{ - inline RARegMask& operator=(const RARegMask& other) noexcept = default; - - inline bool operator==(const RARegMask& other) const noexcept { - return _masks[0] == other._masks[0] && - _masks[1] == other._masks[1] && - _masks[2] == other._masks[2] && - _masks[3] == other._masks[3] ; - } - - inline bool operator!=(const RARegMask& other) const noexcept { - return !operator==(other); - } + inline bool operator==(const RARegMask& other) const noexcept { return _masks == other._masks; } + inline bool operator!=(const RARegMask& other) const noexcept { return _masks != other._masks; } - inline uint32_t& operator[](uint32_t index) noexcept { - ASMJIT_ASSERT(index < BaseReg::kGroupVirt); - return _masks[index]; - } + template<typename Index> + inline uint32_t& operator[](const Index& index) noexcept { return _masks[index]; } - inline const uint32_t& operator[](uint32_t index) const noexcept { - ASMJIT_ASSERT(index < BaseReg::kGroupVirt); - return _masks[index]; - } + template<typename Index> + inline const uint32_t& operator[](const Index& index) const noexcept { return _masks[index]; } //! \} @@ -284,43 +258,34 @@ struct RARegMask { //! Tests whether all register masks are zero (empty). inline bool empty() const noexcept { - uint32_t m = 0; - for (uint32_t i = 0; i < BaseReg::kGroupVirt; i++) - m |= _masks[i]; - return m == 0; + return _masks.aggregate<Support::Or>() == 0; } - inline bool has(uint32_t group, uint32_t mask = 0xFFFFFFFFu) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + inline bool has(RegGroup group, RegMask mask = 0xFFFFFFFFu) const noexcept { return (_masks[group] & mask) != 0; } template<class Operator> inline void op(const RARegMask& other) noexcept { - for (uint32_t i = 0; i < BaseReg::kGroupVirt; i++) - _masks[i] = Operator::op(_masks[i], other._masks[i]); + _masks.combine<Operator>(other._masks); } template<class Operator> - inline void op(uint32_t group, uint32_t input) noexcept { + inline void op(RegGroup group, uint32_t input) noexcept { _masks[group] = Operator::op(_masks[group], input); } //! \} }; -// ============================================================================ -// [asmjit::RARegsStats] -// ============================================================================ - -//! Information associated with each instruction, propagated to blocks, loops, -//! and the whole function. This information can be used to do minor decisions -//! before the register allocator tries to do its job. For example to use fast -//! register allocation inside a block or loop it cannot have clobbered and/or -//! fixed registers, etc... +//! Information associated with each instruction, propagated to blocks, loops, and the whole function. This +//! information can be used to do minor decisions before the register allocator tries to do its job. For +//! example to use fast register allocation inside a block or loop it cannot have clobbered and/or fixed +//! registers, etc... class RARegsStats { public: - uint32_t _packed = 0; + //! \name Constants + //! \{ enum Index : uint32_t { kIndexUsed = 0, @@ -334,30 +299,45 @@ public: kMaskClobbered = 0xFFu << kIndexClobbered }; + //! \} + + //! \name Members + //! \{ + + uint32_t _packed = 0; + + //! \} + + //! \name Accessors + //! \{ + inline void reset() noexcept { _packed = 0; } inline void combineWith(const RARegsStats& other) noexcept { _packed |= other._packed; } inline bool hasUsed() const noexcept { return (_packed & kMaskUsed) != 0u; } - inline bool hasUsed(uint32_t group) const noexcept { return (_packed & Support::bitMask(kIndexUsed + group)) != 0u; } - inline void makeUsed(uint32_t group) noexcept { _packed |= Support::bitMask(kIndexUsed + group); } + inline bool hasUsed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexUsed + uint32_t(group))) != 0u; } + inline void makeUsed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexUsed + uint32_t(group)); } inline bool hasFixed() const noexcept { return (_packed & kMaskFixed) != 0u; } - inline bool hasFixed(uint32_t group) const noexcept { return (_packed & Support::bitMask(kIndexFixed + group)) != 0u; } - inline void makeFixed(uint32_t group) noexcept { _packed |= Support::bitMask(kIndexFixed + group); } + inline bool hasFixed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexFixed + uint32_t(group))) != 0u; } + inline void makeFixed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexFixed + uint32_t(group)); } inline bool hasClobbered() const noexcept { return (_packed & kMaskClobbered) != 0u; } - inline bool hasClobbered(uint32_t group) const noexcept { return (_packed & Support::bitMask(kIndexClobbered + group)) != 0u; } - inline void makeClobbered(uint32_t group) noexcept { _packed |= Support::bitMask(kIndexClobbered + group); } -}; + inline bool hasClobbered(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexClobbered + uint32_t(group))) != 0u; } + inline void makeClobbered(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexClobbered + uint32_t(group)); } -// ============================================================================ -// [asmjit::RALiveCount] -// ============================================================================ + //! \} +}; //! Count of live registers, per group. class RALiveCount { public: - uint32_t n[BaseReg::kGroupVirt] {}; + //! \name Members + //! \{ + + Support::Array<uint32_t, Globals::kNumVirtGroups> n {}; + + //! \} //! \name Construction & Destruction //! \{ @@ -365,15 +345,8 @@ public: inline RALiveCount() noexcept = default; inline RALiveCount(const RALiveCount& other) noexcept = default; - inline void init(const RALiveCount& other) noexcept { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - n[group] = other.n[group]; - } - - inline void reset() noexcept { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - n[group] = 0; - } + inline void init(const RALiveCount& other) noexcept { n = other.n; } + inline void reset() noexcept { n.fill(0); } //! \} @@ -382,8 +355,8 @@ public: inline RALiveCount& operator=(const RALiveCount& other) noexcept = default; - inline uint32_t& operator[](uint32_t group) noexcept { return n[group]; } - inline const uint32_t& operator[](uint32_t group) const noexcept { return n[group]; } + inline uint32_t& operator[](RegGroup group) noexcept { return n[group]; } + inline const uint32_t& operator[](RegGroup group) const noexcept { return n[group]; } //! \} @@ -391,26 +364,29 @@ public: //! \{ template<class Operator> - inline void op(const RALiveCount& other) noexcept { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - n[group] = Operator::op(n[group], other.n[group]); - } + inline void op(const RALiveCount& other) noexcept { n.combine<Operator>(other.n); } //! \} }; -// ============================================================================ -// [asmjit::RALiveInterval] -// ============================================================================ - struct RALiveInterval { - uint32_t a, b; + //! \name Constants + //! \{ - enum Misc : uint32_t { + enum : uint32_t { kNaN = 0, kInf = 0xFFFFFFFFu }; + //! \} + + //! \name Members + //! \{ + + uint32_t a, b; + + //! \} + //! \name Construction & Destruction //! \{ @@ -443,15 +419,17 @@ struct RALiveInterval { //! \} }; -// ============================================================================ -// [asmjit::RALiveSpan<T>] -// ============================================================================ - +//! Live span with payload of type `T`. template<typename T> class RALiveSpan : public RALiveInterval, public T { public: + //! \name Types + //! \{ + typedef T DataType; + //! \} + //! \name Construction & Destruction //! \{ @@ -489,10 +467,7 @@ public: //! \} }; -// ============================================================================ -// [asmjit::RALiveSpans<T>] -// ============================================================================ - +//! Vector of `RALiveSpan<T>` with additional convenience API. template<typename T> class RALiveSpans { public: @@ -533,12 +508,12 @@ public: inline void swap(RALiveSpans<T>& other) noexcept { _data.swap(other._data); } //! Open the current live span. - ASMJIT_INLINE Error openAt(ZoneAllocator* allocator, uint32_t start, uint32_t end) noexcept { + ASMJIT_FORCE_INLINE Error openAt(ZoneAllocator* allocator, uint32_t start, uint32_t end) noexcept { bool wasOpen; return openAt(allocator, start, end, wasOpen); } - ASMJIT_INLINE Error openAt(ZoneAllocator* allocator, uint32_t start, uint32_t end, bool& wasOpen) noexcept { + ASMJIT_FORCE_INLINE Error openAt(ZoneAllocator* allocator, uint32_t start, uint32_t end, bool& wasOpen) noexcept { uint32_t size = _data.size(); wasOpen = false; @@ -554,7 +529,7 @@ public: return _data.append(allocator, T(start, end)); } - inline void closeAt(uint32_t end) noexcept { + ASMJIT_FORCE_INLINE void closeAt(uint32_t end) noexcept { ASMJIT_ASSERT(!empty()); uint32_t size = _data.size(); @@ -563,9 +538,8 @@ public: //! Returns the sum of width of all spans. //! - //! \note Don't overuse, this iterates over all spans so it's O(N). - //! It should be only called once and then cached. - ASMJIT_INLINE uint32_t width() const noexcept { + //! \note Don't overuse, this iterates over all spans so it's O(N). It should be only called once and then cached. + inline uint32_t width() const noexcept { uint32_t width = 0; for (const T& span : _data) width += span.width(); @@ -579,7 +553,7 @@ public: return intersects(*this, other); } - ASMJIT_INLINE Error nonOverlappingUnionOf(ZoneAllocator* allocator, const RALiveSpans<T>& x, const RALiveSpans<T>& y, const DataType& yData) noexcept { + ASMJIT_FORCE_INLINE Error nonOverlappingUnionOf(ZoneAllocator* allocator, const RALiveSpans<T>& x, const RALiveSpans<T>& y, const DataType& yData) noexcept { uint32_t finalSize = x.size() + y.size(); ASMJIT_PROPAGATE(_data.reserve(allocator, finalSize)); @@ -590,9 +564,8 @@ public: const T* xEnd = xSpan + x.size(); const T* yEnd = ySpan + y.size(); - // Loop until we have intersection or either `xSpan == xEnd` or `ySpan == yEnd`, - // which means that there is no intersection. We advance either `xSpan` or `ySpan` - // depending on their ranges. + // Loop until we have intersection or either `xSpan == xEnd` or `ySpan == yEnd`, which means that there is no + // intersection. We advance either `xSpan` or `ySpan` depending on their ranges. if (xSpan != xEnd && ySpan != yEnd) { uint32_t xa, ya; xa = xSpan->a; @@ -633,16 +606,15 @@ public: return kErrorOk; } - static ASMJIT_INLINE bool intersects(const RALiveSpans<T>& x, const RALiveSpans<T>& y) noexcept { + static ASMJIT_FORCE_INLINE bool intersects(const RALiveSpans<T>& x, const RALiveSpans<T>& y) noexcept { const T* xSpan = x.data(); const T* ySpan = y.data(); const T* xEnd = xSpan + x.size(); const T* yEnd = ySpan + y.size(); - // Loop until we have intersection or either `xSpan == xEnd` or `ySpan == yEnd`, - // which means that there is no intersection. We advance either `xSpan` or `ySpan` - // depending on their end positions. + // Loop until we have intersection or either `xSpan == xEnd` or `ySpan == yEnd`, which means that there is no + // intersection. We advance either `xSpan` or `ySpan` depending on their end positions. if (xSpan == xEnd || ySpan == yEnd) return false; @@ -669,10 +641,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::RALiveStats] -// ============================================================================ - //! Statistics about a register liveness. class RALiveStats { public: @@ -690,10 +658,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::LiveRegData] -// ============================================================================ - struct LiveRegData { uint32_t id; @@ -709,177 +673,255 @@ struct LiveRegData { typedef RALiveSpan<LiveRegData> LiveRegSpan; typedef RALiveSpans<LiveRegSpan> LiveRegSpans; -// ============================================================================ -// [asmjit::RATiedReg] -// ============================================================================ +//! Flags used by \ref RATiedReg. +//! +//! Register access information is encoded in 4 flags in total: +//! +//! - `kRead` - Register is Read (ReadWrite if combined with `kWrite`). +//! - `kWrite` - Register is Written (ReadWrite if combined with `kRead`). +//! - `kUse` - Encoded as Read or ReadWrite. +//! - `kOut` - Encoded as WriteOnly. +//! +//! Let's describe all of these on two X86 instructions: +//! +//! - ADD x{R|W|Use}, x{R|Use} -> {x:R|W|Use } +//! - LEA x{ W|Out}, [x{R|Use} + x{R|Out}] -> {x:R|W|Use|Out } +//! - ADD x{R|W|Use}, y{R|Use} -> {x:R|W|Use y:R|Use} +//! - LEA x{ W|Out}, [x{R|Use} + y{R|Out}] -> {x:R|W|Use|Out y:R|Use} +//! +//! It should be obvious from the example above how these flags get created. Each operand contains READ/WRITE +//! information, which is then merged to RATiedReg's flags. However, we also need to represent the possitility +//! to view the operation as two independent operations - USE and OUT, because the register allocator first +//! allocates USE registers, and then assigns OUT registers independently of USE registers. +enum class RATiedFlags : uint32_t { + //! No flags. + kNone = 0, + + // Access Flags + // ------------ + + //! Register is read. + kRead = uint32_t(OpRWFlags::kRead), + //! Register is written. + kWrite = uint32_t(OpRWFlags::kWrite), + //! Register both read and written. + kRW = uint32_t(OpRWFlags::kRW), + + // Use / Out Flags + // --------------- + + //! Register has a USE slot (read/rw). + kUse = 0x00000004u, + //! Register has an OUT slot (write-only). + kOut = 0x00000008u, + //! Register in USE slot can be patched to memory. + kUseRM = 0x00000010u, + //! Register in OUT slot can be patched to memory. + kOutRM = 0x00000020u, + + //! Register has a fixed USE slot. + kUseFixed = 0x00000040u, + //! Register has a fixed OUT slot. + kOutFixed = 0x00000080u, + //! Register USE slot has been allocated. + kUseDone = 0x00000100u, + //! Register OUT slot has been allocated. + kOutDone = 0x00000200u, + + // Consecutive Flags / Data + // ------------------------ + + kUseConsecutive = 0x00000400u, + kOutConsecutive = 0x00000800u, + kLeadConsecutive = 0x00001000u, + kConsecutiveData = 0x00006000u, + + // Liveness Flags + // -------------- + + //! Register must be duplicated (function call only). + kDuplicate = 0x00010000u, + //! Last occurrence of this VirtReg in basic block. + kLast = 0x00020000u, + //! Kill this VirtReg after use. + kKill = 0x00040000u, + + // X86 Specific Flags + // ------------------ + + // Architecture specific flags are used during RATiedReg building to ensure that architecture-specific constraints + // are handled properly. These flags are not really needed after RATiedReg[] is built and copied to `RAInst`. + + //! This RATiedReg references GPB-LO or GPB-HI. + kX86_Gpb = 0x01000000u, + + // Instruction Flags (Never used by RATiedReg) + // ------------------------------------------- + + //! Instruction is transformable to another instruction if necessary. + //! + //! This is flag that is only used by \ref RAInst to inform register allocator that the instruction has some + //! constraints that can only be solved by transforming the instruction into another instruction, most likely + //! by changing its InstId. + kInst_IsTransformable = 0x80000000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(RATiedFlags) + +static_assert(uint32_t(RATiedFlags::kRead ) == 0x1, "RATiedFlags::kRead must be 0x1"); +static_assert(uint32_t(RATiedFlags::kWrite) == 0x2, "RATiedFlags::kWrite must be 0x2"); +static_assert(uint32_t(RATiedFlags::kRW ) == 0x3, "RATiedFlags::kRW must be 0x3"); -//! Tied register merges one ore more register operand into a single entity. It -//! contains information about its access (Read|Write) and allocation slots -//! (Use|Out) that are used by the register allocator and liveness analysis. +//! Tied register merges one ore more register operand into a single entity. It contains information about its access +//! (Read|Write) and allocation slots (Use|Out) that are used by the register allocator and liveness analysis. struct RATiedReg { + //! \name Members + //! \{ + //! WorkReg id. uint32_t _workId; + //! WorkReg id that is an immediate consecutive parent of this register, or Globals::kInvalidId if it has no parent. + uint32_t _consecutiveParent; //! Allocation flags. - uint32_t _flags; - //! Registers where input {R|X} can be allocated to. - uint32_t _allocableRegs; - //! Indexes used to rewrite USE regs. - uint32_t _useRewriteMask; - //! Indexes used to rewrite OUT regs. - uint32_t _outRewriteMask; + RATiedFlags _flags; union { struct { //! How many times the VirtReg is referenced in all operands. uint8_t _refCount; + //! Size of a memory operand in case that it's use instead of the register. + uint8_t _rmSize; //! Physical register for use operation (ReadOnly / ReadWrite). uint8_t _useId; //! Physical register for out operation (WriteOnly). uint8_t _outId; - //! Reserved for future use (padding). - uint8_t _rmSize; }; //! Packed data. uint32_t _packed; }; - //! Flags. - //! - //! Register access information is encoded in 4 flags in total: - //! - //! - `kRead` - Register is Read (ReadWrite if combined with `kWrite`). - //! - `kWrite` - Register is Written (ReadWrite if combined with `kRead`). - //! - `kUse` - Encoded as Read or ReadWrite. - //! - `kOut` - Encoded as WriteOnly. - //! - //! Let's describe all of these on two X86 instructions: - //! - //! - ADD x{R|W|Use}, x{R|Use} -> {x:R|W|Use } - //! - LEA x{ W|Out}, [x{R|Use} + x{R|Out}] -> {x:R|W|Use|Out } - //! - ADD x{R|W|Use}, y{R|Use} -> {x:R|W|Use y:R|Use} - //! - LEA x{ W|Out}, [x{R|Use} + y{R|Out}] -> {x:R|W|Use|Out y:R|Use} - //! - //! It should be obvious from the example above how these flags get created. - //! Each operand contains READ/WRITE information, which is then merged to - //! RATiedReg's flags. However, we also need to represent the possitility to - //! use see the operation as two independent operations - USE and OUT, because - //! the register allocator will first allocate USE registers, and then assign - //! OUT registers independently of USE registers. - enum Flags : uint32_t { - kRead = OpRWInfo::kRead, //!< Register is read. - kWrite = OpRWInfo::kWrite, //!< Register is written. - kRW = OpRWInfo::kRW, //!< Register both read and written. - - kUse = 0x00000100u, //!< Register has a USE slot (read/rw). - kOut = 0x00000200u, //!< Register has an OUT slot (write-only). - kUseRM = 0x00000400u, //!< Register in USE slot can be patched to memory. - kOutRM = 0x00000800u, //!< Register in OUT slot can be patched to memory. - - kUseFixed = 0x00001000u, //!< Register has a fixed USE slot. - kOutFixed = 0x00002000u, //!< Register has a fixed OUT slot. - kUseDone = 0x00004000u, //!< Register USE slot has been allocated. - kOutDone = 0x00008000u, //!< Register OUT slot has been allocated. - - kDuplicate = 0x00010000u, //!< Register must be duplicated (function call only). - kLast = 0x00020000u, //!< Last occurrence of this VirtReg in basic block. - kKill = 0x00040000u, //!< Kill this VirtReg after use. - - // Architecture specific flags are used during RATiedReg building to ensure - // that architecture-specific constraints are handled properly. These flags - // are not really needed after RATiedReg[] is built and copied to `RAInst`. - - kX86Gpb = 0x01000000u //!< This RATiedReg references GPB-LO or GPB-HI. - }; + //! Registers where inputs {R|X} can be allocated to. + RegMask _useRegMask; + //! Registers where outputs {W} can be allocated to. + RegMask _outRegMask; + //! Indexes used to rewrite USE regs. + uint32_t _useRewriteMask; + //! Indexes used to rewrite OUT regs. + uint32_t _outRewriteMask; + + //! \} + + //! \name Statics + //! \{ + + static inline RATiedFlags consecutiveDataToFlags(uint32_t offset) noexcept { + ASMJIT_ASSERT(offset < 4); + constexpr uint32_t kOffsetShift = Support::ConstCTZ<uint32_t(RATiedFlags::kConsecutiveData)>::value; + return (RATiedFlags)(offset << kOffsetShift); + } + + static inline uint32_t consecutiveDataFromFlags(RATiedFlags flags) noexcept { + constexpr uint32_t kOffsetShift = Support::ConstCTZ<uint32_t(RATiedFlags::kConsecutiveData)>::value; + return uint32_t(flags & RATiedFlags::kConsecutiveData) >> kOffsetShift; + } - static_assert(kRead == 0x1, "RATiedReg::kRead flag must be 0x1"); - static_assert(kWrite == 0x2, "RATiedReg::kWrite flag must be 0x2"); - static_assert(kRW == 0x3, "RATiedReg::kRW combination must be 0x3"); + //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE void init(uint32_t workId, uint32_t flags, uint32_t allocableRegs, uint32_t useId, uint32_t useRewriteMask, uint32_t outId, uint32_t outRewriteMask, uint32_t rmSize = 0) noexcept { + inline void init(uint32_t workId, RATiedFlags flags, RegMask useRegMask, uint32_t useId, uint32_t useRewriteMask, RegMask outRegMask, uint32_t outId, uint32_t outRewriteMask, uint32_t rmSize = 0, uint32_t consecutiveParent = Globals::kInvalidId) noexcept { _workId = workId; + _consecutiveParent = consecutiveParent; _flags = flags; - _allocableRegs = allocableRegs; - _useRewriteMask = useRewriteMask; - _outRewriteMask = outRewriteMask; _refCount = 1; + _rmSize = uint8_t(rmSize); _useId = uint8_t(useId); _outId = uint8_t(outId); - _rmSize = uint8_t(rmSize); + _useRegMask = useRegMask; + _outRegMask = outRegMask; + _useRewriteMask = useRewriteMask; + _outRewriteMask = outRewriteMask; } //! \} - //! \name Overloaded Operators - //! \{ - - inline RATiedReg& operator=(const RATiedReg& other) noexcept = default; - - //! \} - //! \name Accessors //! \{ //! Returns the associated WorkReg id. inline uint32_t workId() const noexcept { return _workId; } - //! Checks if the given `flag` is set, see `Flags`. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } + inline bool hasConsecutiveParent() const noexcept { return _consecutiveParent != Globals::kInvalidId; } + inline uint32_t consecutiveParent() const noexcept { return _consecutiveParent; } + inline uint32_t consecutiveData() const noexcept { return consecutiveDataFromFlags(_flags); } - //! Returns TiedReg flags, see `RATiedReg::Flags`. - inline uint32_t flags() const noexcept { return _flags; } - //! Adds tied register flags, see `Flags`. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } + //! Returns TiedReg flags. + inline RATiedFlags flags() const noexcept { return _flags; } + //! Checks if the given `flag` is set. + inline bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); } + //! Adds tied register flags. + inline void addFlags(RATiedFlags flags) noexcept { _flags |= flags; } //! Tests whether the register is read (writes `true` also if it's Read/Write). - inline bool isRead() const noexcept { return hasFlag(kRead); } + inline bool isRead() const noexcept { return hasFlag(RATiedFlags::kRead); } //! Tests whether the register is written (writes `true` also if it's Read/Write). - inline bool isWrite() const noexcept { return hasFlag(kWrite); } + inline bool isWrite() const noexcept { return hasFlag(RATiedFlags::kWrite); } //! Tests whether the register is read only. - inline bool isReadOnly() const noexcept { return (_flags & kRW) == kRead; } + inline bool isReadOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRead; } //! Tests whether the register is write only. - inline bool isWriteOnly() const noexcept { return (_flags & kRW) == kWrite; } + inline bool isWriteOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kWrite; } //! Tests whether the register is read and written. - inline bool isReadWrite() const noexcept { return (_flags & kRW) == kRW; } + inline bool isReadWrite() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRW; } //! Tests whether the tied register has use operand (Read/ReadWrite). - inline bool isUse() const noexcept { return hasFlag(kUse); } + inline bool isUse() const noexcept { return hasFlag(RATiedFlags::kUse); } //! Tests whether the tied register has out operand (Write). - inline bool isOut() const noexcept { return hasFlag(kOut); } + inline bool isOut() const noexcept { return hasFlag(RATiedFlags::kOut); } + + //! Tests whether the tied register has \ref RATiedFlags::kLeadConsecutive flag set. + inline bool isLeadConsecutive() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive); } + //! Tests whether the tied register has \ref RATiedFlags::kUseConsecutive flag set. + inline bool isUseConsecutive() const noexcept { return hasFlag(RATiedFlags::kUseConsecutive); } + //! Tests whether the tied register has \ref RATiedFlags::kOutConsecutive flag set. + inline bool isOutConsecutive() const noexcept { return hasFlag(RATiedFlags::kOutConsecutive); } + + //! Tests whether the tied register has any consecutive flag. + inline bool hasAnyConsecutiveFlag() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive); } //! Tests whether the USE slot can be patched to memory operand. - inline bool hasUseRM() const noexcept { return hasFlag(kUseRM); } + inline bool hasUseRM() const noexcept { return hasFlag(RATiedFlags::kUseRM); } //! Tests whether the OUT slot can be patched to memory operand. - inline bool hasOutRM() const noexcept { return hasFlag(kOutRM); } + inline bool hasOutRM() const noexcept { return hasFlag(RATiedFlags::kOutRM); } inline uint32_t rmSize() const noexcept { return _rmSize; } inline void makeReadOnly() noexcept { - _flags = (_flags & ~(kOut | kWrite)) | kUse; + _flags = (_flags & ~(RATiedFlags::kOut | RATiedFlags::kWrite)) | RATiedFlags::kUse; _useRewriteMask |= _outRewriteMask; _outRewriteMask = 0; } inline void makeWriteOnly() noexcept { - _flags = (_flags & ~(kUse | kRead)) | kOut; + _flags = (_flags & ~(RATiedFlags::kUse | RATiedFlags::kRead)) | RATiedFlags::kOut; _outRewriteMask |= _useRewriteMask; _useRewriteMask = 0; } //! Tests whether the register would duplicate. - inline bool isDuplicate() const noexcept { return hasFlag(kDuplicate); } + inline bool isDuplicate() const noexcept { return hasFlag(RATiedFlags::kDuplicate); } //! Tests whether the register (and the instruction it's part of) appears last in the basic block. - inline bool isLast() const noexcept { return hasFlag(kLast); } + inline bool isLast() const noexcept { return hasFlag(RATiedFlags::kLast); } //! Tests whether the register should be killed after USEd and/or OUTed. - inline bool isKill() const noexcept { return hasFlag(kKill); } + inline bool isKill() const noexcept { return hasFlag(RATiedFlags::kKill); } //! Tests whether the register is OUT or KILL (used internally by local register allocator). - inline bool isOutOrKill() const noexcept { return hasFlag(kOut | kKill); } + inline bool isOutOrKill() const noexcept { return hasFlag(RATiedFlags::kOut | RATiedFlags::kKill); } - inline uint32_t allocableRegs() const noexcept { return _allocableRegs; } + //! Returns a register mask that describes allocable USE registers (Read/ReadWrite access). + inline RegMask useRegMask() const noexcept { return _useRegMask; } + //! Returns a register mask that describes allocable OUT registers (WriteOnly access). + inline RegMask outRegMask() const noexcept { return _outRegMask; } inline uint32_t refCount() const noexcept { return _refCount; } inline void addRefCount(uint32_t n = 1) noexcept { _refCount = uint8_t(_refCount + n); } @@ -902,23 +944,67 @@ struct RATiedReg { //! Sets a physical register used for 'out' operation. inline void setOutId(uint32_t index) noexcept { _outId = uint8_t(index); } - inline bool isUseDone() const noexcept { return hasFlag(kUseDone); } - inline bool isOutDone() const noexcept { return hasFlag(kUseDone); } + inline bool isUseDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); } + inline bool isOutDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); } - inline void markUseDone() noexcept { addFlags(kUseDone); } - inline void markOutDone() noexcept { addFlags(kUseDone); } + inline void markUseDone() noexcept { addFlags(RATiedFlags::kUseDone); } + inline void markOutDone() noexcept { addFlags(RATiedFlags::kUseDone); } //! \} }; -// ============================================================================ -// [asmjit::RAWorkReg] -// ============================================================================ +//! Flags used by \ref RAWorkReg. +enum class RAWorkRegFlags : uint32_t { + //! No flags. + kNone = 0, + + //! This register has already been allocated. + kAllocated = 0x00000001u, + //! Has been coalesced to another WorkReg. + kCoalesced = 0x00000002u, + + //! Set when this register is used as a LEAD consecutive register at least once. + kLeadConsecutive = 0x00000004u, + //! Used to mark consecutive registers during processing. + kProcessedConsecutive = 0x00000008u, + + //! Stack slot has to be allocated. + kStackUsed = 0x00000010u, + //! Stack allocation is preferred. + kStackPreferred = 0x00000020u, + //! Marked for stack argument reassignment. + kStackArgToStack = 0x00000040u +}; +ASMJIT_DEFINE_ENUM_FLAGS(RAWorkRegFlags) +//! Work register provides additional data of \ref VirtReg that is used by register allocator. +//! +//! In general when a virtual register is found by register allocator it maps it to \ref RAWorkReg +//! and then only works with it. The reason for such mapping is that users can create many virtual +//! registers, which are not used inside a register allocation scope (which is currently always a +//! function). So register allocator basically scans the function for virtual registers and maps +//! them into WorkRegs, which receive a temporary ID (workId), which starts from zero. This WorkId +//! is then used in bit-arrays and other mappings. class RAWorkReg { public: ASMJIT_NONCOPYABLE(RAWorkReg) + //! \name Constants + //! \{ + + enum : uint32_t { + kIdNone = 0xFFFFFFFFu + }; + + enum : uint32_t { + kNoArgIndex = 0xFFu + }; + + //! \} + + //! \name Members + //! \{ + //! RAPass specific ID used during analysis and allocation. uint32_t _workId = 0; //! Copy of ID used by \ref VirtReg. @@ -932,17 +1018,31 @@ public: RAStackSlot* _stackSlot = nullptr; //! Copy of a signature used by \ref VirtReg. - RegInfo _info {}; + OperandSignature _signature {}; //! RAPass specific flags used during analysis and allocation. - uint32_t _flags = 0; - //! IDs of all physical registers this WorkReg has been allocated to. - uint32_t _allocatedMask = 0; - //! IDs of all physical registers that are clobbered during the lifetime of - //! this WorkReg. + RAWorkRegFlags _flags = RAWorkRegFlags::kNone; + + //! Constains all USE ids collected from all instructions. //! - //! This mask should be updated by `RAPass::buildLiveness()`, because it's - //! global and should be updated after unreachable code has been removed. - uint32_t _clobberSurvivalMask = 0; + //! If this mask is non-zero and not a power of two, it means that the register is used multiple times in + //! instructions where it requires to have a different use ID. This means that in general it's not possible + //! to keep this register in a single home. + RegMask _useIdMask = 0; + //! Preferred mask of registers (if non-zero) to allocate this register to. + //! + //! If this mask is zero it means that either there is no intersection of preferred registers collected from all + //! TiedRegs or there is no preference at all (the register can be allocated to any register all the time). + RegMask _preferredMask = 0xFFFFFFFFu; + //! Consecutive mask, which was collected from all instructions where this register was used as a lead consecutive + //! register. + RegMask _consecutiveMask = 0xFFFFFFFFu; + //! IDs of all physical registers that are clobbered during the lifetime of this WorkReg. + //! + //! This mask should be updated by `RAPass::buildLiveness()`, because it's global and should + //! be updated after unreachable code has been removed. + RegMask _clobberSurvivalMask = 0; + //! IDs of all physical registers this WorkReg has been allocated to. + RegMask _allocatedMask = 0; //! A byte-mask where each bit represents one valid byte of the register. uint64_t _regByteMask = 0; @@ -962,37 +1062,27 @@ public: RALiveStats _liveStats {}; //! All nodes that read/write this VirtReg/WorkReg. - ZoneVector<BaseNode*> _refs; + ZoneVector<BaseNode*> _refs {}; //! All nodes that write to this VirtReg/WorkReg. - ZoneVector<BaseNode*> _writes; - - enum Ids : uint32_t { - kIdNone = 0xFFFFFFFFu - }; + ZoneVector<BaseNode*> _writes {}; - enum Flags : uint32_t { - //! Has been coalesced to another WorkReg. - kFlagCoalesced = 0x00000001u, - //! Stack slot has to be allocated. - kFlagStackUsed = 0x00000002u, - //! Stack allocation is preferred. - kFlagStackPreferred = 0x00000004u, - //! Marked for stack argument reassignment. - kFlagStackArgToStack = 0x00000008u - }; + //! Contains work IDs of all immediate consecutive registers of this register. + //! + //! \note This bit array only contains immediate consecutives. This means that if this is a register that is + //! followed by 3 more registers, then it would still have only a single immediate. The rest registers would + //! have immediate consecutive registers as well, except the last one. + ZoneBitVector _immediateConsecutives {}; - enum ArgIndex : uint32_t { - kNoArgIndex = 0xFFu - }; + //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE RAWorkReg(VirtReg* vReg, uint32_t workId) noexcept + inline RAWorkReg(VirtReg* vReg, uint32_t workId) noexcept : _workId(workId), _virtId(vReg->id()), _virtReg(vReg), - _info(vReg->info()) {} + _signature(vReg->signature()) {} //! \} @@ -1005,24 +1095,33 @@ public: inline const char* name() const noexcept { return _virtReg->name(); } inline uint32_t nameSize() const noexcept { return _virtReg->nameSize(); } - inline uint32_t typeId() const noexcept { return _virtReg->typeId(); } + inline TypeId typeId() const noexcept { return _virtReg->typeId(); } - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - inline uint32_t flags() const noexcept { return _flags; } - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } + inline RAWorkRegFlags flags() const noexcept { return _flags; } + inline bool hasFlag(RAWorkRegFlags flag) const noexcept { return Support::test(_flags, flag); } + inline void addFlags(RAWorkRegFlags flags) noexcept { _flags |= flags; } - inline bool isStackUsed() const noexcept { return hasFlag(kFlagStackUsed); } - inline void markStackUsed() noexcept { addFlags(kFlagStackUsed); } + inline bool isAllocated() const noexcept { return hasFlag(RAWorkRegFlags::kAllocated); } + inline void markAllocated() noexcept { addFlags(RAWorkRegFlags::kAllocated); } - inline bool isStackPreferred() const noexcept { return hasFlag(kFlagStackPreferred); } - inline void markStackPreferred() noexcept { addFlags(kFlagStackPreferred); } + inline bool isLeadConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kLeadConsecutive); } + inline void markLeadConsecutive() noexcept { addFlags(RAWorkRegFlags::kLeadConsecutive); } + + inline bool isProcessedConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kProcessedConsecutive); } + inline void markProcessedConsecutive() noexcept { addFlags(RAWorkRegFlags::kProcessedConsecutive); } + + inline bool isStackUsed() const noexcept { return hasFlag(RAWorkRegFlags::kStackUsed); } + inline void markStackUsed() noexcept { addFlags(RAWorkRegFlags::kStackUsed); } + + inline bool isStackPreferred() const noexcept { return hasFlag(RAWorkRegFlags::kStackPreferred); } + inline void markStackPreferred() noexcept { addFlags(RAWorkRegFlags::kStackPreferred); } //! Tests whether this RAWorkReg has been coalesced with another one (cannot be used anymore). - inline bool isCoalesced() const noexcept { return hasFlag(kFlagCoalesced); } + inline bool isCoalesced() const noexcept { return hasFlag(RAWorkRegFlags::kCoalesced); } - inline const RegInfo& info() const noexcept { return _info; } - inline uint32_t group() const noexcept { return _info.group(); } - inline uint32_t signature() const noexcept { return _info.signature(); } + inline OperandSignature signature() const noexcept { return _signature; } + inline RegType type() const noexcept { return _signature.regType(); } + inline RegGroup group() const noexcept { return _signature.regGroup(); } inline VirtReg* virtReg() const noexcept { return _virtReg; } @@ -1057,15 +1156,39 @@ public: inline uint32_t hintRegId() const noexcept { return _hintRegId; } inline void setHintRegId(uint32_t physId) noexcept { _hintRegId = uint8_t(physId); } - inline uint32_t allocatedMask() const noexcept { return _allocatedMask; } - inline void addAllocatedMask(uint32_t mask) noexcept { _allocatedMask |= mask; } + inline RegMask useIdMask() const noexcept { return _useIdMask; } + inline bool hasUseIdMask() const noexcept { return _useIdMask != 0u; } + inline bool hasMultipleUseIds() const noexcept { return _useIdMask != 0u && !Support::isPowerOf2(_useIdMask); } + inline void addUseIdMask(RegMask mask) noexcept { _useIdMask |= mask; } + + inline RegMask preferredMask() const noexcept { return _preferredMask; } + inline bool hasPrereffedMask() const noexcept { return _preferredMask != 0xFFFFFFFFu; } + inline void restrictPreferredMask(RegMask mask) noexcept { _preferredMask &= mask; } + + inline RegMask consecutiveMask() const noexcept { return _consecutiveMask; } + inline bool hasConsecutiveMask() const noexcept { return _consecutiveMask != 0xFFFFFFFFu; } + inline void restrictConsecutiveMask(RegMask mask) noexcept { _consecutiveMask &= mask; } + + inline RegMask clobberSurvivalMask() const noexcept { return _clobberSurvivalMask; } + inline void addClobberSurvivalMask(RegMask mask) noexcept { _clobberSurvivalMask |= mask; } - inline uint32_t clobberSurvivalMask() const noexcept { return _clobberSurvivalMask; } - inline void addClobberSurvivalMask(uint32_t mask) noexcept { _clobberSurvivalMask |= mask; } + inline RegMask allocatedMask() const noexcept { return _allocatedMask; } + inline void addAllocatedMask(RegMask mask) noexcept { _allocatedMask |= mask; } inline uint64_t regByteMask() const noexcept { return _regByteMask; } inline void setRegByteMask(uint64_t mask) noexcept { _regByteMask = mask; } + inline bool hasImmediateConsecutives() const noexcept { return !_immediateConsecutives.empty(); } + inline const ZoneBitVector& immediateConsecutives() const noexcept { return _immediateConsecutives; } + + inline Error addImmediateConsecutive(ZoneAllocator* allocator, uint32_t workId) noexcept { + if (_immediateConsecutives.size() <= workId) + ASMJIT_PROPAGATE(_immediateConsecutives.resize(allocator, workId + 1)); + + _immediateConsecutives.setBit(workId, true); + return kErrorOk; + } + //! \} }; diff --git a/src/asmjit/core/ralocal.cpp b/src/asmjit/core/ralocal.cpp index 5e06d5b..54bc524 100644 --- a/src/asmjit/core/ralocal.cpp +++ b/src/asmjit/core/ralocal.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_COMPILER @@ -29,20 +11,18 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::RALocalAllocator - Utilities] -// ============================================================================ +// RALocalAllocator - Utilities +// ============================ -static ASMJIT_INLINE RATiedReg* RALocal_findTiedRegByWorkId(RATiedReg* tiedRegs, size_t count, uint32_t workId) noexcept { +static ASMJIT_FORCE_INLINE RATiedReg* RALocal_findTiedRegByWorkId(RATiedReg* tiedRegs, size_t count, uint32_t workId) noexcept { for (size_t i = 0; i < count; i++) if (tiedRegs[i].workId() == workId) return &tiedRegs[i]; return nullptr; } -// ============================================================================ -// [asmjit::RALocalAllocator - Init / Reset] -// ============================================================================ +// RALocalAllocator - Init & Reset +// =============================== Error RALocalAllocator::init() noexcept { PhysToWorkMap* physToWorkMap; @@ -67,9 +47,8 @@ Error RALocalAllocator::init() noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::RALocalAllocator - Assignment] -// ============================================================================ +// RALocalAllocator - Assignment +// ============================= Error RALocalAllocator::makeInitialAssignment() noexcept { FuncNode* func = _pass->func(); @@ -83,10 +62,12 @@ Error RALocalAllocator::makeInitialAssignment() noexcept { for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { // Unassigned argument. - VirtReg* virtReg = func->argPack(argIndex)[valueIndex]; - if (!virtReg) + const RegOnly& regArg = func->argPack(argIndex)[valueIndex]; + if (!regArg.isReg() || !_cc->isVirtIdValid(regArg.id())) continue; + VirtReg* virtReg = _cc->virtRegById(regArg.id()); + // Unreferenced argument. RAWorkReg* workReg = virtReg->workReg(); if (!workReg) @@ -97,18 +78,18 @@ Error RALocalAllocator::makeInitialAssignment() noexcept { if (!liveIn.bitAt(workId)) continue; - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); if (_curAssignment.workToPhysId(group, workId) != RAAssignment::kPhysNone) continue; - uint32_t allocableRegs = _availableRegs[group] & ~_curAssignment.assigned(group); + RegMask allocableRegs = _availableRegs[group] & ~_curAssignment.assigned(group); if (iter == 0) { // First iteration: Try to allocate to home RegId. if (workReg->hasHomeRegId()) { uint32_t physId = workReg->homeRegId(); if (Support::bitTest(allocableRegs, physId)) { _curAssignment.assign(group, workId, physId, true); - _pass->_argsAssignment.assignRegInPack(argIndex, valueIndex, workReg->info().type(), physId, workReg->typeId()); + _pass->_argsAssignment.assignRegInPack(argIndex, valueIndex, workReg->type(), physId, workReg->typeId()); continue; } } @@ -120,7 +101,7 @@ Error RALocalAllocator::makeInitialAssignment() noexcept { if (allocableRegs) { uint32_t physId = Support::ctz(allocableRegs); _curAssignment.assign(group, workId, physId, true); - _pass->_argsAssignment.assignRegInPack(argIndex, valueIndex, workReg->info().type(), physId, workReg->typeId()); + _pass->_argsAssignment.assignRegInPack(argIndex, valueIndex, workReg->type(), physId, workReg->typeId()); } else { // This register will definitely need stack, create the slot now and assign also `argIndex` @@ -130,7 +111,7 @@ Error RALocalAllocator::makeInitialAssignment() noexcept { return DebugUtils::errored(kErrorOutOfMemory); // This means STACK_ARG may be moved to STACK. - workReg->addFlags(RAWorkReg::kFlagStackArgToStack); + workReg->addFlags(RAWorkRegFlags::kStackArgToStack); _pass->_numStackArgsToStackSlots++; } } @@ -165,15 +146,15 @@ Error RALocalAllocator::switchToAssignment( if (tryMode) return kErrorOk; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - // ------------------------------------------------------------------------ - // STEP 1: + for (RegGroup group : RegGroupVirtValues{}) { + // STEP 1 + // ------ + // // - KILL all registers that are not live at `dst`, // - SPILL all registers that are not assigned at `dst`. - // ------------------------------------------------------------------------ if (!tryMode) { - Support::BitWordIterator<uint32_t> it(cur.assigned(group)); + Support::BitWordIterator<RegMask> it(cur.assigned(group)); while (it.hasNext()) { uint32_t physId = it.next(); uint32_t workId = cur.physToWorkId(group, physId); @@ -195,19 +176,18 @@ Error RALocalAllocator::switchToAssignment( } } - // ------------------------------------------------------------------------ - // STEP 2: - // - MOVE and SWAP registers from their current assignments into their - // DST assignments. + // STEP 2 + // ------ + // + // - MOVE and SWAP registers from their current assignments into their DST assignments. // - Build `willLoadRegs` mask of registers scheduled for `onLoadReg()`. - // ------------------------------------------------------------------------ // Current run-id (1 means more aggressive decisions). int32_t runId = -1; // Remaining registers scheduled for `onLoadReg()`. - uint32_t willLoadRegs = 0; + RegMask willLoadRegs = 0; // Remaining registers to be allocated in this loop. - uint32_t affectedRegs = dst.assigned(group); + RegMask affectedRegs = dst.assigned(group); while (affectedRegs) { if (++runId == 2) { @@ -218,10 +198,10 @@ Error RALocalAllocator::switchToAssignment( break; } - Support::BitWordIterator<uint32_t> it(affectedRegs); + Support::BitWordIterator<RegMask> it(affectedRegs); while (it.hasNext()) { uint32_t physId = it.next(); - uint32_t physMask = Support::bitMask(physId); + RegMask physMask = Support::bitMask<RegMask>(physId); uint32_t curWorkId = cur.physToWorkId(group, physId); uint32_t dstWorkId = dst.physToWorkId(group, physId); @@ -243,7 +223,7 @@ Error RALocalAllocator::switchToAssignment( // Reset as we will do some changes to the current assignment. runId = -1; - if (_archTraits->hasSwap(group)) { + if (_archTraits->hasInstRegSwap(group)) { ASMJIT_PROPAGATE(onSwapReg(group, curWorkId, physId, dstWorkId, altPhysId)); } else { @@ -252,7 +232,7 @@ Error RALocalAllocator::switchToAssignment( ASMJIT_PROPAGATE(onKillReg(group, curWorkId, physId)); } else { - uint32_t allocableRegs = _pass->_availableRegs[group] & ~cur.assigned(group); + RegMask allocableRegs = _pass->_availableRegs[group] & ~cur.assigned(group); // If possible don't conflict with assigned regs at DST. if (allocableRegs & ~dst.assigned(group)) @@ -294,9 +274,8 @@ Cleared: // CUR dirty, DST not dirty (the assert is just to visualize the condition). ASMJIT_ASSERT(!dst.isPhysDirty(group, physId) && cur.isPhysDirty(group, physId)); - // If `dstReadOnly` is true it means that that block was already - // processed and we cannot change from CLEAN to DIRTY. In that case - // the register has to be saved as it cannot enter the block DIRTY. + // If `dstReadOnly` is true it means that that block was already processed and we cannot change from + // CLEAN to DIRTY. In that case the register has to be saved as it cannot enter the block DIRTY. if (dstReadOnly) ASMJIT_PROPAGATE(onSaveReg(group, dstWorkId, physId)); else @@ -319,13 +298,13 @@ Cleared: } } - // ------------------------------------------------------------------------ - // STEP 3: + // STEP 3 + // ------ + // // - Load registers specified by `willLoadRegs`. - // ------------------------------------------------------------------------ { - Support::BitWordIterator<uint32_t> it(willLoadRegs); + Support::BitWordIterator<RegMask> it(willLoadRegs); while (it.hasNext()) { uint32_t physId = it.next(); @@ -349,7 +328,7 @@ Cleared: } if (!tryMode) { - // Hre is a code that dumps the conflicting part if something fails here: + // Here is a code that dumps the conflicting part if something fails here: // if (!dst.equals(cur)) { // uint32_t physTotal = dst._layout.physTotal; // uint32_t workCount = dst._layout.workCount; @@ -374,9 +353,9 @@ Cleared: return kErrorOk; } -Error RALocalAllocator::spillScratchGpRegsBeforeEntry(uint32_t scratchRegs) noexcept { - uint32_t group = BaseReg::kGroupGp; - Support::BitWordIterator<uint32_t> it(scratchRegs); +Error RALocalAllocator::spillScratchGpRegsBeforeEntry(RegMask scratchRegs) noexcept { + RegGroup group = RegGroup::kGp; + Support::BitWordIterator<RegMask> it(scratchRegs); while (it.hasNext()) { uint32_t physId = it.next(); @@ -389,15 +368,15 @@ Error RALocalAllocator::spillScratchGpRegsBeforeEntry(uint32_t scratchRegs) noex return kErrorOk; } -// ============================================================================ -// [asmjit::RALocalAllocator - Allocation] -// ============================================================================ +// RALocalAllocator - Allocation +// ============================= Error RALocalAllocator::allocInst(InstNode* node) noexcept { RAInst* raInst = node->passData<RAInst>(); RATiedReg* outTiedRegs[Globals::kMaxPhysRegs]; RATiedReg* dupTiedRegs[Globals::kMaxPhysRegs]; + RATiedReg* consecutiveRegs[kMaxConsecutiveRegs]; // The cursor must point to the previous instruction for a possible instruction insertion. _cc->_setCursor(node->prev()); @@ -410,34 +389,43 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { // Whether we already replaced register operand with memory operand. bool rmAllocated = false; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { uint32_t i, count = this->tiedCount(group); RATiedReg* tiedRegs = this->tiedRegs(group); - uint32_t willUse = _raInst->_usedRegs[group]; - uint32_t willOut = _raInst->_clobberedRegs[group]; - uint32_t willFree = 0; - uint32_t usePending = count; + RegMask willUse = _raInst->_usedRegs[group]; + RegMask willOut = _raInst->_clobberedRegs[group]; + RegMask willFree = 0; + uint32_t usePending = count; uint32_t outTiedCount = 0; uint32_t dupTiedCount = 0; + uint32_t consecutiveMask = 0; - // ------------------------------------------------------------------------ - // STEP 1: + // STEP 1 + // ------ // - // Calculate `willUse` and `willFree` masks based on tied registers we have. + // Calculate `willUse` and `willFree` masks based on tied registers we have. In addition, aggregate information + // regarding consecutive registers used by this instruction. We need that to make USE/OUT assignments. // - // We don't do any assignment decisions at this stage as we just need to - // collect some information first. Then, after we populate all masks needed - // we can finally make some decisions in the second loop. The main reason - // for this is that we really need `willFree` to make assignment decisions - // for `willUse`, because if we mark some registers that will be freed, we - // can consider them in decision making afterwards. - // ------------------------------------------------------------------------ + // We don't do any assignment decisions at this stage as we just need to collect some information first. Then, + // after we populate all masks needed we can finally make some decisions in the second loop. The main reason + // for this is that we really need `willFree` to make assignment decisions for `willUse`, because if we mark + // some registers that will be freed, we can consider them in decision making afterwards. for (i = 0; i < count; i++) { RATiedReg* tiedReg = &tiedRegs[i]; + if (tiedReg->hasAnyConsecutiveFlag()) { + uint32_t consecutiveOffset = tiedReg->isLeadConsecutive() ? uint32_t(0) : tiedReg->consecutiveData(); + + if (ASMJIT_UNLIKELY(Support::bitTest(consecutiveMask, consecutiveOffset))) + return DebugUtils::errored(kErrorInvalidState); + + consecutiveMask |= Support::bitMask(consecutiveOffset); + consecutiveRegs[consecutiveOffset] = tiedReg; + } + // Add OUT and KILL to `outPending` for CLOBBERing and/or OUT assignment. if (tiedReg->isOutOrKill()) outTiedRegs[outTiedCount++] = tiedReg; @@ -451,12 +439,16 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { continue; } + // Don't assign anything here if this is a consecutive USE - we will handle this in STEP 2 instead. + if (tiedReg->isUseConsecutive()) + continue; + uint32_t workId = tiedReg->workId(); uint32_t assignedId = _curAssignment.workToPhysId(group, workId); if (tiedReg->hasUseId()) { // If the register has `useId` it means it can only be allocated in that register. - uint32_t useMask = Support::bitMask(tiedReg->useId()); + RegMask useMask = Support::bitMask(tiedReg->useId()); // RAInstBuilder must have collected `usedRegs` on-the-fly. ASMJIT_ASSERT((willUse & useMask) != 0); @@ -475,9 +467,9 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } else { // Check if the register must be moved to `allocableRegs`. - uint32_t allocableRegs = tiedReg->allocableRegs(); + RegMask allocableRegs = tiedReg->useRegMask(); if (assignedId != RAAssignment::kPhysNone) { - uint32_t assignedMask = Support::bitMask(assignedId); + RegMask assignedMask = Support::bitMask(assignedId); if ((allocableRegs & ~willUse) & assignedMask) { tiedReg->setUseId(assignedId); tiedReg->markUseDone(); @@ -493,24 +485,107 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } } - // ------------------------------------------------------------------------ - // STEP 2: + // STEP 2 + // ------ // - // Do some decision making to find the best candidates of registers that - // need to be assigned, moved, and/or spilled. Only USE registers are - // considered here, OUT will be decided later after all CLOBBERed and OUT + // Verify that all the consecutive registers are really consecutive. Terminate if there is a gap. In addition, + // decide which USE ids will be used in case that this consecutive sequence is USE (OUT registers are allocated + // in a different step). + uint32_t consecutiveCount = 0; + + if (consecutiveMask) { + if ((consecutiveMask & (consecutiveMask + 1u)) != 0) + return DebugUtils::errored(kErrorInvalidState); + + // Count of trailing ones is the count of consecutive registers. There cannot be gap. + consecutiveCount = Support::ctz(~consecutiveMask); + + // Prioritize allocation that would result in least moves even when moving registers away from their homes. + RATiedReg* lead = consecutiveRegs[0]; + + // Assign the best possible USE Ids to all consecutives. + if (lead->isUseConsecutive()) { + uint32_t bestScore = 0; + uint32_t bestLeadReg = 0xFFFFFFFF; + RegMask allocableRegs = (_availableRegs[group] | willFree) & ~willUse; + + uint32_t assignments[kMaxConsecutiveRegs]; + + for (i = 0; i < consecutiveCount; i++) + assignments[i] = _curAssignment.workToPhysId(group, consecutiveRegs[i]->workId()); + + Support::BitWordIterator<uint32_t> it(lead->useRegMask()); + while (it.hasNext()) { + uint32_t regIndex = it.next(); + if (Support::bitTest(lead->useRegMask(), regIndex)) { + uint32_t score = 15; + + for (i = 0; i < consecutiveCount; i++) { + uint32_t consecutiveIndex = regIndex + i; + if (!Support::bitTest(allocableRegs, consecutiveIndex)) { + score = 0; + break; + } + + RAWorkReg* workReg = workRegById(consecutiveRegs[i]->workId()); + score += uint32_t(workReg->homeRegId() == consecutiveIndex); + score += uint32_t(assignments[i] == consecutiveIndex) * 2; + } + + if (score > bestScore) { + bestScore = score; + bestLeadReg = regIndex; + } + } + } + + if (bestLeadReg == 0xFFFFFFFF) + return DebugUtils::errored(kErrorConsecutiveRegsAllocation); + + for (i = 0; i < consecutiveCount; i++) { + uint32_t consecutiveIndex = bestLeadReg + i; + + RATiedReg* tiedReg = consecutiveRegs[i]; + RegMask useMask = Support::bitMask(consecutiveIndex); + + uint32_t workId = tiedReg->workId(); + uint32_t assignedId = _curAssignment.workToPhysId(group, workId); + + tiedReg->setUseId(consecutiveIndex); + + if (assignedId == consecutiveIndex) { + // If the register is already allocated in this one, mark it done and continue. + tiedReg->markUseDone(); + if (tiedReg->isWrite()) + _curAssignment.makeDirty(group, workId, assignedId); + usePending--; + willUse |= useMask; + } + else { + willUse |= useMask; + willFree |= useMask & _curAssignment.assigned(group); + } + } + } + } + + // STEP 3 + // ------ + // + // Do some decision making to find the best candidates of registers that need to be assigned, moved, and/or + // spilled. Only USE registers are considered here, OUT will be decided later after all CLOBBERed and OUT // registers are unassigned. - // ------------------------------------------------------------------------ if (usePending) { // TODO: Not sure `liveRegs` should be used, maybe willUse and willFree would be enough and much more clear. // All registers that are currently alive without registers that will be freed. - uint32_t liveRegs = _curAssignment.assigned(group) & ~willFree; + RegMask liveRegs = _curAssignment.assigned(group) & ~willFree; for (i = 0; i < count; i++) { RATiedReg* tiedReg = &tiedRegs[i]; - if (tiedReg->isUseDone()) continue; + if (tiedReg->isUseDone()) + continue; uint32_t workId = tiedReg->workId(); uint32_t assignedId = _curAssignment.workToPhysId(group, workId); @@ -538,18 +613,17 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } if (!tiedReg->hasUseId()) { - uint32_t allocableRegs = tiedReg->allocableRegs() & ~(willFree | willUse); - // DECIDE where to assign the USE register. + RegMask allocableRegs = tiedReg->useRegMask() & ~(willFree | willUse); uint32_t useId = decideOnAssignment(group, workId, assignedId, allocableRegs); - uint32_t useMask = Support::bitMask(useId); + RegMask useMask = Support::bitMask(useId); willUse |= useMask; willFree |= useMask & liveRegs; tiedReg->setUseId(useId); if (assignedId != RAAssignment::kPhysNone) { - uint32_t assignedMask = Support::bitMask(assignedId); + RegMask assignedMask = Support::bitMask(assignedId); willFree |= assignedMask; liveRegs &= ~assignedMask; @@ -579,19 +653,18 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } } - // Initially all used regs will be marked clobbered. - uint32_t clobberedByInst = willUse | willOut; + // Initially all used regs will be marked as clobbered. + RegMask clobberedByInst = willUse | willOut; - // ------------------------------------------------------------------------ - // STEP 3: + // STEP 4 + // ------ // - // Free all registers that we marked as `willFree`. Only registers that are not - // USEd by the instruction are considered as we don't want to free regs we need. - // ------------------------------------------------------------------------ + // Free all registers that we marked as `willFree`. Only registers that are not USEd by the instruction are + // considered as we don't want to free regs we need. if (willFree) { - uint32_t allocableRegs = _availableRegs[group] & ~(_curAssignment.assigned(group) | willFree | willUse | willOut); - Support::BitWordIterator<uint32_t> it(willFree); + RegMask allocableRegs = _availableRegs[group] & ~(_curAssignment.assigned(group) | willFree | willUse | willOut); + Support::BitWordIterator<RegMask> it(willFree); do { uint32_t assignedId = it.next(); @@ -613,21 +686,17 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } while (it.hasNext()); } - // ------------------------------------------------------------------------ - // STEP 4: + // STEP 5 + // ------ // - // ALLOCATE / SHUFFLE all registers that we marked as `willUse` and weren't - // allocated yet. This is a bit complicated as the allocation is iterative. - // In some cases we have to wait before allocating a particual physical - // register as it's still occupied by some other one, which we need to move - // before we can use it. In this case we skip it and allocate another some - // other instead (making it free for another iteration). + // ALLOCATE / SHUFFLE all registers that we marked as `willUse` and weren't allocated yet. This is a bit + // complicated as the allocation is iterative. In some cases we have to wait before allocating a particual + // physical register as it's still occupied by some other one, which we need to move before we can use it. + // In this case we skip it and allocate another some other instead (making it free for another iteration). // - // NOTE: Iterations are mostly important for complicated allocations like - // function calls, where there can be up to N registers used at once. Asm - // instructions won't run the loop more than once in 99.9% of cases as they - // use 2..3 registers in average. - // ------------------------------------------------------------------------ + // NOTE: Iterations are mostly important for complicated allocations like function calls, where there can + // be up to N registers used at once. Asm instructions won't run the loop more than once in 99.9% of cases + // as they use 2..3 registers in average. if (usePending) { bool mustSwap = false; @@ -636,7 +705,8 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { for (i = 0; i < count; i++) { RATiedReg* thisTiedReg = &tiedRegs[i]; - if (thisTiedReg->isUseDone()) continue; + if (thisTiedReg->isUseDone()) + continue; uint32_t thisWorkId = thisTiedReg->workId(); uint32_t thisPhysId = _curAssignment.workToPhysId(group, thisWorkId); @@ -649,11 +719,10 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { if (targetWorkId != RAAssignment::kWorkNone) { RAWorkReg* targetWorkReg = workRegById(targetWorkId); - // Swapping two registers can solve two allocation tasks by emitting - // just a single instruction. However, swap is only available on few - // architectures and it's definitely not available for each register - // group. Calling `onSwapReg()` before checking these would be fatal. - if (_archTraits->hasSwap(group) && thisPhysId != RAAssignment::kPhysNone) { + // Swapping two registers can solve two allocation tasks by emitting just a single instruction. However, + // swap is only available on few architectures and it's definitely not available for each register group. + // Calling `onSwapReg()` before checking these would be fatal. + if (_archTraits->hasInstRegSwap(group) && thisPhysId != RAAssignment::kPhysNone) { ASMJIT_PROPAGATE(onSwapReg(group, thisWorkId, thisPhysId, targetWorkId, targetPhysId)); thisTiedReg->markUseDone(); @@ -675,10 +744,9 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { if (!mustSwap) continue; - // Only branched here if the previous iteration did nothing. This is - // essentially a SWAP operation without having a dedicated instruction - // for that purpose (vector registers, etc). The simplest way to - // handle such case is to SPILL the target register. + // Only branched here if the previous iteration did nothing. This is essentially a SWAP operation without + // having a dedicated instruction for that purpose (vector registers, etc). The simplest way to handle + // such case is to SPILL the target register. ASMJIT_PROPAGATE(onSpillReg(group, targetWorkId, targetPhysId)); } @@ -704,11 +772,10 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } while (usePending); } - // ------------------------------------------------------------------------ - // STEP 5: + // STEP 6 + // ------ // // KILL registers marked as KILL/OUT. - // ------------------------------------------------------------------------ uint32_t outPending = outTiedCount; if (outTiedCount) { @@ -718,28 +785,27 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { uint32_t workId = tiedReg->workId(); uint32_t physId = _curAssignment.workToPhysId(group, workId); - // Must check if it's allocated as KILL can be related to OUT (like KILL - // immediately after OUT, which could mean the register is not assigned). + // Must check if it's allocated as KILL can be related to OUT (like KILL immediately after OUT, which could + // mean the register is not assigned). if (physId != RAAssignment::kPhysNone) { ASMJIT_PROPAGATE(onKillReg(group, workId, physId)); willOut &= ~Support::bitMask(physId); } - // We still maintain number of pending registers for OUT assignment. - // So, if this is only KILL, not OUT, we can safely decrement it. + // We still maintain number of pending registers for OUT assignment. So, if this is only KILL, not OUT, we + // can safely decrement it. outPending -= !tiedReg->isOut(); } } - // ------------------------------------------------------------------------ - // STEP 6: + // STEP 7 + // ------ // - // SPILL registers that will be CLOBBERed. Since OUT and KILL were - // already processed this is used mostly to handle function CALLs. - // ------------------------------------------------------------------------ + // SPILL registers that will be CLOBBERed. Since OUT and KILL were already processed this is used mostly to + // handle function CALLs. if (willOut) { - Support::BitWordIterator<uint32_t> it(willOut); + Support::BitWordIterator<RegMask> it(willOut); do { uint32_t physId = it.next(); uint32_t workId = _curAssignment.physToWorkId(group, physId); @@ -751,18 +817,17 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } while (it.hasNext()); } - // ------------------------------------------------------------------------ - // STEP 7: + // STEP 8 + // ------ // // Duplication. - // ------------------------------------------------------------------------ for (i = 0; i < dupTiedCount; i++) { RATiedReg* tiedReg = dupTiedRegs[i]; uint32_t workId = tiedReg->workId(); uint32_t srcId = tiedReg->useId(); - Support::BitWordIterator<uint32_t> it(tiedReg->_allocableRegs); + Support::BitWordIterator<RegMask> it(tiedReg->useRegMask()); while (it.hasNext()) { uint32_t dstId = it.next(); if (dstId == srcId) @@ -771,27 +836,71 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } } - // ------------------------------------------------------------------------ - // STEP 8: + // STEP 9 + // ------ // // Assign OUT registers. - // ------------------------------------------------------------------------ if (outPending) { - // Live registers, we need a separate variable (outside of `_curAssignment) - // to hold these because of KILLed registers. If we KILL a register here it - // will go out from `_curAssignment`, but we cannot assign to it in here. - uint32_t liveRegs = _curAssignment.assigned(group); + // Live registers, we need a separate register (outside of `_curAssignment) to hold these because of KILLed + // registers. If we KILL a register here it will go out from `_curAssignment`, but we cannot assign to it in + // here. + RegMask liveRegs = _curAssignment.assigned(group); // Must avoid as they have been already OUTed (added during the loop). - uint32_t outRegs = 0; + RegMask outRegs = 0; // Must avoid as they collide with already allocated ones. - uint32_t avoidRegs = willUse & ~clobberedByInst; + RegMask avoidRegs = willUse & ~clobberedByInst; + + // Assign the best possible OUT ids of all consecutives. + if (consecutiveCount) { + RATiedReg* lead = consecutiveRegs[0]; + if (lead->isOutConsecutive()) { + uint32_t bestScore = 0; + uint32_t bestLeadReg = 0xFFFFFFFF; + RegMask allocableRegs = _availableRegs[group] & ~(outRegs | avoidRegs); + + Support::BitWordIterator<uint32_t> it(lead->outRegMask()); + while (it.hasNext()) { + uint32_t regIndex = it.next(); + if (Support::bitTest(lead->outRegMask(), regIndex)) { + uint32_t score = 15; + + for (i = 0; i < consecutiveCount; i++) { + uint32_t consecutiveIndex = regIndex + i; + if (!Support::bitTest(allocableRegs, consecutiveIndex)) { + score = 0; + break; + } + + RAWorkReg* workReg = workRegById(consecutiveRegs[i]->workId()); + score += uint32_t(workReg->homeRegId() == consecutiveIndex); + } + + if (score > bestScore) { + bestScore = score; + bestLeadReg = regIndex; + } + } + } + + if (bestLeadReg == 0xFFFFFFFF) + return DebugUtils::errored(kErrorConsecutiveRegsAllocation); + + for (i = 0; i < consecutiveCount; i++) { + uint32_t consecutiveIndex = bestLeadReg + i; + RATiedReg* tiedReg = consecutiveRegs[i]; + tiedReg->setOutId(consecutiveIndex); + } + } + } + // Allocate OUT registers. for (i = 0; i < outTiedCount; i++) { RATiedReg* tiedReg = outTiedRegs[i]; - if (!tiedReg->isOut()) continue; + if (!tiedReg->isOut()) + continue; uint32_t workId = tiedReg->workId(); uint32_t assignedId = _curAssignment.workToPhysId(group, workId); @@ -801,7 +910,7 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { uint32_t physId = tiedReg->outId(); if (physId == RAAssignment::kPhysNone) { - uint32_t allocableRegs = tiedReg->_allocableRegs & ~(outRegs | avoidRegs); + RegMask allocableRegs = tiedReg->outRegMask() & ~(outRegs | avoidRegs); if (!(allocableRegs & ~liveRegs)) { // There are no more registers, decide which one to spill. @@ -839,9 +948,8 @@ Error RALocalAllocator::allocInst(InstNode* node) noexcept { } Error RALocalAllocator::spillAfterAllocation(InstNode* node) noexcept { - // This is experimental feature that would spill registers that don't have - // home-id and are last in this basic block. This prevents saving these regs - // in other basic blocks and then restoring them (mostly relevant for loops). + // This is experimental feature that would spill registers that don't have home-id and are last in this basic block. + // This prevents saving these regs in other basic blocks and then restoring them (mostly relevant for loops). RAInst* raInst = node->passData<RAInst>(); uint32_t count = raInst->tiedCount(); @@ -851,7 +959,7 @@ Error RALocalAllocator::spillAfterAllocation(InstNode* node) noexcept { uint32_t workId = tiedReg->workId(); RAWorkReg* workReg = workRegById(workId); if (!workReg->hasHomeRegId()) { - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); uint32_t assignedId = _curAssignment.workToPhysId(group, workId); if (assignedId != RAAssignment::kPhysNone) { _cc->_setCursor(node); @@ -898,9 +1006,8 @@ Error RALocalAllocator::allocBranch(InstNode* node, RABlock* target, RABlock* co BaseNode* curCursor = _cc->cursor(); if (curCursor != injectionPoint) { - // Additional instructions emitted to switch from the current state to - // the `target` state. This means that we have to move these instructions - // into an independent code block and patch the jump location. + // Additional instructions emitted to switch from the current state to the `target` state. This means + // that we have to move these instructions into an independent code block and patch the jump location. Operand& targetOp = node->op(node->opCount() - 1); if (ASMJIT_UNLIKELY(!targetOp.isLabel())) return DebugUtils::errored(kErrorInvalidState); @@ -911,9 +1018,9 @@ Error RALocalAllocator::allocBranch(InstNode* node, RABlock* target, RABlock* co // Patch `target` to point to the `trampoline` we just created. targetOp = trampoline; - // Clear a possible SHORT form as we have no clue now if the SHORT form would - // be encodable after patching the target to `trampoline` (X86 specific). - node->clearInstOptions(BaseInst::kOptionShortForm); + // Clear a possible SHORT form as we have no clue now if the SHORT form would be encodable after patching + // the target to `trampoline` (X86 specific). + node->clearOptions(InstOptions::kShortForm); // Finalize the switch assignment sequence. ASMJIT_PROPAGATE(_pass->emitJump(savedTarget)); @@ -969,11 +1076,10 @@ Error RALocalAllocator::allocJumpTable(InstNode* node, const RABlocks& targets, return kErrorOk; } -// ============================================================================ -// [asmjit::RALocalAllocator - Decision Making] -// ============================================================================ +// RALocalAllocator - Decision Making +// ================================== -uint32_t RALocalAllocator::decideOnAssignment(uint32_t group, uint32_t workId, uint32_t physId, uint32_t allocableRegs) const noexcept { +uint32_t RALocalAllocator::decideOnAssignment(RegGroup group, uint32_t workId, uint32_t physId, RegMask allocableRegs) const noexcept { ASMJIT_ASSERT(allocableRegs != 0); DebugUtils::unused(group, physId); @@ -987,14 +1093,14 @@ uint32_t RALocalAllocator::decideOnAssignment(uint32_t group, uint32_t workId, u } // Prefer registers used upon block entries. - uint32_t previouslyAssignedRegs = workReg->allocatedMask(); + RegMask previouslyAssignedRegs = workReg->allocatedMask(); if (allocableRegs & previouslyAssignedRegs) allocableRegs &= previouslyAssignedRegs; return Support::ctz(allocableRegs); } -uint32_t RALocalAllocator::decideOnReassignment(uint32_t group, uint32_t workId, uint32_t physId, uint32_t allocableRegs) const noexcept { +uint32_t RALocalAllocator::decideOnReassignment(RegGroup group, uint32_t workId, uint32_t physId, RegMask allocableRegs) const noexcept { ASMJIT_ASSERT(allocableRegs != 0); DebugUtils::unused(group, physId); @@ -1012,12 +1118,12 @@ uint32_t RALocalAllocator::decideOnReassignment(uint32_t group, uint32_t workId, return RAAssignment::kPhysNone; } -uint32_t RALocalAllocator::decideOnSpillFor(uint32_t group, uint32_t workId, uint32_t spillableRegs, uint32_t* spillWorkId) const noexcept { +uint32_t RALocalAllocator::decideOnSpillFor(RegGroup group, uint32_t workId, RegMask spillableRegs, uint32_t* spillWorkId) const noexcept { // May be used in the future to decide which register would be best to spill so `workId` can be assigned. DebugUtils::unused(workId); ASMJIT_ASSERT(spillableRegs != 0); - Support::BitWordIterator<uint32_t> it(spillableRegs); + Support::BitWordIterator<RegMask> it(spillableRegs); uint32_t bestPhysId = it.next(); uint32_t bestWorkId = _curAssignment.physToWorkId(group, bestPhysId); diff --git a/src/asmjit/core/ralocal_p.h b/src/asmjit/core/ralocal_p.h index eebecc9..05467c5 100644 --- a/src/asmjit/core/ralocal_p.h +++ b/src/asmjit/core/ralocal_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RALOCAL_P_H_INCLUDED #define ASMJIT_CORE_RALOCAL_P_H_INCLUDED @@ -38,10 +20,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [asmjit::RALocalAllocator] -// ============================================================================ - //! Local register allocator. class RALocalAllocator { public: @@ -119,14 +97,14 @@ public: //! Returns all tied regs as `RATiedReg` array. inline RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); } //! Returns tied registers grouped by the given `group`. - inline RATiedReg* tiedRegs(uint32_t group) const noexcept { return _raInst->tiedRegs(group); } + inline RATiedReg* tiedRegs(RegGroup group) const noexcept { return _raInst->tiedRegs(group); } //! Returns count of all TiedRegs used by the instruction. inline uint32_t tiedCount() const noexcept { return _tiedTotal; } //! Returns count of TiedRegs used by the given register `group`. - inline uint32_t tiedCount(uint32_t group) const noexcept { return _tiedCount.get(group); } + inline uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount.get(group); } - inline bool isGroupUsed(uint32_t group) const noexcept { return _tiedCount[group] != 0; } + inline bool isGroupUsed(RegGroup group) const noexcept { return _tiedCount[group] != 0; } //! \} @@ -139,14 +117,12 @@ public: const PhysToWorkMap* physToWorkMap, const WorkToPhysMap* workToPhysMap) noexcept; - //! Switch to the given assignment by reassigning all register and emitting - //! code that reassigns them. This is always used to switch to a previously - //! stored assignment. + //! Switch to the given assignment by reassigning all register and emitting code that reassigns them. + //! This is always used to switch to a previously stored assignment. //! - //! If `tryMode` is true then the final assignment doesn't have to be exactly - //! same as specified by `dstPhysToWorkMap` and `dstWorkToPhysMap`. This mode - //! is only used before conditional jumps that already have assignment to - //! generate a code sequence that is always executed regardless of the flow. + //! If `tryMode` is true then the final assignment doesn't have to be exactly same as specified by `dstPhysToWorkMap` + //! and `dstWorkToPhysMap`. This mode is only used before conditional jumps that already have assignment to generate + //! a code sequence that is always executed regardless of the flow. Error switchToAssignment( PhysToWorkMap* dstPhysToWorkMap, WorkToPhysMap* dstWorkToPhysMap, @@ -185,7 +161,7 @@ public: return uint32_t(int32_t(freq * float(kCostOfFrequency))); } - inline uint32_t calculateSpillCost(uint32_t group, uint32_t workId, uint32_t assignedId) const noexcept { + inline uint32_t calculateSpillCost(RegGroup group, uint32_t workId, uint32_t assignedId) const noexcept { RAWorkReg* workReg = workRegById(workId); uint32_t cost = costByFrequency(workReg->liveStats().freq()); @@ -196,18 +172,18 @@ public: } //! Decides on register assignment. - uint32_t decideOnAssignment(uint32_t group, uint32_t workId, uint32_t assignedId, uint32_t allocableRegs) const noexcept; + uint32_t decideOnAssignment(RegGroup group, uint32_t workId, uint32_t assignedId, RegMask allocableRegs) const noexcept; - //! Decides on whether to MOVE or SPILL the given WorkReg, because it's allocated - //! in a physical register that have to be used by another WorkReg. + //! Decides on whether to MOVE or SPILL the given WorkReg, because it's allocated in a physical register that have + //! to be used by another WorkReg. //! - //! The function must return either `RAAssignment::kPhysNone`, which means that - //! the WorkReg of `workId` should be spilled, or a valid physical register ID, - //! which means that the register should be moved to that physical register instead. - uint32_t decideOnReassignment(uint32_t group, uint32_t workId, uint32_t assignedId, uint32_t allocableRegs) const noexcept; + //! The function must return either `RAAssignment::kPhysNone`, which means that the WorkReg of `workId` should be + //! spilled, or a valid physical register ID, which means that the register should be moved to that physical register + //! instead. + uint32_t decideOnReassignment(RegGroup group, uint32_t workId, uint32_t assignedId, RegMask allocableRegs) const noexcept; //! Decides on best spill given a register mask `spillableRegs` - uint32_t decideOnSpillFor(uint32_t group, uint32_t workId, uint32_t spillableRegs, uint32_t* spillWorkId) const noexcept; + uint32_t decideOnSpillFor(RegGroup group, uint32_t workId, RegMask spillableRegs, uint32_t* spillWorkId) const noexcept; //! \} @@ -216,7 +192,7 @@ public: //! Emits a move between a destination and source register, and fixes the //! register assignment. - inline Error onMoveReg(uint32_t group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { + inline Error onMoveReg(RegGroup group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { if (dstPhysId == srcPhysId) return kErrorOk; _curAssignment.reassign(group, workId, dstPhysId, srcPhysId); return _pass->emitMove(workId, dstPhysId, srcPhysId); @@ -225,21 +201,21 @@ public: //! Emits a swap between two physical registers and fixes their assignment. //! //! \note Target must support this operation otherwise this would ASSERT. - inline Error onSwapReg(uint32_t group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { + inline Error onSwapReg(RegGroup group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { _curAssignment.swap(group, aWorkId, aPhysId, bWorkId, bPhysId); return _pass->emitSwap(aWorkId, aPhysId, bWorkId, bPhysId); } //! Emits a load from [VirtReg/WorkReg]'s spill slot to a physical register //! and makes it assigned and clean. - inline Error onLoadReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline Error onLoadReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept { _curAssignment.assign(group, workId, physId, RAAssignment::kClean); return _pass->emitLoad(workId, physId); } //! Emits a save a physical register to a [VirtReg/WorkReg]'s spill slot, //! keeps it assigned, and makes it clean. - inline Error onSaveReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline Error onSaveReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept { ASMJIT_ASSERT(_curAssignment.workToPhysId(group, workId) == physId); ASMJIT_ASSERT(_curAssignment.physToWorkId(group, physId) == workId); @@ -248,24 +224,24 @@ public: } //! Assigns a register, the content of it is undefined at this point. - inline Error onAssignReg(uint32_t group, uint32_t workId, uint32_t physId, uint32_t dirty) noexcept { + inline Error onAssignReg(RegGroup group, uint32_t workId, uint32_t physId, bool dirty) noexcept { _curAssignment.assign(group, workId, physId, dirty); return kErrorOk; } //! Spills a variable/register, saves the content to the memory-home if modified. - inline Error onSpillReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline Error onSpillReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept { if (_curAssignment.isPhysDirty(group, physId)) ASMJIT_PROPAGATE(onSaveReg(group, workId, physId)); return onKillReg(group, workId, physId); } - inline Error onDirtyReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline Error onDirtyReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept { _curAssignment.makeDirty(group, workId, physId); return kErrorOk; } - inline Error onKillReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline Error onKillReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept { _curAssignment.unassign(group, workId, physId); return kErrorOk; } diff --git a/src/asmjit/core/rapass.cpp b/src/asmjit/core/rapass.cpp index 5e55584..9d714cd 100644 --- a/src/asmjit/core/rapass.cpp +++ b/src/asmjit/core/rapass.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_COMPILER @@ -33,16 +15,14 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::RABlock - Control Flow] -// ============================================================================ +// RABlock - Control Flow +// ====================== Error RABlock::appendSuccessor(RABlock* successor) noexcept { RABlock* predecessor = this; - if (predecessor->_successors.contains(successor)) + if (predecessor->hasSuccessor(successor)) return kErrorOk; - ASMJIT_ASSERT(!successor->_predecessors.contains(predecessor)); ASMJIT_PROPAGATE(successor->_predecessors.willGrow(allocator())); ASMJIT_PROPAGATE(predecessor->_successors.willGrow(allocator())); @@ -56,9 +36,8 @@ Error RABlock::appendSuccessor(RABlock* successor) noexcept { Error RABlock::prependSuccessor(RABlock* successor) noexcept { RABlock* predecessor = this; - if (predecessor->_successors.contains(successor)) + if (predecessor->hasSuccessor(successor)) return kErrorOk; - ASMJIT_ASSERT(!successor->_predecessors.contains(predecessor)); ASMJIT_PROPAGATE(successor->_predecessors.willGrow(allocator())); ASMJIT_PROPAGATE(predecessor->_successors.willGrow(allocator())); @@ -69,18 +48,16 @@ Error RABlock::prependSuccessor(RABlock* successor) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - Construction / Destruction] -// ============================================================================ +// BaseRAPass - Construction & Destruction +// ======================================= BaseRAPass::BaseRAPass() noexcept : FuncPass("BaseRAPass") {} BaseRAPass::~BaseRAPass() noexcept {} -// ============================================================================ -// [asmjit::BaseRAPass - RunOnFunction] -// ============================================================================ +// BaseRAPass - RunOnFunction +// ========================== -static void RAPass_reset(BaseRAPass* self, FuncDetail* funcDetail) noexcept { +static void BaseRAPass_reset(BaseRAPass* self, FuncDetail* funcDetail) noexcept { ZoneAllocator* allocator = self->allocator(); self->_blocks.reset(); @@ -97,20 +74,16 @@ static void RAPass_reset(BaseRAPass* self, FuncDetail* funcDetail) noexcept { self->_physRegIndex.reset(); self->_physRegCount.reset(); self->_physRegTotal = 0; - - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(self->_scratchRegIndexes); i++) - self->_scratchRegIndexes[i] = BaseReg::kIdBad; + self->_scratchRegIndexes.fill(BaseReg::kIdBad); self->_availableRegs.reset(); self->_availableRegCount.reset(); self->_clobberedRegs.reset(); self->_workRegs.reset(); - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - self->_workRegsOfGroup[group].reset(); - self->_strategy[group].reset(); - self->_globalLiveSpans[group] = nullptr; - } + self->_workRegsOfGroup.forEach([](RAWorkRegs& regs) { regs.reset(); }); + self->_strategy.forEach([](RAStrategy& strategy) { strategy.reset(); }); + self->_globalLiveSpans.fill(nullptr); self->_globalMaxLiveCount.reset(); self->_temporaryMem.reset(); @@ -120,7 +93,7 @@ static void RAPass_reset(BaseRAPass* self, FuncDetail* funcDetail) noexcept { self->_maxWorkRegNameSize = 0; } -static void RAPass_resetVirtRegData(BaseRAPass* self) noexcept { +static void BaseRAPass_resetVirtRegData(BaseRAPass* self) noexcept { // Zero everything so it cannot be used by accident. for (RAWorkReg* wReg : self->_workRegs) { VirtReg* vReg = wReg->virtReg(); @@ -133,12 +106,12 @@ Error BaseRAPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { #ifndef ASMJIT_NO_LOGGING _logger = logger; - _debugLogger = nullptr; + _formatOptions.reset(); + _diagnosticOptions = DiagnosticOptions::kNone; if (logger) { - _loggerFlags = logger->flags(); - if (_loggerFlags & FormatOptions::kFlagDebugPasses) - _debugLogger = logger; + _formatOptions = logger->options(); + _diagnosticOptions = _cb->diagnosticOptions(); } #else DebugUtils::unused(logger); @@ -150,7 +123,7 @@ Error BaseRAPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { _stop = end->next(); _extraBlock = end; - RAPass_reset(this, &_func->_funcDetail); + BaseRAPass_reset(this, &_func->_funcDetail); // Initialize architecture-specific members. onInit(); @@ -162,16 +135,16 @@ Error BaseRAPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { onDone(); // Reset possible connections introduced by the register allocator. - RAPass_resetVirtRegData(this); + BaseRAPass_resetVirtRegData(this); // Reset all core structures and everything that depends on the passed `Zone`. - RAPass_reset(this, nullptr); + BaseRAPass_reset(this, nullptr); _allocator.reset(nullptr); #ifndef ASMJIT_NO_LOGGING _logger = nullptr; - _debugLogger = nullptr; - _loggerFlags = 0; + _formatOptions.reset(); + _diagnosticOptions = DiagnosticOptions::kNone; #endif _func = nullptr; @@ -181,9 +154,8 @@ Error BaseRAPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { // Reset `Zone` as nothing should persist between `runOnFunction()` calls. zone->reset(); - // We alter the compiler cursor, because it doesn't make sense to reference - // it after the compilation - some nodes may disappear and the old cursor - // can go out anyway. + // We alter the compiler cursor, because it doesn't make sense to reference it after the compilation - some + // nodes may disappear and the old cursor can go out anyway. cc()->_setCursor(cc()->lastNode()); return err; @@ -191,15 +163,15 @@ Error BaseRAPass::runOnFunction(Zone* zone, Logger* logger, FuncNode* func) { Error BaseRAPass::onPerformAllSteps() noexcept { ASMJIT_PROPAGATE(buildCFG()); - ASMJIT_PROPAGATE(buildViews()); - ASMJIT_PROPAGATE(removeUnreachableBlocks()); + ASMJIT_PROPAGATE(buildCFGViews()); + ASMJIT_PROPAGATE(removeUnreachableCode()); - ASMJIT_PROPAGATE(buildDominators()); + ASMJIT_PROPAGATE(buildCFGDominators()); ASMJIT_PROPAGATE(buildLiveness()); ASMJIT_PROPAGATE(assignArgIndexToWorkRegs()); #ifndef ASMJIT_NO_LOGGING - if (logger() && logger()->hasFlag(FormatOptions::kFlagAnnotations)) + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) ASMJIT_PROPAGATE(annotateCode()); #endif @@ -214,9 +186,8 @@ Error BaseRAPass::onPerformAllSteps() noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - CFG - Basic Block Management] -// ============================================================================ +// BaseRAPass - CFG - Basic Block Management +// ========================================= RABlock* BaseRAPass::newBlock(BaseNode* initialNode) noexcept { RABlock* block = zone()->newT<RABlock>(this); @@ -238,9 +209,8 @@ RABlock* BaseRAPass::newBlockOrExistingAt(LabelNode* cbLabel, BaseNode** stopped BaseNode* node = cbLabel->prev(); RABlock* block = nullptr; - // Try to find some label, but terminate the loop on any code. We try hard to - // coalesce code that contains two consecutive labels or a combination of - // non-code nodes between 2 or more labels. + // Try to find some label, but terminate the loop on any code. We try hard to coalesce code that contains two + // consecutive labels or a combination of non-code nodes between 2 or more labels. // // Possible cases that would share the same basic block: // @@ -256,16 +226,15 @@ RABlock* BaseRAPass::newBlockOrExistingAt(LabelNode* cbLabel, BaseNode** stopped size_t nPendingLabels = 0; while (node) { - if (node->type() == BaseNode::kNodeLabel) { - // Function has a different NodeType, just make sure this was not messed - // up as we must never associate BasicBlock with a `func` itself. + if (node->type() == NodeType::kLabel) { + // Function has a different NodeType, just make sure this was not messed up as we must never associate + // BasicBlock with a `func` itself. ASMJIT_ASSERT(node != func); block = node->passData<RABlock>(); if (block) { - // Exit node has always a block associated with it. If we went here it - // means that `cbLabel` passed here is after the end of the function - // and cannot be merged with the function exit block. + // Exit node has always a block associated with it. If we went here it means that `cbLabel` passed here + // is after the end of the function and cannot be merged with the function exit block. if (node == func->exitNode()) block = nullptr; break; @@ -273,7 +242,7 @@ RABlock* BaseRAPass::newBlockOrExistingAt(LabelNode* cbLabel, BaseNode** stopped nPendingLabels++; } - else if (node->type() == BaseNode::kNodeAlign) { + else if (node->type() == NodeType::kAlign) { // Align node is fine. } else { @@ -298,7 +267,7 @@ RABlock* BaseRAPass::newBlockOrExistingAt(LabelNode* cbLabel, BaseNode** stopped while (nPendingLabels) { node = node->prev(); for (;;) { - if (node->type() == BaseNode::kNodeLabel) { + if (node->type() == NodeType::kLabel) { node->setPassData<RABlock>(block); nPendingLabels--; break; @@ -325,9 +294,8 @@ Error BaseRAPass::addBlock(RABlock* block) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - CFG - Build] -// ============================================================================ +// BaseRAPass - CFG - Build +// ======================== Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssignmentsMap) noexcept { if (sharedAssignmentsMap.empty()) @@ -344,16 +312,15 @@ Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssign ASMJIT_PROPAGATE(_sharedAssignments.resize(allocator(), count)); - // Aggregate all entry scratch GP regs from blocks of the same assignment to - // the assignment itself. It will then be used instead of RABlock's own scratch - // regs mask, as shared assignments have precedence. + // Aggregate all entry scratch GP regs from blocks of the same assignment to the assignment itself. It will then be + // used instead of RABlock's own scratch regs mask, as shared assignments have precedence. for (RABlock* block : _blocks) { if (block->hasJumpTable()) { const RABlocks& successors = block->successors(); if (!successors.empty()) { RABlock* firstSuccessor = successors[0]; - // NOTE: Shared assignments connect all possible successors so we only - // need the first to propagate exit scratch gp registers. + // NOTE: Shared assignments connect all possible successors so we only need the first to propagate exit scratch + // GP registers. ASMJIT_ASSERT(firstSuccessor->hasSharedAssignmentId()); RASharedAssignment& sa = _sharedAssignments[firstSuccessor->sharedAssignmentId()]; sa.addEntryScratchGpRegs(block->exitScratchGpRegs()); @@ -368,9 +335,8 @@ Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssign return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - CFG - Views Order] -// ============================================================================ +// BaseRAPass - CFG - Views Order +// ============================== class RABlockVisitItem { public: @@ -391,10 +357,10 @@ public: uint32_t _index; }; -Error BaseRAPass::buildViews() noexcept { +Error BaseRAPass::buildCFGViews() noexcept { #ifndef ASMJIT_NO_LOGGING - Logger* logger = debugLogger(); - ASMJIT_RA_LOG_FORMAT("[RAPass::BuildViews]\n"); + Logger* logger = getLoggerIf(DiagnosticOptions::kRADebugCFG); + ASMJIT_RA_LOG_FORMAT("[BuildCFGViews]\n"); #endif uint32_t count = blockCount(); @@ -462,11 +428,10 @@ Error BaseRAPass::buildViews() noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - CFG - Dominators] -// ============================================================================ +// BaseRAPass - CFG - Dominators +// ============================= -static ASMJIT_INLINE RABlock* intersectBlocks(RABlock* b1, RABlock* b2) noexcept { +static ASMJIT_FORCE_INLINE RABlock* intersectBlocks(RABlock* b1, RABlock* b2) noexcept { while (b1 != b2) { while (b2->povOrder() > b1->povOrder()) b1 = b1->iDom(); while (b1->povOrder() > b2->povOrder()) b2 = b2->iDom(); @@ -475,10 +440,10 @@ static ASMJIT_INLINE RABlock* intersectBlocks(RABlock* b1, RABlock* b2) noexcept } // Based on "A Simple, Fast Dominance Algorithm". -Error BaseRAPass::buildDominators() noexcept { +Error BaseRAPass::buildCFGDominators() noexcept { #ifndef ASMJIT_NO_LOGGING - Logger* logger = debugLogger(); - ASMJIT_RA_LOG_FORMAT("[RAPass::BuildDominators]\n"); + Logger* logger = getLoggerIf(DiagnosticOptions::kRADebugCFG); + ASMJIT_RA_LOG_FORMAT("[BuildCFGDominators]\n"); #endif if (_blocks.empty()) @@ -576,11 +541,10 @@ const RABlock* BaseRAPass::_nearestCommonDominator(const RABlock* a, const RABlo return entryBlock; } -// ============================================================================ -// [asmjit::BaseRAPass - CFG - Utilities] -// ============================================================================ +// BaseRAPass - CFG - Utilities +// ============================ -Error BaseRAPass::removeUnreachableBlocks() noexcept { +Error BaseRAPass::removeUnreachableCode() noexcept { uint32_t numAllBlocks = blockCount(); uint32_t numReachableBlocks = reachableBlockCount(); @@ -589,8 +553,9 @@ Error BaseRAPass::removeUnreachableBlocks() noexcept { return kErrorOk; #ifndef ASMJIT_NO_LOGGING - Logger* logger = debugLogger(); - ASMJIT_RA_LOG_FORMAT("[RAPass::RemoveUnreachableBlocks (%u of %u unreachable)]\n", numAllBlocks - numReachableBlocks, numAllBlocks); + StringTmp<256> sb; + Logger* logger = getLoggerIf(DiagnosticOptions::kRADebugUnreachable); + ASMJIT_RA_LOG_FORMAT("[RemoveUnreachableCode - detected %u of %u unreachable blocks]\n", numAllBlocks - numReachableBlocks, numAllBlocks); #endif for (uint32_t i = 0; i < numAllBlocks; i++) { @@ -598,7 +563,7 @@ Error BaseRAPass::removeUnreachableBlocks() noexcept { if (block->isReachable()) continue; - ASMJIT_RA_LOG_FORMAT(" Removing block {%u}\n", i); + ASMJIT_RA_LOG_FORMAT(" Removing code from unreachable block {%u}\n", i); BaseNode* first = block->first(); BaseNode* last = block->last(); @@ -609,8 +574,16 @@ Error BaseRAPass::removeUnreachableBlocks() noexcept { while (node != afterLast) { BaseNode* next = node->next(); - if (node->isCode() || node->isRemovable()) + if (node->isCode() || node->isRemovable()) { +#ifndef ASMJIT_NO_LOGGING + if (logger) { + sb.clear(); + Formatter::formatNode(sb, _formatOptions, cc(), node); + logger->logf(" %s\n", sb.data()); + } +#endif cc()->removeNode(node); + } node = next; } @@ -647,16 +620,15 @@ bool BaseRAPass::isNextTo(BaseNode* node, BaseNode* target) noexcept { } } -// ============================================================================ -// [asmjit::BaseRAPass - ?] -// ============================================================================ +// BaseRAPass - Registers - VirtReg / WorkReg Mapping +// ================================================== Error BaseRAPass::_asWorkReg(VirtReg* vReg, RAWorkReg** out) noexcept { // Checked by `asWorkReg()` - must be true. ASMJIT_ASSERT(vReg->_workReg == nullptr); - uint32_t group = vReg->group(); - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); + RegGroup group = vReg->group(); + ASMJIT_ASSERT(group <= RegGroup::kMaxVirt); RAWorkRegs& wRegs = workRegs(); RAWorkRegs& wRegsByGroup = workRegs(group); @@ -712,22 +684,21 @@ RAAssignment::PhysToWorkMap* BaseRAPass::newPhysToWorkMap() noexcept { return map; } -// ============================================================================ -// [asmjit::BaseRAPass - Registers - Liveness Analysis and Statistics] -// ============================================================================ +// BaseRAPass - Registers - Liveness Analysis and Statistics +// ========================================================= namespace LiveOps { typedef ZoneBitVector::BitWord BitWord; struct In { - static ASMJIT_INLINE BitWord op(BitWord dst, BitWord out, BitWord gen, BitWord kill) noexcept { + static ASMJIT_FORCE_INLINE BitWord op(BitWord dst, BitWord out, BitWord gen, BitWord kill) noexcept { DebugUtils::unused(dst); return (out | gen) & ~kill; } }; template<typename Operator> - static ASMJIT_INLINE bool op(BitWord* dst, const BitWord* a, uint32_t n) noexcept { + static ASMJIT_FORCE_INLINE bool op(BitWord* dst, const BitWord* a, uint32_t n) noexcept { BitWord changed = 0; for (uint32_t i = 0; i < n; i++) { @@ -742,7 +713,7 @@ namespace LiveOps { } template<typename Operator> - static ASMJIT_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, uint32_t n) noexcept { + static ASMJIT_FORCE_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, uint32_t n) noexcept { BitWord changed = 0; for (uint32_t i = 0; i < n; i++) { @@ -757,7 +728,7 @@ namespace LiveOps { } template<typename Operator> - static ASMJIT_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, const BitWord* c, uint32_t n) noexcept { + static ASMJIT_FORCE_INLINE bool op(BitWord* dst, const BitWord* a, const BitWord* b, const BitWord* c, uint32_t n) noexcept { BitWord changed = 0; for (uint32_t i = 0; i < n; i++) { @@ -771,7 +742,7 @@ namespace LiveOps { return changed != 0; } - static ASMJIT_INLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { + static ASMJIT_FORCE_INLINE bool recalcInOut(RABlock* block, uint32_t numBitWords, bool initial = false) noexcept { bool changed = initial; const RABlocks& successors = block->successors(); @@ -791,11 +762,11 @@ namespace LiveOps { ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { #ifndef ASMJIT_NO_LOGGING - Logger* logger = debugLogger(); + Logger* logger = getLoggerIf(DiagnosticOptions::kRADebugLiveness); StringTmp<512> sb; #endif - ASMJIT_RA_LOG_FORMAT("[RAPass::BuildLiveness]\n"); + ASMJIT_RA_LOG_FORMAT("[BuildLiveness]\n"); uint32_t i; @@ -819,9 +790,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { ASMJIT_PROPAGATE(nOutsPerWorkReg.resize(allocator(), numWorkRegs)); ASMJIT_PROPAGATE(nInstsPerBlock.resize(allocator(), numAllBlocks)); - // -------------------------------------------------------------------------- - // Calculate GEN/KILL of each block. - // -------------------------------------------------------------------------- + // Calculate GEN/KILL of Each Block + // -------------------------------- for (i = 0; i < numReachableBlocks; i++) { RABlock* block = _pov[i]; @@ -852,9 +822,9 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { // KILL - if this VirtReg is killed afterwards. // LAST - if this VirtReg is last in this basic block. if (block->kill().bitAt(workId)) - tiedReg->addFlags(RATiedReg::kKill); + tiedReg->addFlags(RATiedFlags::kKill); else if (!block->gen().bitAt(workId)) - tiedReg->addFlags(RATiedReg::kLast); + tiedReg->addFlags(RATiedFlags::kLast); if (tiedReg->isWriteOnly()) { // KILL. @@ -865,6 +835,16 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { block->kill().setBit(workId, false); block->gen().setBit(workId, true); } + + if (tiedReg->isLeadConsecutive()) { + RAWorkReg* workReg = workRegById(workId); + workReg->markLeadConsecutive(); + } + + if (tiedReg->hasConsecutiveParent()) { + RAWorkReg* consecutiveParentReg = workRegById(tiedReg->consecutiveParent()); + consecutiveParentReg->addImmediateConsecutive(allocator(), workId); + } } nInsts++; @@ -880,9 +860,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { nInstsPerBlock[block->blockId()] = nInsts; } - // -------------------------------------------------------------------------- - // Calculate IN/OUT of each block. - // -------------------------------------------------------------------------- + // Calculate IN/OUT of Each Block + // ------------------------------ { ZoneStack<RABlock*> workList; @@ -933,9 +912,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { } }); - // -------------------------------------------------------------------------- - // Reserve the space in each `RAWorkReg` for references. - // -------------------------------------------------------------------------- + // Reserve the space in each `RAWorkReg` for references + // ---------------------------------------------------- for (i = 0; i < numWorkRegs; i++) { RAWorkReg* workReg = workRegById(i); @@ -943,9 +921,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { ASMJIT_PROPAGATE(workReg->_writes.reserve(allocator(), nOutsPerWorkReg[i])); } - // -------------------------------------------------------------------------- - // Assign block and instruction positions, build LiveCount and LiveSpans. - // -------------------------------------------------------------------------- + // Assign block and instruction positions, build LiveCount and LiveSpans + // --------------------------------------------------------------------- uint32_t position = 2; for (i = 0; i < numAllBlocks; i++) { @@ -993,17 +970,17 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { if (tiedReg->isWrite()) workReg->_writes.appendUnsafe(node); - // We couldn't calculate this in previous steps, but since we know all LIVE-OUT - // at this point it becomes trivial. If this is the last instruction that uses - // this `workReg` and it's not LIVE-OUT then it is KILLed here. + // We couldn't calculate this in previous steps, but since we know all LIVE-OUT at this point it becomes + // trivial. If this is the last instruction that uses this `workReg` and it's not LIVE-OUT then it is + // KILLed here. if (tiedReg->isLast() && !block->liveOut().bitAt(workId)) - tiedReg->addFlags(RATiedReg::kKill); + tiedReg->addFlags(RATiedFlags::kKill); LiveRegSpans& liveSpans = workReg->liveSpans(); bool wasOpen; ASMJIT_PROPAGATE(liveSpans.openAt(allocator(), position + !tiedReg->isRead(), endPosition, wasOpen)); - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); if (!wasOpen) { curLiveCount[group]++; raInst->_liveCount[group]++; @@ -1014,16 +991,30 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { curLiveCount[group]--; } - // Update `RAWorkReg::hintRegId`. - if (tiedReg->hasUseId() && !workReg->hasHintRegId()) { + // Update `RAWorkReg::useIdMask` and `RAWorkReg::hintRegId`. + if (tiedReg->hasUseId()) { uint32_t useId = tiedReg->useId(); - if (!(raInst->_clobberedRegs[group] & Support::bitMask(useId))) + workReg->addUseIdMask(Support::bitMask(useId)); + if (!workReg->hasHintRegId() && !Support::bitTest(raInst->_clobberedRegs[group], useId)) workReg->setHintRegId(useId); } + if (tiedReg->useRegMask()) { + workReg->restrictPreferredMask(tiedReg->useRegMask()); + if (workReg->isLeadConsecutive()) + workReg->restrictConsecutiveMask(tiedReg->useRegMask()); + } + + if (tiedReg->outRegMask()) { + workReg->restrictPreferredMask(tiedReg->outRegMask()); + if (workReg->isLeadConsecutive()) + workReg->restrictConsecutiveMask(tiedReg->outRegMask()); + } + // Update `RAWorkReg::clobberedSurvivalMask`. - if (raInst->_clobberedRegs[group] && !tiedReg->isOutOrKill()) + if (raInst->_clobberedRegs[group] && !tiedReg->isOutOrKill()) { workReg->addClobberSurvivalMask(raInst->_clobberedRegs[group]); + } } position += 2; @@ -1042,9 +1033,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { ASMJIT_ASSERT(position == block->endPosition()); } - // -------------------------------------------------------------------------- - // Calculate WorkReg statistics. - // -------------------------------------------------------------------------- + // Calculate WorkReg statistics + // ---------------------------- for (i = 0; i < numWorkRegs; i++) { RAWorkReg* workReg = _workRegs[i]; @@ -1079,7 +1069,11 @@ Error BaseRAPass::assignArgIndexToWorkRegs() noexcept { for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { // Unassigned argument. - VirtReg* virtReg = func()->argPack(argIndex)[valueIndex]; + const RegOnly& regArg = func()->argPack(argIndex)[valueIndex]; + if (!regArg.isReg() || !cc()->isVirtIdValid(regArg.id())) + continue; + + VirtReg* virtReg = cc()->virtRegById(regArg.id()); if (!virtReg) continue; @@ -1105,9 +1099,8 @@ Error BaseRAPass::assignArgIndexToWorkRegs() noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - Allocation - Global] -// ============================================================================ +// BaseRAPass - Allocation - Global +// ================================ #ifndef ASMJIT_NO_LOGGING static void RAPass_dumpSpans(String& sb, uint32_t index, const LiveRegSpans& liveSpans) noexcept { @@ -1126,7 +1119,7 @@ static void RAPass_dumpSpans(String& sb, uint32_t index, const LiveRegSpans& liv Error BaseRAPass::runGlobalAllocator() noexcept { ASMJIT_PROPAGATE(initGlobalLiveSpans()); - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { ASMJIT_PROPAGATE(binPack(group)); } @@ -1134,7 +1127,7 @@ Error BaseRAPass::runGlobalAllocator() noexcept { } ASMJIT_FAVOR_SPEED Error BaseRAPass::initGlobalLiveSpans() noexcept { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { size_t physCount = _physRegCount[group]; LiveRegSpans* liveSpans = nullptr; @@ -1153,24 +1146,31 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::initGlobalLiveSpans() noexcept { return kErrorOk; } -ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(uint32_t group) noexcept { +struct RAConsecutiveReg { + RAWorkReg* workReg; + RAWorkReg* parentReg; +}; + +ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(RegGroup group) noexcept { if (workRegCount(group) == 0) return kErrorOk; #ifndef ASMJIT_NO_LOGGING - Logger* logger = debugLogger(); + Logger* logger = getLoggerIf(DiagnosticOptions::kRADebugAssignment); StringTmp<512> sb; - ASMJIT_RA_LOG_FORMAT("[RAPass::BinPack] Available=%u (0x%08X) Count=%u\n", + ASMJIT_RA_LOG_FORMAT("[BinPack] Available=%u (0x%08X) Count=%u RegGroup=%u\n", Support::popcnt(_availableRegs[group]), _availableRegs[group], - workRegCount(group)); + workRegCount(group), + uint32_t(group)); #endif uint32_t i; uint32_t physCount = _physRegCount[group]; RAWorkRegs workRegs; + ZoneVector<RAConsecutiveReg> consecutiveRegs; LiveRegSpans tmpSpans; ASMJIT_PROPAGATE(workRegs.concat(allocator(), this->workRegs(group))); @@ -1179,28 +1179,35 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(uint32_t group) noexcept { }); uint32_t numWorkRegs = workRegs.size(); - uint32_t availableRegs = _availableRegs[group]; + RegMask availableRegs = _availableRegs[group]; - // First try to pack everything that provides register-id hint as these are - // most likely function arguments and fixed (precolored) virtual registers. + // First try to pack everything that provides register-id hint as these are most likely function arguments and fixed + // (precolored) virtual registers. if (!workRegs.empty()) { uint32_t dstIndex = 0; for (i = 0; i < numWorkRegs; i++) { RAWorkReg* workReg = workRegs[i]; + + if (workReg->isLeadConsecutive()) { + ASMJIT_PROPAGATE(consecutiveRegs.append(allocator(), RAConsecutiveReg{workReg, nullptr})); + workReg->markProcessedConsecutive(); + } + if (workReg->hasHintRegId()) { uint32_t physId = workReg->hintRegId(); - if (availableRegs & Support::bitMask(physId)) { + if (Support::bitTest(availableRegs, physId)) { LiveRegSpans& live = _globalLiveSpans[group][physId]; Error err = tmpSpans.nonOverlappingUnionOf(allocator(), live, workReg->liveSpans(), LiveRegData(workReg->virtId())); if (err == kErrorOk) { - workReg->setHomeRegId(physId); live.swap(tmpSpans); + workReg->setHomeRegId(physId); + workReg->markAllocated(); continue; } - if (ASMJIT_UNLIKELY(err != 0xFFFFFFFFu)) + if (err != 0xFFFFFFFFu) return err; } } @@ -1212,18 +1219,108 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(uint32_t group) noexcept { numWorkRegs = dstIndex; } + // Allocate consecutive registers - both leads and all consecutives. This is important and prioritized over the rest, + // because once a lead is allocated we really need to allocate its consecutives, otherwise we may bin pack other + // registers into their places, which would result in wrong hints to the local allocator, and then into many moves + // or spills. + if (!consecutiveRegs.empty()) { + // This loop appends all other consecutive registers into `consecutiveRegs` array. Leads are at the beginning, + // non-leads follow. + i = 0; + for (;;) { + uint32_t stop = consecutiveRegs.size(); + if (i == stop) + break; + + while (i < stop) { + RAWorkReg* workReg = consecutiveRegs[i].workReg; + if (workReg->hasImmediateConsecutives()) { + ZoneBitVector::ForEachBitSet it(workReg->immediateConsecutives()); + while (it.hasNext()) { + uint32_t consecutiveWorkId = uint32_t(it.next()); + RAWorkReg* consecutiveReg = workRegById(consecutiveWorkId); + if (!consecutiveReg->isProcessedConsecutive()) { + ASMJIT_PROPAGATE(consecutiveRegs.append(allocator(), RAConsecutiveReg{consecutiveReg, workReg})); + consecutiveReg->markProcessedConsecutive(); + } + } + } + i++; + } + } + + uint32_t numConsecutiveRegs = consecutiveRegs.size(); + for (i = 0; i < numConsecutiveRegs; i++) { + RAWorkReg* workReg = consecutiveRegs[i].workReg; + if (workReg->isAllocated()) + continue; + + RAWorkReg* parentReg = consecutiveRegs[i].parentReg; + RegMask physRegs = 0; + + if (!parentReg) { + physRegs = availableRegs & workReg->preferredMask(); + if (!physRegs) { + physRegs = availableRegs & workReg->consecutiveMask(); + + // NOTE: This should never be true as it would mean we would never allocate this virtual register + // (not here, and not later when local register allocator processes RATiedReg sets). + if (ASMJIT_UNLIKELY(!physRegs)) + return DebugUtils::errored(kErrorConsecutiveRegsAllocation); + } + } + else if (parentReg->hasHomeRegId()) { + uint32_t consecutiveId = parentReg->homeRegId() + 1; + + // NOTE: We don't support wrapping. If this goes beyond all allocable registers there is something wrong. + if (consecutiveId > 31 || !Support::bitTest(availableRegs, consecutiveId)) + return DebugUtils::errored(kErrorConsecutiveRegsAllocation); + + workReg->setHintRegId(consecutiveId); + physRegs = Support::bitMask(consecutiveId); + } + + while (physRegs) { + uint32_t physId = Support::bitSizeOf<RegMask>() - 1 - Support::clz(physRegs); + + LiveRegSpans& live = _globalLiveSpans[group][physId]; + Error err = tmpSpans.nonOverlappingUnionOf(allocator(), live, workReg->liveSpans(), LiveRegData(workReg->virtId())); + + if (err == kErrorOk) { + workReg->setHomeRegId(physId); + workReg->markAllocated(); + live.swap(tmpSpans); + break; + } + + if (ASMJIT_UNLIKELY(err != 0xFFFFFFFFu)) + return err; + + physRegs ^= Support::bitMask(physId); + } + } + } + // Try to pack the rest. if (!workRegs.empty()) { uint32_t dstIndex = 0; for (i = 0; i < numWorkRegs; i++) { RAWorkReg* workReg = workRegs[i]; - uint32_t physRegs = availableRegs; + + if (workReg->isAllocated()) + continue; + + RegMask physRegs = availableRegs; + if (physRegs & workReg->preferredMask()) + physRegs &= workReg->preferredMask(); while (physRegs) { - uint32_t physId = Support::ctz(physRegs); + RegMask preferredMask = physRegs; + uint32_t physId = Support::ctz(preferredMask); + if (workReg->clobberSurvivalMask()) { - uint32_t preferredMask = physRegs & workReg->clobberSurvivalMask(); + preferredMask &= workReg->clobberSurvivalMask(); if (preferredMask) physId = Support::ctz(preferredMask); } @@ -1233,6 +1330,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(uint32_t group) noexcept { if (err == kErrorOk) { workReg->setHomeRegId(physId); + workReg->markAllocated(); live.swap(tmpSpans); break; } @@ -1271,7 +1369,7 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(uint32_t group) noexcept { ASMJIT_RA_LOG_FORMAT(" Completed.\n"); } else { - _strategy[group].setType(RAStrategy::kStrategyComplex); + _strategy[group].setType(RAStrategyType::kComplex); for (RAWorkReg* workReg : workRegs) workReg->markStackPreferred(); @@ -1292,9 +1390,8 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::binPack(uint32_t group) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - Allocation - Local] -// ============================================================================ +// BaseRAPass - Allocation - Local +// =============================== Error BaseRAPass::runLocalAllocator() noexcept { RALocalAllocator lra(this); @@ -1317,9 +1414,8 @@ Error BaseRAPass::runLocalAllocator() noexcept { lra.makeInitialAssignment(); ASMJIT_PROPAGATE(setBlockEntryAssignment(block, block, lra._curAssignment)); - // The loop starts from the first block and iterates blocks in order, however, - // the algorithm also allows to jump to any other block when finished if it's - // a jump target. In-order iteration just makes sure that all blocks are visited. + // The loop starts from the first block and iterates blocks in order, however, the algorithm also allows to jump to + // any other block when finished if it's a jump target. In-order iteration just makes sure that all blocks are visited. for (;;) { BaseNode* first = block->first(); BaseNode* last = block->last(); @@ -1365,7 +1461,7 @@ Error BaseRAPass::runLocalAllocator() noexcept { } ASMJIT_PROPAGATE(lra.allocInst(inst)); - if (inst->type() == BaseNode::kNodeInvoke) + if (inst->type() == NodeType::kInvoke) ASMJIT_PROPAGATE(emitPreCall(inst->as<InvokeNode>())); else ASMJIT_PROPAGATE(lra.spillAfterAllocation(inst)); @@ -1432,9 +1528,8 @@ Error BaseRAPass::setBlockEntryAssignment(RABlock* block, const RABlock* fromBlo if (block->hasSharedAssignmentId()) { uint32_t sharedAssignmentId = block->sharedAssignmentId(); - // Shouldn't happen. Entry assignment of a block that has a shared-state - // will assign to all blocks with the same sharedAssignmentId. It's a bug if - // the shared state has been already assigned. + // Shouldn't happen. Entry assignment of a block that has a shared-state will assign to all blocks + // with the same sharedAssignmentId. It's a bug if the shared state has been already assigned. if (!_sharedAssignments[sharedAssignmentId].empty()) return DebugUtils::errored(kErrorInvalidState); @@ -1473,7 +1568,7 @@ Error BaseRAPass::setBlockEntryAssignment(RABlock* block, const RABlock* fromBlo uint32_t workId = uint32_t(it.next()); RAWorkReg* workReg = workRegById(workId); - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); uint32_t physId = as.workToPhysId(group, workId); if (physId != RAAssignment::kPhysNone) @@ -1500,7 +1595,7 @@ Error BaseRAPass::setSharedAssignment(uint32_t sharedAssignmentId, const RAAssig RAAssignment as; as.initLayout(_physRegCount, workRegs()); - uint32_t sharedAssigned[BaseReg::kGroupVirt] {}; + Support::Array<uint32_t, Globals::kNumVirtGroups> sharedAssigned {}; for (RABlock* block : blocks()) { if (block->sharedAssignmentId() == sharedAssignmentId) { @@ -1518,9 +1613,9 @@ Error BaseRAPass::setSharedAssignment(uint32_t sharedAssignmentId, const RAAssig const ZoneBitVector& liveIn = block->liveIn(); sharedLiveIn.or_(liveIn); - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { sharedAssigned[group] |= entryPhysToWorkMap->assigned[group]; - Support::BitWordIterator<uint32_t> it(entryPhysToWorkMap->assigned[group]); + Support::BitWordIterator<RegMask> it(entryPhysToWorkMap->assigned[group]); while (it.hasNext()) { uint32_t physId = it.next(); @@ -1536,8 +1631,8 @@ Error BaseRAPass::setSharedAssignment(uint32_t sharedAssignmentId, const RAAssig { as.initMaps(physToWorkMap, workToPhysMap); - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - Support::BitWordIterator<uint32_t> it(_availableRegs[group] & ~sharedAssigned[group]); + for (RegGroup group : RegGroupVirtValues{}) { + Support::BitWordIterator<RegMask> it(_availableRegs[group] & ~sharedAssigned[group]); while (it.hasNext()) { uint32_t physId = it.next(); @@ -1553,13 +1648,12 @@ Error BaseRAPass::setSharedAssignment(uint32_t sharedAssignmentId, const RAAssig } Error BaseRAPass::blockEntryAssigned(const RAAssignment& as) noexcept { - // Complex allocation strategy requires to record register assignments upon - // block entry (or per shared state). - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + // Complex allocation strategy requires to record register assignments upon block entry (or per shared state). + for (RegGroup group : RegGroupVirtValues{}) { if (!_strategy[group].isComplex()) continue; - Support::BitWordIterator<uint32_t> it(as.assigned(group)); + Support::BitWordIterator<RegMask> it(as.assigned(group)); while (it.hasNext()) { uint32_t physId = it.next(); uint32_t workId = as.physToWorkId(group, physId); @@ -1572,9 +1666,8 @@ Error BaseRAPass::blockEntryAssigned(const RAAssignment& as) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - Allocation - Utilities] -// ============================================================================ +// BaseRAPass - Allocation - Utilities +// =================================== Error BaseRAPass::useTemporaryMem(BaseMem& out, uint32_t size, uint32_t alignment) noexcept { ASMJIT_ASSERT(alignment <= 64); @@ -1596,22 +1689,19 @@ Error BaseRAPass::useTemporaryMem(BaseMem& out, uint32_t size, uint32_t alignmen return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - Allocation - Prolog / Epilog] -// ============================================================================ +// BaseRAPass - Allocation - Prolog & Epilog +// ========================================= Error BaseRAPass::updateStackFrame() noexcept { - // Update some StackFrame information that we updated during allocation. The - // only information we don't have at the moment is final local stack size, - // which is calculated last. + // Update some StackFrame information that we updated during allocation. The only information we don't have at the + // moment is final local stack size, which is calculated last. FuncFrame& frame = func()->frame(); - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) + for (RegGroup group : RegGroupVirtValues{}) frame.addDirtyRegs(group, _clobberedRegs[group]); frame.setLocalStackAlignment(_stackAllocator.alignment()); - // If there are stack arguments that are not assigned to registers upon entry - // and the function doesn't require dynamic stack alignment we keep these - // arguments where they are. This will also mark all stack slots that match + // If there are stack arguments that are not assigned to registers upon entry and the function doesn't require + // dynamic stack alignment we keep these arguments where they are. This will also mark all stack slots that match // these arguments as allocated. if (_numStackArgsToStackSlots) ASMJIT_PROPAGATE(_markStackArgsToKeep()); @@ -1620,8 +1710,8 @@ Error BaseRAPass::updateStackFrame() noexcept { ASMJIT_PROPAGATE(_stackAllocator.calculateStackFrame()); frame.setLocalStackSize(_stackAllocator.stackSize()); - // Update the stack frame based on `_argsAssignment` and finalize it. - // Finalization means to apply final calculation to the stack layout. + // Update the stack frame based on `_argsAssignment` and finalize it. Finalization means to apply final calculation + // to the stack layout. ASMJIT_PROPAGATE(_argsAssignment.updateFuncFrame(frame)); ASMJIT_PROPAGATE(frame.finalize()); @@ -1629,9 +1719,8 @@ Error BaseRAPass::updateStackFrame() noexcept { if (frame.localStackOffset() != 0) ASMJIT_PROPAGATE(_stackAllocator.adjustSlotOffsets(int32_t(frame.localStackOffset()))); - // Again, if there are stack arguments allocated in function's stack we have - // to handle them. This handles all cases (either regular or dynamic stack - // alignment). + // Again, if there are stack arguments allocated in function's stack we have to handle them. This handles all cases + // (either regular or dynamic stack alignment). if (_numStackArgsToStackSlots) ASMJIT_PROPAGATE(_updateStackArgs()); @@ -1647,28 +1736,26 @@ Error BaseRAPass::_markStackArgsToKeep() noexcept { for (uint32_t workId = 0; workId < numWorkRegs; workId++) { RAWorkReg* workReg = workRegs[workId]; - if (workReg->hasFlag(RAWorkReg::kFlagStackArgToStack)) { + if (workReg->hasFlag(RAWorkRegFlags::kStackArgToStack)) { ASMJIT_ASSERT(workReg->hasArgIndex()); const FuncValue& srcArg = _func->detail().arg(workReg->argIndex()); - // If the register doesn't have stack slot then we failed. It doesn't - // make much sense as it was marked as `kFlagStackArgToStack`, which - // requires the WorkReg was live-in upon function entry. + // If the register doesn't have stack slot then we failed. It doesn't make much sense as it was marked as + // `kFlagStackArgToStack`, which requires the WorkReg was live-in upon function entry. RAStackSlot* slot = workReg->stackSlot(); if (ASMJIT_UNLIKELY(!slot)) return DebugUtils::errored(kErrorInvalidState); if (hasSAReg && srcArg.isStack() && !srcArg.isIndirect()) { - uint32_t typeSize = Type::sizeOf(srcArg.typeId()); + uint32_t typeSize = TypeUtils::sizeOf(srcArg.typeId()); if (typeSize == slot->size()) { slot->addFlags(RAStackSlot::kFlagStackArg); continue; } } - // NOTE: Update StackOffset here so when `_argsAssignment.updateFuncFrame()` - // is called it will take into consideration moving to stack slots. Without - // this we may miss some scratch registers later. + // NOTE: Update StackOffset here so when `_argsAssignment.updateFuncFrame()` is called it will take into + // consideration moving to stack slots. Without this we may miss some scratch registers later. FuncValue& dstArg = _argsAssignment.arg(workReg->argIndex(), workReg->argValueIndex()); dstArg.assignStackOffset(0); } @@ -1684,7 +1771,7 @@ Error BaseRAPass::_updateStackArgs() noexcept { for (uint32_t workId = 0; workId < numWorkRegs; workId++) { RAWorkReg* workReg = workRegs[workId]; - if (workReg->hasFlag(RAWorkReg::kFlagStackArgToStack)) { + if (workReg->hasFlag(RAWorkRegFlags::kStackArgToStack)) { ASMJIT_ASSERT(workReg->hasArgIndex()); RAStackSlot* slot = workReg->stackSlot(); @@ -1724,25 +1811,18 @@ Error BaseRAPass::insertPrologEpilog() noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::BaseRAPass - Rewriter] -// ============================================================================ +// BaseRAPass - Rewriter +// ===================== Error BaseRAPass::rewrite() noexcept { -#ifndef ASMJIT_NO_LOGGING - Logger* logger = debugLogger(); - ASMJIT_RA_LOG_FORMAT("[RAPass::Rewrite]\n"); -#endif - return _rewrite(_func, _stop); } -// ============================================================================ -// [asmjit::BaseRAPass - Logging] -// ============================================================================ +// BaseRAPass - Logging +// ==================== #ifndef ASMJIT_NO_LOGGING -static void RAPass_dumpRAInst(BaseRAPass* pass, String& sb, const RAInst* raInst) noexcept { +static void RAPass_formatLiveness(BaseRAPass* pass, String& sb, const RAInst* raInst) noexcept { const RATiedReg* tiedRegs = raInst->tiedRegs(); uint32_t tiedCount = raInst->tiedCount(); @@ -1757,16 +1837,25 @@ static void RAPass_dumpRAInst(BaseRAPass* pass, String& sb, const RAInst* raInst tiedReg.isRead() ? 'R' : tiedReg.isWrite() ? 'W' : '?'); + if (tiedReg.isLeadConsecutive()) + sb.appendFormat("|Lead[%u]", tiedReg.consecutiveData() + 1u); + if (tiedReg.hasUseId()) sb.appendFormat("|Use=%u", tiedReg.useId()); else if (tiedReg.isUse()) sb.append("|Use"); + if (tiedReg.isUseConsecutive() && !tiedReg.isLeadConsecutive()) + sb.appendFormat("+%u", tiedReg.consecutiveData()); + if (tiedReg.hasOutId()) sb.appendFormat("|Out=%u", tiedReg.outId()); else if (tiedReg.isOut()) sb.append("|Out"); + if (tiedReg.isOutConsecutive() && !tiedReg.isLeadConsecutive()) + sb.appendFormat("+%u", tiedReg.consecutiveData()); + if (tiedReg.isLast()) sb.append("|Last"); @@ -1778,7 +1867,6 @@ static void RAPass_dumpRAInst(BaseRAPass* pass, String& sb, const RAInst* raInst } ASMJIT_FAVOR_SIZE Error BaseRAPass::annotateCode() noexcept { - uint32_t loggerFlags = _loggerFlags; StringTmp<1024> sb; for (const RABlock* block : _blocks) { @@ -1788,21 +1876,18 @@ ASMJIT_FAVOR_SIZE Error BaseRAPass::annotateCode() noexcept { BaseNode* last = block->last(); for (;;) { sb.clear(); - Formatter::formatNode(sb, loggerFlags, cc(), node); + Formatter::formatNode(sb, _formatOptions, cc(), node); - if ((loggerFlags & FormatOptions::kFlagDebugRA) != 0 && node->isInst() && node->hasPassData()) { + if (hasDiagnosticOption(DiagnosticOptions::kRADebugLiveness) && node->isInst() && node->hasPassData()) { const RAInst* raInst = node->passData<RAInst>(); if (raInst->tiedCount() > 0) { sb.padEnd(40); sb.append(" | "); - RAPass_dumpRAInst(this, sb, raInst); + RAPass_formatLiveness(this, sb, raInst); } } - node->setInlineComment( - static_cast<char*>( - cc()->_dataZone.dup(sb.data(), sb.size(), true))); - + node->setInlineComment(static_cast<char*>(cc()->_dataZone.dup(sb.data(), sb.size(), true))); if (node == last) break; node = node->next(); diff --git a/src/asmjit/core/rapass_p.h b/src/asmjit/core/rapass_p.h index 034ec07..098c5c9 100644 --- a/src/asmjit/core/rapass_p.h +++ b/src/asmjit/core/rapass_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RAPASS_P_H_INCLUDED #define ASMJIT_CORE_RAPASS_P_H_INCLUDED @@ -40,9 +22,34 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [asmjit::RABlock] -// ============================================================================ +//! Flags used by \ref RABlock. +enum class RABlockFlags : uint32_t { + //! No flags. + kNone = 0, + + //! Block has been constructed from nodes. + kIsConstructed = 0x00000001u, + //! Block is reachable (set by `buildCFGViews()`). + kIsReachable = 0x00000002u, + //! Block is a target (has an associated label or multiple labels). + kIsTargetable = 0x00000004u, + //! Block has been allocated. + kIsAllocated = 0x00000008u, + //! Block is a function-exit. + kIsFuncExit = 0x00000010u, + + //! Block has a terminator (jump, conditional jump, ret). + kHasTerminator = 0x00000100u, + //! Block naturally flows to the next block. + kHasConsecutive = 0x00000200u, + //! Block has a jump to a jump-table at the end. + kHasJumpTable = 0x00000400u, + //! Block contains fixed registers (precolored). + kHasFixedRegs = 0x00000800u, + //! Block contains function calls. + kHasFuncCalls = 0x00001000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(RABlockFlags) //! Basic block used by register allocator pass. class RABlock { @@ -52,42 +59,34 @@ public: typedef RAAssignment::PhysToWorkMap PhysToWorkMap; typedef RAAssignment::WorkToPhysMap WorkToPhysMap; - enum Id : uint32_t { + //! \name Constants + //! \{ + + enum : uint32_t { + //! Unassigned block id. kUnassignedId = 0xFFFFFFFFu }; - //! Basic block flags. - enum Flags : uint32_t { - //! Block has been constructed from nodes. - kFlagIsConstructed = 0x00000001u, - //! Block is reachable (set by `buildViews()`). - kFlagIsReachable = 0x00000002u, - //! Block is a target (has an associated label or multiple labels). - kFlagIsTargetable = 0x00000004u, - //! Block has been allocated. - kFlagIsAllocated = 0x00000008u, - //! Block is a function-exit. - kFlagIsFuncExit = 0x00000010u, - - //! Block has a terminator (jump, conditional jump, ret). - kFlagHasTerminator = 0x00000100u, - //! Block naturally flows to the next block. - kFlagHasConsecutive = 0x00000200u, - //! Block has a jump to a jump-table at the end. - kFlagHasJumpTable = 0x00000400u, - //! Block contains fixed registers (precolored). - kFlagHasFixedRegs = 0x00000800u, - //! Block contains function calls. - kFlagHasFuncCalls = 0x00001000u + enum LiveType : uint32_t { + kLiveIn = 0, + kLiveOut = 1, + kLiveGen = 2, + kLiveKill = 3, + kLiveCount = 4 }; + //! \} + + //! \name Members + //! \{ + //! Register allocator pass. BaseRAPass* _ra; //! Block id (indexed from zero). uint32_t _blockId = kUnassignedId; //! Block flags, see `Flags`. - uint32_t _flags = 0; + RABlockFlags _flags = RABlockFlags::kNone; //! First `BaseNode` of this block (inclusive). BaseNode* _first = nullptr; @@ -119,30 +118,24 @@ public: //! Block successors. RABlocks _successors {}; - enum LiveType : uint32_t { - kLiveIn = 0, - kLiveOut = 1, - kLiveGen = 2, - kLiveKill = 3, - kLiveCount = 4 - }; - //! Liveness in/out/use/kill. ZoneBitVector _liveBits[kLiveCount] {}; - //! Shared assignment it or `Globals::kInvalidId` if this block doesn't - //! have shared assignment. See `RASharedAssignment` for more details. + //! Shared assignment it or `Globals::kInvalidId` if this block doesn't have shared assignment. + //! See \ref RASharedAssignment for more details. uint32_t _sharedAssignmentId = Globals::kInvalidId; //! Scratch registers that cannot be allocated upon block entry. - uint32_t _entryScratchGpRegs = 0; + RegMask _entryScratchGpRegs = 0; //! Scratch registers used at exit, by a terminator instruction. - uint32_t _exitScratchGpRegs = 0; + RegMask _exitScratchGpRegs = 0; //! Register assignment (PhysToWork) on entry. PhysToWorkMap* _entryPhysToWorkMap = nullptr; //! Register assignment (WorkToPhys) on entry. WorkToPhysMap* _entryWorkToPhysMap = nullptr; + //! \} + //! \name Construction & Destruction //! \{ @@ -158,37 +151,43 @@ public: inline ZoneAllocator* allocator() const noexcept; inline uint32_t blockId() const noexcept { return _blockId; } - inline uint32_t flags() const noexcept { return _flags; } + inline RABlockFlags flags() const noexcept { return _flags; } - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } + inline bool hasFlag(RABlockFlags flag) const noexcept { return Support::test(_flags, flag); } + inline void addFlags(RABlockFlags flags) noexcept { _flags |= flags; } inline bool isAssigned() const noexcept { return _blockId != kUnassignedId; } - inline bool isConstructed() const noexcept { return hasFlag(kFlagIsConstructed); } - inline bool isReachable() const noexcept { return hasFlag(kFlagIsReachable); } - inline bool isTargetable() const noexcept { return hasFlag(kFlagIsTargetable); } - inline bool isAllocated() const noexcept { return hasFlag(kFlagIsAllocated); } - inline bool isFuncExit() const noexcept { return hasFlag(kFlagIsFuncExit); } + inline bool isConstructed() const noexcept { return hasFlag(RABlockFlags::kIsConstructed); } + inline bool isReachable() const noexcept { return hasFlag(RABlockFlags::kIsReachable); } + inline bool isTargetable() const noexcept { return hasFlag(RABlockFlags::kIsTargetable); } + inline bool isAllocated() const noexcept { return hasFlag(RABlockFlags::kIsAllocated); } + inline bool isFuncExit() const noexcept { return hasFlag(RABlockFlags::kIsFuncExit); } + inline bool hasTerminator() const noexcept { return hasFlag(RABlockFlags::kHasTerminator); } + inline bool hasConsecutive() const noexcept { return hasFlag(RABlockFlags::kHasConsecutive); } + inline bool hasJumpTable() const noexcept { return hasFlag(RABlockFlags::kHasJumpTable); } inline void makeConstructed(const RARegsStats& regStats) noexcept { - _flags |= kFlagIsConstructed; + _flags |= RABlockFlags::kIsConstructed; _regsStats.combineWith(regStats); } - inline void makeReachable() noexcept { _flags |= kFlagIsReachable; } - inline void makeTargetable() noexcept { _flags |= kFlagIsTargetable; } - inline void makeAllocated() noexcept { _flags |= kFlagIsAllocated; } + inline void makeReachable() noexcept { _flags |= RABlockFlags::kIsReachable; } + inline void makeTargetable() noexcept { _flags |= RABlockFlags::kIsTargetable; } + inline void makeAllocated() noexcept { _flags |= RABlockFlags::kIsAllocated; } inline const RARegsStats& regsStats() const noexcept { return _regsStats; } - inline bool hasTerminator() const noexcept { return hasFlag(kFlagHasTerminator); } - inline bool hasConsecutive() const noexcept { return hasFlag(kFlagHasConsecutive); } - inline bool hasJumpTable() const noexcept { return hasFlag(kFlagHasJumpTable); } - inline bool hasPredecessors() const noexcept { return !_predecessors.empty(); } inline bool hasSuccessors() const noexcept { return !_successors.empty(); } + inline bool hasSuccessor(RABlock* block) noexcept { + if (block->_predecessors.size() < _successors.size()) + return block->_predecessors.contains(this); + else + return _successors.contains(block); + } + inline const RABlocks& predecessors() const noexcept { return _predecessors; } inline const RABlocks& successors() const noexcept { return _successors; } @@ -206,11 +205,11 @@ public: inline uint32_t povOrder() const noexcept { return _povOrder; } - inline uint32_t entryScratchGpRegs() const noexcept; - inline uint32_t exitScratchGpRegs() const noexcept { return _exitScratchGpRegs; } + inline RegMask entryScratchGpRegs() const noexcept; + inline RegMask exitScratchGpRegs() const noexcept { return _exitScratchGpRegs; } - inline void addEntryScratchGpRegs(uint32_t regMask) noexcept { _entryScratchGpRegs |= regMask; } - inline void addExitScratchGpRegs(uint32_t regMask) noexcept { _exitScratchGpRegs |= regMask; } + inline void addEntryScratchGpRegs(RegMask regMask) noexcept { _entryScratchGpRegs |= regMask; } + inline void addExitScratchGpRegs(RegMask regMask) noexcept { _exitScratchGpRegs |= regMask; } inline bool hasSharedAssignmentId() const noexcept { return _sharedAssignmentId != Globals::kInvalidId; } inline uint32_t sharedAssignmentId() const noexcept { return _sharedAssignmentId; } @@ -261,11 +260,9 @@ public: //! \name Utilities //! \{ - //! Adds a successor to this block, and predecessor to `successor`, making - //! connection on both sides. + //! Adds a successor to this block, and predecessor to `successor`, making connection on both sides. //! - //! This API must be used to manage successors and predecessors, never manage - //! it manually. + //! This API must be used to manage successors and predecessors, never manage it manually. Error appendSuccessor(RABlock* successor) noexcept; //! Similar to `appendSuccessor()`, but does prepend instead append. @@ -276,19 +273,18 @@ public: //! \} }; -// ============================================================================ -// [asmjit::RAInst] -// ============================================================================ - //! Register allocator's data associated with each `InstNode`. class RAInst { public: ASMJIT_NONCOPYABLE(RAInst) + //! \name Members + //! \{ + //! Parent block. RABlock* _block; - //! Instruction flags. - uint32_t _flags; + //! Aggregated RATiedFlags from all operands & instruction specific flags. + RATiedFlags _flags; //! Total count of RATiedReg's. uint32_t _tiedTotal; //! Index of RATiedReg's per register group. @@ -304,14 +300,12 @@ public: //! Tied registers. RATiedReg _tiedRegs[1]; - enum Flags : uint32_t { - kFlagIsTransformable = 0x80000000u - }; + //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE RAInst(RABlock* block, uint32_t flags, uint32_t tiedTotal, const RARegMask& clobberedRegs) noexcept { + inline RAInst(RABlock* block, RATiedFlags flags, uint32_t tiedTotal, const RARegMask& clobberedRegs) noexcept { _block = block; _flags = flags; _tiedTotal = tiedTotal; @@ -328,18 +322,18 @@ public: //! \{ //! Returns the instruction flags. - inline uint32_t flags() const noexcept { return _flags; } + inline RATiedFlags flags() const noexcept { return _flags; } //! Tests whether the instruction has flag `flag`. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } + inline bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); } //! Replaces the existing instruction flags with `flags`. - inline void setFlags(uint32_t flags) noexcept { _flags = flags; } + inline void setFlags(RATiedFlags flags) noexcept { _flags = flags; } //! Adds instruction `flags` to this RAInst. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } + inline void addFlags(RATiedFlags flags) noexcept { _flags |= flags; } //! Clears instruction `flags` from this RAInst. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } + inline void clearFlags(RATiedFlags flags) noexcept { _flags &= ~flags; } //! Tests whether this instruction can be transformed to another instruction if necessary. - inline bool isTransformable() const noexcept { return hasFlag(kFlagIsTransformable); } + inline bool isTransformable() const noexcept { return hasFlag(RATiedFlags::kInst_IsTransformable); } //! Returns the associated block with this RAInst. inline RABlock* block() const noexcept { return _block; } @@ -347,12 +341,12 @@ public: //! Returns tied registers (all). inline RATiedReg* tiedRegs() const noexcept { return const_cast<RATiedReg*>(_tiedRegs); } //! Returns tied registers for a given `group`. - inline RATiedReg* tiedRegs(uint32_t group) const noexcept { return const_cast<RATiedReg*>(_tiedRegs) + _tiedIndex.get(group); } + inline RATiedReg* tiedRegs(RegGroup group) const noexcept { return const_cast<RATiedReg*>(_tiedRegs) + _tiedIndex.get(group); } //! Returns count of all tied registers. inline uint32_t tiedCount() const noexcept { return _tiedTotal; } //! Returns count of tied registers of a given `group`. - inline uint32_t tiedCount(uint32_t group) const noexcept { return _tiedCount[group]; } + inline uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount[group]; } //! Returns `RATiedReg` at the given `index`. inline RATiedReg* tiedAt(uint32_t index) const noexcept { @@ -361,8 +355,8 @@ public: } //! Returns `RATiedReg` at the given `index` of the given register `group`. - inline RATiedReg* tiedOf(uint32_t group, uint32_t index) const noexcept { - ASMJIT_ASSERT(index < _tiedCount._regs[group]); + inline RATiedReg* tiedOf(RegGroup group, uint32_t index) const noexcept { + ASMJIT_ASSERT(index < _tiedCount.get(group)); return tiedRegs(group) + index; } @@ -381,20 +375,18 @@ public: //! \} }; -// ============================================================================ -// [asmjit::RAInstBuilder] -// ============================================================================ - -//! A helper class that is used to build an array of RATiedReg items that are -//! then copied to `RAInst`. +//! A helper class that is used to build an array of RATiedReg items that are then copied to `RAInst`. class RAInstBuilder { public: ASMJIT_NONCOPYABLE(RAInstBuilder) + //! \name Members + //! \{ + //! Flags combined from all RATiedReg's. - uint32_t _aggregatedFlags; + RATiedFlags _aggregatedFlags; //! Flags that will be cleared before storing the aggregated flags to `RAInst`. - uint32_t _forbiddenFlags; + RATiedFlags _forbiddenFlags; RARegCount _count; RARegsStats _stats; @@ -406,6 +398,8 @@ public: //! Array of temporary tied registers. RATiedReg _tiedRegs[128]; + //! \} + //! \name Construction & Destruction //! \{ @@ -413,8 +407,8 @@ public: inline void init() noexcept { reset(); } inline void reset() noexcept { - _aggregatedFlags = 0; - _forbiddenFlags = 0; + _aggregatedFlags = RATiedFlags::kNone; + _forbiddenFlags = RATiedFlags::kNone; _count.reset(); _stats.reset(); _used.reset(); @@ -427,11 +421,11 @@ public: //! \name Accessors //! \{ - inline uint32_t aggregatedFlags() const noexcept { return _aggregatedFlags; } - inline uint32_t forbiddenFlags() const noexcept { return _forbiddenFlags; } + inline RATiedFlags aggregatedFlags() const noexcept { return _aggregatedFlags; } + inline RATiedFlags forbiddenFlags() const noexcept { return _forbiddenFlags; } - inline void addAggregatedFlags(uint32_t flags) noexcept { _aggregatedFlags |= flags; } - inline void addForbiddenFlags(uint32_t flags) noexcept { _forbiddenFlags |= flags; } + inline void addAggregatedFlags(RATiedFlags flags) noexcept { _aggregatedFlags |= flags; } + inline void addForbiddenFlags(RATiedFlags flags) noexcept { _forbiddenFlags |= flags; } //! Returns the number of tied registers added to the builder. inline uint32_t tiedRegCount() const noexcept { return uint32_t((size_t)(_cur - _tiedRegs)); } @@ -459,19 +453,26 @@ public: //! \name Utilities //! \{ - Error add(RAWorkReg* workReg, uint32_t flags, uint32_t allocable, uint32_t useId, uint32_t useRewriteMask, uint32_t outId, uint32_t outRewriteMask, uint32_t rmSize = 0) noexcept { - uint32_t group = workReg->group(); + Error add( + RAWorkReg* workReg, + RATiedFlags flags, + RegMask useRegMask, uint32_t useId, uint32_t useRewriteMask, + RegMask outRegMask, uint32_t outId, uint32_t outRewriteMask, + uint32_t rmSize = 0, + uint32_t consecutiveParent = Globals::kInvalidId) noexcept { + + RegGroup group = workReg->group(); RATiedReg* tiedReg = workReg->tiedReg(); if (useId != BaseReg::kIdBad) { _stats.makeFixed(group); _used[group] |= Support::bitMask(useId); - flags |= RATiedReg::kUseFixed; + flags |= RATiedFlags::kUseFixed; } if (outId != BaseReg::kIdBad) { _clobbered[group] |= Support::bitMask(outId); - flags |= RATiedReg::kOutFixed; + flags |= RATiedFlags::kOutFixed; } _aggregatedFlags |= flags; @@ -482,13 +483,19 @@ public: ASMJIT_ASSERT(tiedRegCount() < ASMJIT_ARRAY_SIZE(_tiedRegs)); tiedReg = _cur++; - tiedReg->init(workReg->workId(), flags, allocable, useId, useRewriteMask, outId, outRewriteMask, rmSize); + tiedReg->init(workReg->workId(), flags, useRegMask, useId, useRewriteMask, outRegMask, outId, outRewriteMask, rmSize, consecutiveParent); workReg->setTiedReg(tiedReg); _count.add(group); return kErrorOk; } else { + if (consecutiveParent != tiedReg->consecutiveParent()) { + if (tiedReg->consecutiveParent() != Globals::kInvalidId) + return DebugUtils::errored(kErrorInvalidState); + tiedReg->_consecutiveParent = consecutiveParent; + } + if (useId != BaseReg::kIdBad) { if (ASMJIT_UNLIKELY(tiedReg->hasUseId())) return DebugUtils::errored(kErrorOverlappedRegs); @@ -503,8 +510,9 @@ public: tiedReg->addRefCount(); tiedReg->addFlags(flags); - tiedReg->_allocableRegs &= allocable; + tiedReg->_useRegMask &= useRegMask; tiedReg->_useRewriteMask |= useRewriteMask; + tiedReg->_outRegMask &= outRegMask; tiedReg->_outRewriteMask |= outRewriteMask; tiedReg->_rmSize = uint8_t(Support::max<uint32_t>(tiedReg->rmSize(), rmSize)); return kErrorOk; @@ -514,9 +522,9 @@ public: Error addCallArg(RAWorkReg* workReg, uint32_t useId) noexcept { ASMJIT_ASSERT(useId != BaseReg::kIdBad); - uint32_t flags = RATiedReg::kUse | RATiedReg::kRead | RATiedReg::kUseFixed; - uint32_t group = workReg->group(); - uint32_t allocable = Support::bitMask(useId); + RATiedFlags flags = RATiedFlags::kUse | RATiedFlags::kRead | RATiedFlags::kUseFixed; + RegGroup group = workReg->group(); + RegMask allocable = Support::bitMask(useId); _aggregatedFlags |= flags; _used[group] |= allocable; @@ -529,7 +537,7 @@ public: ASMJIT_ASSERT(tiedRegCount() < ASMJIT_ARRAY_SIZE(_tiedRegs)); tiedReg = _cur++; - tiedReg->init(workReg->workId(), flags, allocable, useId, 0, BaseReg::kIdBad, 0); + tiedReg->init(workReg->workId(), flags, allocable, useId, 0, allocable, BaseReg::kIdBad, 0); workReg->setTiedReg(tiedReg); _count.add(group); @@ -537,12 +545,12 @@ public: } else { if (tiedReg->hasUseId()) { - flags |= RATiedReg::kDuplicate; - tiedReg->_allocableRegs |= allocable; + flags |= RATiedFlags::kDuplicate; + tiedReg->_useRegMask |= allocable; } else { tiedReg->setUseId(useId); - tiedReg->_allocableRegs &= allocable; + tiedReg->_useRegMask &= allocable; } tiedReg->addRefCount(); @@ -554,12 +562,12 @@ public: Error addCallRet(RAWorkReg* workReg, uint32_t outId) noexcept { ASMJIT_ASSERT(outId != BaseReg::kIdBad); - uint32_t flags = RATiedReg::kOut | RATiedReg::kWrite | RATiedReg::kOutFixed; - uint32_t group = workReg->group(); - uint32_t allocable = Support::bitMask(outId); + RATiedFlags flags = RATiedFlags::kOut | RATiedFlags::kWrite | RATiedFlags::kOutFixed; + RegGroup group = workReg->group(); + RegMask outRegs = Support::bitMask(outId); _aggregatedFlags |= flags; - _used[group] |= allocable; + _used[group] |= outRegs; _stats.makeFixed(group); _stats.makeUsed(group); @@ -569,7 +577,7 @@ public: ASMJIT_ASSERT(tiedRegCount() < ASMJIT_ARRAY_SIZE(_tiedRegs)); tiedReg = _cur++; - tiedReg->init(workReg->workId(), flags, allocable, BaseReg::kIdBad, 0, outId, 0); + tiedReg->init(workReg->workId(), flags, Support::allOnes<RegMask>(), BaseReg::kIdBad, 0, outRegs, outId, 0); workReg->setTiedReg(tiedReg); _count.add(group); @@ -589,21 +597,21 @@ public: //! \} }; -// ============================================================================ -// [asmjit::RASharedAssignment] -// ============================================================================ - +//! Intersection of multiple register assignments. +//! +//! See \ref RAAssignment for more information about register assignments. class RASharedAssignment { public: typedef RAAssignment::PhysToWorkMap PhysToWorkMap; typedef RAAssignment::WorkToPhysMap WorkToPhysMap; - //! Bit-mask of registers that cannot be used upon a block entry, for each - //! block that has this shared assignment. Scratch registers can come from - //! ISA limits (like jecx/loop instructions on x86) or because the registers - //! are used by jump/branch instruction that uses registers to perform an - //! indirect jump. - uint32_t _entryScratchGpRegs = 0; + //! \name Members + //! \{ + + //! Bit-mask of registers that cannot be used upon a block entry, for each block that has this shared assignment. + //! Scratch registers can come from ISA limits (like jecx/loop instructions on x86) or because the registers are + //! used by jump/branch instruction that uses registers to perform an indirect jump. + RegMask _entryScratchGpRegs = 0; //! Union of all live-in registers. ZoneBitVector _liveIn {}; //! Register assignment (PhysToWork). @@ -611,30 +619,28 @@ public: //! Register assignment (WorkToPhys). WorkToPhysMap* _workToPhysMap = nullptr; - //! Most likely never called as we initialize a vector of shared assignments to zero. - inline RASharedAssignment() noexcept {} + //! \} + + //! \name Accessors + //! \{ - inline uint32_t entryScratchGpRegs() const noexcept { return _entryScratchGpRegs; } - inline void addEntryScratchGpRegs(uint32_t mask) noexcept { _entryScratchGpRegs |= mask; } + inline bool empty() const noexcept { return _physToWorkMap == nullptr; } + + inline RegMask entryScratchGpRegs() const noexcept { return _entryScratchGpRegs; } + inline void addEntryScratchGpRegs(RegMask mask) noexcept { _entryScratchGpRegs |= mask; } inline const ZoneBitVector& liveIn() const noexcept { return _liveIn; } inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } inline WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; } - inline bool empty() const noexcept { - return _physToWorkMap == nullptr; - } - inline void assignMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { _physToWorkMap = physToWorkMap; _workToPhysMap = workToPhysMap; } -}; -// ============================================================================ -// [asmjit::BaseRAPass] -// ============================================================================ + //! \} +}; //! Register allocation pass used by `BaseCompiler`. class BaseRAPass : public FuncPass { @@ -642,13 +648,16 @@ public: ASMJIT_NONCOPYABLE(BaseRAPass) typedef FuncPass Base; - enum Weights : uint32_t { + enum : uint32_t { kCallArgWeight = 80 }; typedef RAAssignment::PhysToWorkMap PhysToWorkMap; typedef RAAssignment::WorkToPhysMap WorkToPhysMap; + //! \name Members + //! \{ + //! Allocator that uses zone passed to `runOnFunction()`. ZoneAllocator _allocator {}; //! Emit helper. @@ -656,10 +665,10 @@ public: //! Logger, disabled if null. Logger* _logger = nullptr; - //! Debug logger, non-null only if `kOptionDebugPasses` option is set. - Logger* _debugLogger = nullptr; - //! Logger flags. - uint32_t _loggerFlags = 0; + //! Format options, copied from Logger, or zeroed if there is no logger. + FormatOptions _formatOptions {}; + //! Diagnostic options, copied from Emitter, or zeroed if there is no logger. + DiagnosticOptions _diagnosticOptions {}; //! Function being processed. FuncNode* _func = nullptr; @@ -680,7 +689,7 @@ public: //! Number of created blocks (internal). uint32_t _createdBlockCount = 0; - //! SharedState blocks. + //! Shared assignment blocks. ZoneVector<RASharedAssignment> _sharedAssignments {}; //! Timestamp generator (incremental). @@ -695,7 +704,7 @@ public: //! Total number of physical registers. uint32_t _physRegTotal = 0; //! Indexes of a possible scratch registers that can be selected if necessary. - uint8_t _scratchRegIndexes[2] {}; + Support::Array<uint8_t, 2> _scratchRegIndexes {}; //! Registers available for allocation. RARegMask _availableRegs = RARegMask(); @@ -707,14 +716,14 @@ public: //! Work registers (registers used by the function). RAWorkRegs _workRegs; //! Work registers per register group. - RAWorkRegs _workRegsOfGroup[BaseReg::kGroupVirt]; + Support::Array<RAWorkRegs, Globals::kNumVirtGroups> _workRegsOfGroup; //! Register allocation strategy per register group. - RAStrategy _strategy[BaseReg::kGroupVirt]; + Support::Array<RAStrategy, Globals::kNumVirtGroups> _strategy; //! Global max live-count (from all blocks) per register group. RALiveCount _globalMaxLiveCount = RALiveCount(); //! Global live spans per register group. - LiveRegSpans* _globalLiveSpans[BaseReg::kGroupVirt] {}; + Support::Array<LiveRegSpans*, Globals::kNumVirtGroups> _globalLiveSpans {}; //! Temporary stack slot. Operand _temporaryMem = Operand(); @@ -734,7 +743,9 @@ public: //! Temporary string builder used to format comments. StringTmp<80> _tmpString; - //! \name Construction & Reset + //! \} + + //! \name Construction & Destruction //! \{ BaseRAPass() noexcept; @@ -747,8 +758,14 @@ public: //! Returns \ref Logger passed to \ref runOnFunction(). inline Logger* logger() const noexcept { return _logger; } - //! Returns \ref Logger passed to \ref runOnFunction() or null if `kOptionDebugPasses` is not set. - inline Logger* debugLogger() const noexcept { return _debugLogger; } + + //! Returns either a valid logger if the given `option` is set and logging is enabled, or nullptr. + inline Logger* getLoggerIf(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option) ? _logger : nullptr; } + + //! Returns whether the diagnostic `option` is enabled. + //! + //! \note Returns false if there is no logger (as diagnostics without logging make no sense). + inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); } //! Returns \ref Zone passed to \ref runOnFunction(). inline Zone* zone() const noexcept { return _allocator.zone(); } @@ -778,7 +795,7 @@ public: //! \name Utilities //! \{ - inline void makeUnavailable(uint32_t group, uint32_t regId) noexcept { + inline void makeUnavailable(RegGroup group, uint32_t regId) noexcept { _availableRegs[group] &= ~Support::bitMask(regId); _availableRegCount[group]--; } @@ -829,12 +846,11 @@ public: //! Returns the count of reachable basic blocks (returns size of `_pov` array). inline uint32_t reachableBlockCount() const noexcept { return _pov.size(); } - //! Tests whether the CFG has dangling blocks - these were created by `newBlock()`, - //! but not added to CFG through `addBlocks()`. If `true` is returned and the - //! CFG is constructed it means that something is missing and it's incomplete. + //! Tests whether the CFG has dangling blocks - these were created by `newBlock()`, but not added to CFG through + //! `addBlocks()`. If `true` is returned and the CFG is constructed it means that something is missing and it's + //! incomplete. //! - //! \note This is only used to check if the number of created blocks matches - //! the number of added blocks. + //! \note This is only used to check if the number of created blocks matches the number of added blocks. inline bool hasDanglingBlocks() const noexcept { return _createdBlockCount != blockCount(); } //! Gest a next timestamp to be used to mark CFG blocks. @@ -842,31 +858,29 @@ public: //! Createss a new `RABlock` instance. //! - //! \note New blocks don't have ID assigned until they are added to the block - //! array by calling `addBlock()`. + //! \note New blocks don't have ID assigned until they are added to the block array by calling `addBlock()`. RABlock* newBlock(BaseNode* initialNode = nullptr) noexcept; - //! Tries to find a neighboring LabelNode (without going through code) that is - //! already connected with `RABlock`. If no label is found then a new RABlock - //! is created and assigned to all possible labels in a backward direction. + //! Tries to find a neighboring LabelNode (without going through code) that is already connected with `RABlock`. + //! If no label is found then a new RABlock is created and assigned to all possible labels in a backward direction. RABlock* newBlockOrExistingAt(LabelNode* cbLabel, BaseNode** stoppedAt = nullptr) noexcept; //! Adds the given `block` to the block list and assign it a unique block id. Error addBlock(RABlock* block) noexcept; inline Error addExitBlock(RABlock* block) noexcept { - block->addFlags(RABlock::kFlagIsFuncExit); + block->addFlags(RABlockFlags::kIsFuncExit); return _exits.append(allocator(), block); } - ASMJIT_INLINE RAInst* newRAInst(RABlock* block, uint32_t flags, uint32_t tiedRegCount, const RARegMask& clobberedRegs) noexcept { + ASMJIT_FORCE_INLINE RAInst* newRAInst(RABlock* block, RATiedFlags flags, uint32_t tiedRegCount, const RARegMask& clobberedRegs) noexcept { void* p = zone()->alloc(RAInst::sizeOf(tiedRegCount)); if (ASMJIT_UNLIKELY(!p)) return nullptr; return new(p) RAInst(block, flags, tiedRegCount, clobberedRegs); } - ASMJIT_INLINE Error assignRAInst(BaseNode* node, RABlock* block, RAInstBuilder& ib) noexcept { + ASMJIT_FORCE_INLINE Error assignRAInst(BaseNode* node, RABlock* block, RAInstBuilder& ib) noexcept { uint32_t tiedRegCount = ib.tiedRegCount(); RAInst* raInst = newRAInst(block, ib.aggregatedFlags(), tiedRegCount, ib._clobbered); @@ -874,7 +888,7 @@ public: return DebugUtils::errored(kErrorOutOfMemory); RARegIndex index; - uint32_t flagsFilter = ~ib.forbiddenFlags(); + RATiedFlags flagsFilter = ~ib.forbiddenFlags(); index.buildIndexes(ib._count); raInst->_tiedIndex = index; @@ -885,15 +899,15 @@ public: RAWorkReg* workReg = workRegById(tiedReg->workId()); workReg->resetTiedReg(); - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); if (tiedReg->hasUseId()) { - block->addFlags(RABlock::kFlagHasFixedRegs); + block->addFlags(RABlockFlags::kHasFixedRegs); raInst->_usedRegs[group] |= Support::bitMask(tiedReg->useId()); } if (tiedReg->hasOutId()) { - block->addFlags(RABlock::kFlagHasFixedRegs); + block->addFlags(RABlockFlags::kHasFixedRegs); } RATiedReg& dst = raInst->_tiedRegs[index[group]++]; @@ -901,7 +915,7 @@ public: dst._flags &= flagsFilter; if (!tiedReg->isDuplicate()) - dst._allocableRegs &= ~ib._used[group]; + dst._useRegMask &= ~ib._used[group]; } node->setPassData<RAInst>(raInst); @@ -915,18 +929,15 @@ public: //! Traverse the whole function and do the following: //! - //! 1. Construct CFG (represented by `RABlock`) by populating `_blocks` and - //! `_exits`. Blocks describe the control flow of the function and contain - //! some additional information that is used by the register allocator. + //! 1. Construct CFG (represented by `RABlock`) by populating `_blocks` and `_exits`. Blocks describe the control + //! flow of the function and contain some additional information that is used by the register allocator. //! - //! 2. Remove unreachable code immediately. This is not strictly necessary - //! for BaseCompiler itself as the register allocator cannot reach such - //! nodes, but keeping instructions that use virtual registers would fail - //! during instruction encoding phase (Assembler). + //! 2. Remove unreachable code immediately. This is not strictly necessary for BaseCompiler itself as the register + //! allocator cannot reach such nodes, but keeping instructions that use virtual registers would fail during + //! instruction encoding phase (Assembler). //! - //! 3. `RAInst` is created for each `InstNode` or compatible. It contains - //! information that is essential for further analysis and register - //! allocation. + //! 3. `RAInst` is created for each `InstNode` or compatible. It contains information that is essential for further + //! analysis and register allocation. //! //! Use `RACFGBuilderT` template that provides the necessary boilerplate. virtual Error buildCFG() noexcept = 0; @@ -940,7 +951,7 @@ public: //! \{ //! Constructs CFG views (only POV at the moment). - Error buildViews() noexcept; + Error buildCFGViews() noexcept; //! \} @@ -948,13 +959,11 @@ public: //! \{ // Terminology: - // - A node `X` dominates a node `Z` if any path from the entry point to - // `Z` has to go through `X`. - // - A node `Z` post-dominates a node `X` if any path from `X` to the end - // of the graph has to go through `Z`. + // - A node `X` dominates a node `Z` if any path from the entry point to `Z` has to go through `X`. + // - A node `Z` post-dominates a node `X` if any path from `X` to the end of the graph has to go through `Z`. //! Constructs a dominator-tree from CFG. - Error buildDominators() noexcept; + Error buildCFGDominators() noexcept; bool _strictlyDominates(const RABlock* a, const RABlock* b) const noexcept; const RABlock* _nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept; @@ -974,17 +983,15 @@ public: //! \name CFG - Utilities //! \{ - Error removeUnreachableBlocks() noexcept; + Error removeUnreachableCode() noexcept; - //! Returns `node` or some node after that is ideal for beginning a new block. - //! This function is mostly used after a conditional or unconditional jump to - //! select the successor node. In some cases the next node could be a label, + //! Returns `node` or some node after that is ideal for beginning a new block. This function is mostly used after + //! a conditional or unconditional jump to select the successor node. In some cases the next node could be a label, //! which means it could have assigned some block already. BaseNode* findSuccessorStartingAt(BaseNode* node) noexcept; - //! Returns `true` of the `node` can flow to `target` without reaching code - //! nor data. It's used to eliminate jumps to labels that are next right to - //! them. + //! Returns `true` of the `node` can flow to `target` without reaching code nor data. It's used to eliminate jumps + //! to labels that are next right to them. bool isNextTo(BaseNode* node, BaseNode* target) noexcept; //! \} @@ -994,25 +1001,25 @@ public: //! Returns a native size of the general-purpose register of the target architecture. inline uint32_t registerSize() const noexcept { return _sp.size(); } - inline uint32_t availableRegCount(uint32_t group) const noexcept { return _availableRegCount[group]; } + inline uint32_t availableRegCount(RegGroup group) const noexcept { return _availableRegCount[group]; } inline RAWorkReg* workRegById(uint32_t workId) const noexcept { return _workRegs[workId]; } inline RAWorkRegs& workRegs() noexcept { return _workRegs; } - inline RAWorkRegs& workRegs(uint32_t group) noexcept { return _workRegsOfGroup[group]; } + inline RAWorkRegs& workRegs(RegGroup group) noexcept { return _workRegsOfGroup[group]; } inline const RAWorkRegs& workRegs() const noexcept { return _workRegs; } - inline const RAWorkRegs& workRegs(uint32_t group) const noexcept { return _workRegsOfGroup[group]; } + inline const RAWorkRegs& workRegs(RegGroup group) const noexcept { return _workRegsOfGroup[group]; } inline uint32_t workRegCount() const noexcept { return _workRegs.size(); } - inline uint32_t workRegCount(uint32_t group) const noexcept { return _workRegsOfGroup[group].size(); } + inline uint32_t workRegCount(RegGroup group) const noexcept { return _workRegsOfGroup[group].size(); } inline void _buildPhysIndex() noexcept { _physRegIndex.buildIndexes(_physRegCount); - _physRegTotal = uint32_t(_physRegIndex[BaseReg::kGroupVirt - 1]) + - uint32_t(_physRegCount[BaseReg::kGroupVirt - 1]) ; + _physRegTotal = uint32_t(_physRegIndex[RegGroup::kMaxVirt]) + + uint32_t(_physRegCount[RegGroup::kMaxVirt]) ; } - inline uint32_t physRegIndex(uint32_t group) const noexcept { return _physRegIndex[group]; } + inline uint32_t physRegIndex(RegGroup group) const noexcept { return _physRegIndex[group]; } inline uint32_t physRegTotal() const noexcept { return _physRegTotal; } Error _asWorkReg(VirtReg* vReg, RAWorkReg** out) noexcept; @@ -1024,7 +1031,7 @@ public: return *out ? kErrorOk : _asWorkReg(vReg, out); } - inline Error virtIndexAsWorkReg(uint32_t vIndex, RAWorkReg** out) noexcept { + ASMJIT_FORCE_INLINE Error virtIndexAsWorkReg(uint32_t vIndex, RAWorkReg** out) noexcept { const ZoneVector<VirtReg*>& virtRegs = cc()->virtRegs(); if (ASMJIT_UNLIKELY(vIndex >= virtRegs.size())) return DebugUtils::errored(kErrorInvalidVirtId); @@ -1045,7 +1052,10 @@ public: inline BaseMem workRegAsMem(RAWorkReg* workReg) noexcept { getOrCreateStackSlot(workReg); - return BaseMem(BaseMem::Decomposed { _sp.type(), workReg->virtId(), BaseReg::kTypeNone, 0, 0, 0, BaseMem::kSignatureMemRegHomeFlag }); + return BaseMem(OperandSignature::fromOpType(OperandType::kMem) | + OperandSignature::fromMemBaseType(_sp.type()) | + OperandSignature::fromBits(OperandSignature::kMemRegHomeFlag), + workReg->virtId(), 0, 0); } WorkToPhysMap* newWorkToPhysMap() noexcept; @@ -1085,7 +1095,7 @@ public: //! Initializes data structures used for global live spans. Error initGlobalLiveSpans() noexcept; - Error binPack(uint32_t group) noexcept; + Error binPack(RegGroup group) noexcept; //! \} @@ -1159,8 +1169,8 @@ public: inline ZoneAllocator* RABlock::allocator() const noexcept { return _ra->allocator(); } -inline uint32_t RABlock::entryScratchGpRegs() const noexcept { - uint32_t regs = _entryScratchGpRegs; +inline RegMask RABlock::entryScratchGpRegs() const noexcept { + RegMask regs = _entryScratchGpRegs; if (hasSharedAssignmentId()) regs = _ra->_sharedAssignments[_sharedAssignmentId].entryScratchGpRegs(); return regs; diff --git a/src/asmjit/core/rastack.cpp b/src/asmjit/core/rastack.cpp index b886279..2b7ed59 100644 --- a/src/asmjit/core/rastack.cpp +++ b/src/asmjit/core/rastack.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_COMPILER @@ -29,9 +11,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::RAStackAllocator - Slots] -// ============================================================================ +// RAStackAllocator - Slots +// ======================== RAStackSlot* RAStackAllocator::newSlot(uint32_t baseRegId, uint32_t size, uint32_t alignment, uint32_t flags) noexcept { if (ASMJIT_UNLIKELY(_slots.willGrow(allocator(), 1) != kErrorOk)) @@ -55,9 +36,8 @@ RAStackSlot* RAStackAllocator::newSlot(uint32_t baseRegId, uint32_t size, uint32 return slot; } -// ============================================================================ -// [asmjit::RAStackAllocator - Utilities] -// ============================================================================ +// RAStackAllocator - Utilities +// ============================ struct RAStackGap { inline RAStackGap() noexcept @@ -82,10 +62,9 @@ Error RAStackAllocator::calculateStackFrame() noexcept { // STEP 1: // - // Update usage based on the size of the slot. We boost smaller slots in a way - // that 32-bit register has higher priority than a 128-bit register, however, - // if one 128-bit register is used 4 times more than some other 32-bit register - // it will overweight it. + // Update usage based on the size of the slot. We boost smaller slots in a way that 32-bit register has higher + // priority than a 128-bit register, however, if one 128-bit register is used 4 times more than some other 32-bit + // register it will overweight it. for (RAStackSlot* slot : _slots) { uint32_t alignment = slot->alignment(); ASMJIT_ASSERT(alignment > 0); @@ -98,8 +77,8 @@ Error RAStackAllocator::calculateStackFrame() noexcept { else weight = power; - // If overflown, which has less chance of winning a lottery, just use max - // possible weight. In such case it probably doesn't matter at all. + // If overflown, which has less chance of winning a lottery, just use max possible weight. In such case it + // probably doesn't matter at all. if (weight > 0xFFFFFFFFu) weight = 0xFFFFFFFFu; @@ -116,12 +95,11 @@ Error RAStackAllocator::calculateStackFrame() noexcept { // STEP 3: // - // Calculate offset of each slot. We start from the slot that has the highest - // weight and advance to slots with lower weight. It could look that offsets - // start from the first slot in our list and then simply increase, but it's - // not always the case as we also try to fill all gaps introduced by the fact - // that slots are sorted by weight and not by size & alignment, so when we need - // to align some slot we distribute the gap caused by the alignment to `gaps`. + // Calculate offset of each slot. We start from the slot that has the highest weight and advance to slots with + // lower weight. It could look that offsets start from the first slot in our list and then simply increase, but + // it's not always the case as we also try to fill all gaps introduced by the fact that slots are sorted by + // weight and not by size & alignment, so when we need to align some slot we distribute the gap caused by the + // alignment to `gaps`. uint32_t offset = 0; ZoneVector<RAStackGap> gaps[kSizeCount - 1]; diff --git a/src/asmjit/core/rastack_p.h b/src/asmjit/core/rastack_p.h index 33d4e1d..90640b4 100644 --- a/src/asmjit/core/rastack_p.h +++ b/src/asmjit/core/rastack_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RASTACK_P_H_INCLUDED #define ASMJIT_CORE_RASTACK_P_H_INCLUDED @@ -35,26 +17,25 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [asmjit::RAStackSlot] -// ============================================================================ - //! Stack slot. struct RAStackSlot { //! Stack slot flags. //! //! TODO: kFlagStackArg is not used by the current implementation, do we need to keep it? - enum Flags : uint32_t { + enum Flags : uint16_t { //! Stack slot is register home slot. kFlagRegHome = 0x0001u, //! Stack slot position matches argument passed via stack. - kFlagStackArg = 0x0002u + kFlagStackArg = 0x0002u }; enum ArgIndex : uint32_t { kNoArgIndex = 0xFF }; + //! \name Members + //! \{ + //! Base register used to address the stack. uint8_t _baseRegId; //! Minimum alignment required by the slot. @@ -71,6 +52,8 @@ struct RAStackSlot { //! Stack offset, calculated by \ref RAStackAllocator::calculateStackFrame(). int32_t _offset; + //! \} + //! \name Accessors //! \{ @@ -101,10 +84,6 @@ struct RAStackSlot { typedef ZoneVector<RAStackSlot*> RAStackSlots; -// ============================================================================ -// [asmjit::RAStackAllocator] -// ============================================================================ - //! Stack allocator. class RAStackAllocator { public: @@ -121,6 +100,9 @@ public: kSizeCount = 7 }; + //! \name Members + //! \{ + //! Allocator used to allocate internal data. ZoneAllocator* _allocator; //! Count of bytes used by all slots. @@ -132,7 +114,9 @@ public: //! Stack slots vector. RAStackSlots _slots; - //! \name Construction / Destruction + //! \} + + //! \name Construction & Destruction //! \{ inline RAStackAllocator() noexcept diff --git a/src/asmjit/core/string.cpp b/src/asmjit/core/string.cpp index 8cebfcc..19d1e18 100644 --- a/src/asmjit/core/string.cpp +++ b/src/asmjit/core/string.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/string.h" @@ -27,18 +9,16 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::String - Globals] -// ============================================================================ +// String - Globals +// ================ static const char String_baseN[] = "0123456789ABCDEF"; constexpr size_t kMinAllocSize = 64; constexpr size_t kMaxAllocSize = SIZE_MAX - Globals::kGrowThreshold; -// ============================================================================ -// [asmjit::String] -// ============================================================================ +// String - Clear & Reset +// ====================== Error String::reset() noexcept { if (_type == kTypeLarge) @@ -60,7 +40,10 @@ Error String::clear() noexcept { return kErrorOk; } -char* String::prepare(uint32_t op, size_t size) noexcept { +// String - Prepare +// ================ + +char* String::prepare(ModifyOp op, size_t size) noexcept { char* curData; size_t curSize; size_t curCapacity; @@ -76,7 +59,7 @@ char* String::prepare(uint32_t op, size_t size) noexcept { curCapacity = kSSOCapacity; } - if (op == kOpAssign) { + if (op == ModifyOp::kAssign) { if (size > curCapacity) { // Prevent arithmetic overflow. if (ASMJIT_UNLIKELY(size >= kMaxAllocSize)) @@ -150,6 +133,9 @@ char* String::prepare(uint32_t op, size_t size) noexcept { } } +// String - Assign +// =============== + Error String::assign(const char* data, size_t size) noexcept { char* dst = nullptr; @@ -210,11 +196,10 @@ Error String::assign(const char* data, size_t size) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::String - Operations] -// ============================================================================ +// String - Operations +// =================== -Error String::_opString(uint32_t op, const char* str, size_t size) noexcept { +Error String::_opString(ModifyOp op, const char* str, size_t size) noexcept { if (size == SIZE_MAX) size = str ? strlen(str) : size_t(0); @@ -229,7 +214,7 @@ Error String::_opString(uint32_t op, const char* str, size_t size) noexcept { return kErrorOk; } -Error String::_opChar(uint32_t op, char c) noexcept { +Error String::_opChar(ModifyOp op, char c) noexcept { char* p = prepare(op, 1); if (!p) return DebugUtils::errored(kErrorOutOfMemory); @@ -238,7 +223,7 @@ Error String::_opChar(uint32_t op, char c) noexcept { return kErrorOk; } -Error String::_opChars(uint32_t op, char c, size_t n) noexcept { +Error String::_opChars(ModifyOp op, char c, size_t n) noexcept { if (!n) return kErrorOk; @@ -255,7 +240,7 @@ Error String::padEnd(size_t n, char c) noexcept { return n > size ? appendChars(c, n - size) : kErrorOk; } -Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) noexcept { +Error String::_opNumber(ModifyOp op, uint64_t i, uint32_t base, size_t width, StringFormatFlags flags) noexcept { if (base == 0) base = 10; @@ -265,24 +250,22 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui uint64_t orig = i; char sign = '\0'; - // -------------------------------------------------------------------------- - // [Sign] - // -------------------------------------------------------------------------- + // Format Sign + // ----------- - if ((flags & kFormatSigned) != 0 && int64_t(i) < 0) { + if (Support::test(flags, StringFormatFlags::kSigned) && int64_t(i) < 0) { i = uint64_t(-int64_t(i)); sign = '-'; } - else if ((flags & kFormatShowSign) != 0) { + else if (Support::test(flags, StringFormatFlags::kShowSign)) { sign = '+'; } - else if ((flags & kFormatShowSpace) != 0) { + else if (Support::test(flags, StringFormatFlags::kShowSpace)) { sign = ' '; } - // -------------------------------------------------------------------------- - // [Number] - // -------------------------------------------------------------------------- + // Format Number + // ------------- switch (base) { case 2: @@ -320,11 +303,10 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui size_t numberSize = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p); - // -------------------------------------------------------------------------- - // [Alternate Form] - // -------------------------------------------------------------------------- + // Alternate Form + // -------------- - if ((flags & kFormatAlternate) != 0) { + if (Support::test(flags, StringFormatFlags::kAlternate)) { if (base == 8) { if (orig != 0) *--p = '0'; @@ -335,9 +317,8 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui } } - // -------------------------------------------------------------------------- - // [Width] - // -------------------------------------------------------------------------- + // String Width + // ------------ if (sign != 0) *--p = sign; @@ -350,9 +331,8 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui else width -= numberSize; - // -------------------------------------------------------------------------- - // Write] - // -------------------------------------------------------------------------- + // Finalize + // -------- size_t prefixSize = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p) - numberSize; char* data = prepare(op, prefixSize + width + numberSize); @@ -370,7 +350,7 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui return kErrorOk; } -Error String::_opHex(uint32_t op, const void* data, size_t size, char separator) noexcept { +Error String::_opHex(ModifyOp op, const void* data, size_t size, char separator) noexcept { char* dst; const uint8_t* src = static_cast<const uint8_t*>(data); @@ -414,7 +394,7 @@ Error String::_opHex(uint32_t op, const void* data, size_t size, char separator) return kErrorOk; } -Error String::_opFormat(uint32_t op, const char* fmt, ...) noexcept { +Error String::_opFormat(ModifyOp op, const char* fmt, ...) noexcept { Error err; va_list ap; @@ -425,8 +405,8 @@ Error String::_opFormat(uint32_t op, const char* fmt, ...) noexcept { return err; } -Error String::_opVFormat(uint32_t op, const char* fmt, va_list ap) noexcept { - size_t startAt = (op == kOpAssign) ? size_t(0) : size(); +Error String::_opVFormat(ModifyOp op, const char* fmt, va_list ap) noexcept { + size_t startAt = (op == ModifyOp::kAssign) ? size_t(0) : size(); size_t remainingCapacity = capacity() - startAt; char buf[1024]; @@ -504,9 +484,8 @@ bool String::eq(const char* other, size_t size) const noexcept { } } -// ============================================================================ -// [asmjit::Support - Unit] -// ============================================================================ +// String - Tests +// ============== #if defined(ASMJIT_TEST) UNIT(core_string) { @@ -566,7 +545,7 @@ UNIT(core_string) { EXPECT(s.appendUInt(1234) == kErrorOk); EXPECT(s.eq("1234") == true); - EXPECT(s.assignUInt(0xFFFF, 16, 0, String::kFormatAlternate) == kErrorOk); + EXPECT(s.assignUInt(0xFFFF, 16, 0, StringFormatFlags::kAlternate) == kErrorOk); EXPECT(s.eq("0xFFFF")); StringTmp<64> sTmp; diff --git a/src/asmjit/core/string.h b/src/asmjit/core/string.h index b58725e..d309b82 100644 --- a/src/asmjit/core/string.h +++ b/src/asmjit/core/string.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_STRING_H_INCLUDED #define ASMJIT_CORE_STRING_H_INCLUDED @@ -32,20 +14,41 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_utilities //! \{ -// ============================================================================ -// [asmjit::FixedString] -// ============================================================================ +//! Format flags used by \ref String API. +enum class StringFormatFlags : uint32_t { + //! No flags. + kNone = 0x00000000u, + //! Show sign. + kShowSign = 0x00000001u, + //! Show space. + kShowSpace = 0x00000002u, + //! Alternate form (use 0x when formatting HEX number). + kAlternate = 0x00000004u, + //! The input is signed. + kSigned = 0x80000000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(StringFormatFlags) -//! A fixed string - only useful for strings that would never exceed `N - 1` -//! characters; always null-terminated. +//! Fixed string - only useful for strings that would never exceed `N - 1` characters; always null-terminated. template<size_t N> union FixedString { + //! \name Constants + //! \{ + + // This cannot be constexpr as GCC 4.8 refuses constexpr members of unions. enum : uint32_t { - kNumU32 = uint32_t((N + sizeof(uint32_t) - 1) / sizeof(uint32_t)) + kNumUInt32Words = uint32_t((N + sizeof(uint32_t) - 1) / sizeof(uint32_t)) }; - char str[kNumU32 * sizeof(uint32_t)]; - uint32_t u32[kNumU32]; + //! \} + + //! \name Members + //! \{ + + char str[kNumUInt32Words * sizeof(uint32_t)]; + uint32_t u32[kNumUInt32Words]; + + //! \} //! \name Utilities //! \{ @@ -56,46 +59,31 @@ union FixedString { //! \} }; -// ============================================================================ -// [asmjit::String] -// ============================================================================ //! A simple non-reference counted string that uses small string optimization (SSO). //! //! This string has 3 allocation possibilities: //! -//! 1. Small - embedded buffer is used for up to `kSSOCapacity` characters. -//! This should handle most small strings and thus avoid dynamic -//! memory allocation for most use-cases. +//! 1. Small - embedded buffer is used for up to `kSSOCapacity` characters. This should handle most small +//! strings and thus avoid dynamic memory allocation for most use-cases. //! -//! 2. Large - string that doesn't fit into an embedded buffer (or string -//! that was truncated from a larger buffer) and is owned by -//! AsmJit. When you destroy the string AsmJit would automatically +//! 2. Large - string that doesn't fit into an embedded buffer (or string that was truncated from a larger +//! buffer) and is owned by AsmJit. When you destroy the string AsmJit would automatically //! release the large buffer. //! -//! 3. External - like Large (2), however, the large buffer is not owned by -//! AsmJit and won't be released when the string is destroyed -//! or reallocated. This is mostly useful for working with -//! larger temporary strings allocated on stack or with immutable -//! strings. +//! 3. External - like Large (2), however, the large buffer is not owned by AsmJit and won't be released when +//! the string is destroyed or reallocated. This is mostly useful for working with larger temporary +//! strings allocated on stack or with immutable strings. class String { public: ASMJIT_NONCOPYABLE(String) //! String operation. - enum Op : uint32_t { + enum class ModifyOp : uint32_t { //! Assignment - a new content replaces the current one. - kOpAssign = 0, + kAssign = 0, //! Append - a new content is appended to the string. - kOpAppend = 1 - }; - - //! String format flags. - enum FormatFlags : uint32_t { - kFormatShowSign = 0x00000001u, - kFormatShowSpace = 0x00000002u, - kFormatAlternate = 0x00000004u, - kFormatSigned = 0x80000000u + kAppend = 1 }; //! \cond INTERNAL @@ -106,8 +94,10 @@ public: //! String type. enum Type : uint8_t { - kTypeLarge = 0x1Fu, //!< Large string (owned by String). - kTypeExternal = 0x20u //!< External string (zone allocated or not owned by String). + //! Large string (owned by String). + kTypeLarge = 0x1Fu, + //! External string (zone allocated or not owned by String). + kTypeExternal = 0x20u }; union Raw { @@ -213,15 +203,15 @@ public: //! Clears the content of the string. ASMJIT_API Error clear() noexcept; - ASMJIT_API char* prepare(uint32_t op, size_t size) noexcept; + ASMJIT_API char* prepare(ModifyOp op, size_t size) noexcept; - ASMJIT_API Error _opString(uint32_t op, const char* str, size_t size = SIZE_MAX) noexcept; - ASMJIT_API Error _opChar(uint32_t op, char c) noexcept; - ASMJIT_API Error _opChars(uint32_t op, char c, size_t n) noexcept; - ASMJIT_API Error _opNumber(uint32_t op, uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept; - ASMJIT_API Error _opHex(uint32_t op, const void* data, size_t size, char separator = '\0') noexcept; - ASMJIT_API Error _opFormat(uint32_t op, const char* fmt, ...) noexcept; - ASMJIT_API Error _opVFormat(uint32_t op, const char* fmt, va_list ap) noexcept; + ASMJIT_API Error _opString(ModifyOp op, const char* str, size_t size = SIZE_MAX) noexcept; + ASMJIT_API Error _opChar(ModifyOp op, char c) noexcept; + ASMJIT_API Error _opChars(ModifyOp op, char c, size_t n) noexcept; + ASMJIT_API Error _opNumber(ModifyOp op, uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept; + ASMJIT_API Error _opHex(ModifyOp op, const void* data, size_t size, char separator = '\0') noexcept; + ASMJIT_API Error _opFormat(ModifyOp op, const char* fmt, ...) noexcept; + ASMJIT_API Error _opVFormat(ModifyOp op, const char* fmt, va_list ap) noexcept; //! Replaces the current of the string with `data` of the given `size`. //! @@ -235,45 +225,45 @@ public: //! Replaces the current of the string by a single `c` character. inline Error assign(char c) noexcept { - return _opChar(kOpAssign, c); + return _opChar(ModifyOp::kAssign, c); } //! Replaces the current of the string by a `c` character, repeated `n` times. inline Error assignChars(char c, size_t n) noexcept { - return _opChars(kOpAssign, c, n); + return _opChars(ModifyOp::kAssign, c, n); } //! Replaces the current of the string by a formatted integer `i` (signed). - inline Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept { - return _opNumber(kOpAssign, uint64_t(i), base, width, flags | kFormatSigned); + inline Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + return _opNumber(ModifyOp::kAssign, uint64_t(i), base, width, flags | StringFormatFlags::kSigned); } //! Replaces the current of the string by a formatted integer `i` (unsigned). - inline Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept { - return _opNumber(kOpAssign, i, base, width, flags); + inline Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + return _opNumber(ModifyOp::kAssign, i, base, width, flags); } //! Replaces the current of the string by the given `data` converted to a HEX string. inline Error assignHex(const void* data, size_t size, char separator = '\0') noexcept { - return _opHex(kOpAssign, data, size, separator); + return _opHex(ModifyOp::kAssign, data, size, separator); } //! Replaces the current of the string by a formatted string `fmt`. template<typename... Args> inline Error assignFormat(const char* fmt, Args&&... args) noexcept { - return _opFormat(kOpAssign, fmt, std::forward<Args>(args)...); + return _opFormat(ModifyOp::kAssign, fmt, std::forward<Args>(args)...); } //! Replaces the current of the string by a formatted string `fmt` (va_list version). inline Error assignVFormat(const char* fmt, va_list ap) noexcept { - return _opVFormat(kOpAssign, fmt, ap); + return _opVFormat(ModifyOp::kAssign, fmt, ap); } //! Appends `str` having the given size `size` to the string. //! //! Null terminated strings can set `size` to `SIZE_MAX`. inline Error append(const char* str, size_t size = SIZE_MAX) noexcept { - return _opString(kOpAppend, str, size); + return _opString(ModifyOp::kAppend, str, size); } //! Appends `other` string to this string. @@ -283,38 +273,38 @@ public: //! Appends a single `c` character. inline Error append(char c) noexcept { - return _opChar(kOpAppend, c); + return _opChar(ModifyOp::kAppend, c); } //! Appends `c` character repeated `n` times. inline Error appendChars(char c, size_t n) noexcept { - return _opChars(kOpAppend, c, n); + return _opChars(ModifyOp::kAppend, c, n); } //! Appends a formatted integer `i` (signed). - inline Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept { - return _opNumber(kOpAppend, uint64_t(i), base, width, flags | kFormatSigned); + inline Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + return _opNumber(ModifyOp::kAppend, uint64_t(i), base, width, flags | StringFormatFlags::kSigned); } //! Appends a formatted integer `i` (unsigned). - inline Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) noexcept { - return _opNumber(kOpAppend, i, base, width, flags); + inline Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept { + return _opNumber(ModifyOp::kAppend, i, base, width, flags); } //! Appends the given `data` converted to a HEX string. inline Error appendHex(const void* data, size_t size, char separator = '\0') noexcept { - return _opHex(kOpAppend, data, size, separator); + return _opHex(ModifyOp::kAppend, data, size, separator); } //! Appends a formatted string `fmt` with `args`. template<typename... Args> inline Error appendFormat(const char* fmt, Args&&... args) noexcept { - return _opFormat(kOpAppend, fmt, std::forward<Args>(args)...); + return _opFormat(ModifyOp::kAppend, fmt, std::forward<Args>(args)...); } //! Appends a formatted string `fmt` (va_list version). inline Error appendVFormat(const char* fmt, va_list ap) noexcept { - return _opVFormat(kOpAppend, fmt, ap); + return _opVFormat(ModifyOp::kAppend, fmt, ap); } ASMJIT_API Error padEnd(size_t n, char c = ' ') noexcept; @@ -332,8 +322,8 @@ public: //! Resets string to embedded and makes it empty (zero length, zero first char) //! - //! \note This is always called internally after an external buffer was released - //! as it zeroes all bytes used by String's embedded storage. + //! \note This is always called internally after an external buffer was released as it zeroes all bytes + //! used by String's embedded storage. inline void _resetInternal() noexcept { for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_raw.uptr); i++) _raw.uptr[i] = 0; @@ -347,26 +337,8 @@ public: } //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use assign() instead of assignString()") - inline Error assignString(const char* data, size_t size = SIZE_MAX) noexcept { return assign(data, size); } - - ASMJIT_DEPRECATED("Use assign() instead of assignChar()") - inline Error assignChar(char c) noexcept { return assign(c); } - - ASMJIT_DEPRECATED("Use append() instead of appendString()") - inline Error appendString(const char* data, size_t size = SIZE_MAX) noexcept { return append(data, size); } - - ASMJIT_DEPRECATED("Use append() instead of appendChar()") - inline Error appendChar(char c) noexcept { return append(c); } -#endif // !ASMJIT_NO_DEPRECATED }; -// ============================================================================ -// [asmjit::StringTmp] -// ============================================================================ - //! Temporary string builder, has statically allocated `N` bytes. template<size_t N> class StringTmp : public String { diff --git a/src/asmjit/core/support.cpp b/src/asmjit/core/support.cpp index a99477d..34253fd 100644 --- a/src/asmjit/core/support.cpp +++ b/src/asmjit/core/support.cpp @@ -1,34 +1,15 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/support.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Support - Unit] -// ============================================================================ +// Support - Tests +// =============== #if defined(ASMJIT_TEST) template<typename T> @@ -85,10 +66,14 @@ static void testBitUtils() noexcept { for (i = 0; i < 63; i++) EXPECT(Support::blsi(uint64_t(3) << i) == uint64_t(1) << i); INFO("Support::ctz()"); + for (i = 0; i < 32; i++) EXPECT(Support::Internal::clzFallback(uint32_t(1) << i) == 31 - i); + for (i = 0; i < 64; i++) EXPECT(Support::Internal::clzFallback(uint64_t(1) << i) == 63 - i); + for (i = 0; i < 32; i++) EXPECT(Support::Internal::ctzFallback(uint32_t(1) << i) == i); + for (i = 0; i < 64; i++) EXPECT(Support::Internal::ctzFallback(uint64_t(1) << i) == i); + for (i = 0; i < 32; i++) EXPECT(Support::clz(uint32_t(1) << i) == 31 - i); + for (i = 0; i < 64; i++) EXPECT(Support::clz(uint64_t(1) << i) == 63 - i); for (i = 0; i < 32; i++) EXPECT(Support::ctz(uint32_t(1) << i) == i); for (i = 0; i < 64; i++) EXPECT(Support::ctz(uint64_t(1) << i) == i); - for (i = 0; i < 32; i++) EXPECT(Support::constCtz(uint32_t(1) << i) == i); - for (i = 0; i < 64; i++) EXPECT(Support::constCtz(uint64_t(1) << i) == i); INFO("Support::bitMask()"); EXPECT(Support::bitMask(0, 1, 7) == 0x83u); diff --git a/src/asmjit/core/support.h b/src/asmjit/core/support.h index f98ffaa..ebf0354 100644 --- a/src/asmjit/core/support.h +++ b/src/asmjit/core/support.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_SUPPORT_H_INCLUDED #define ASMJIT_CORE_SUPPORT_H_INCLUDED @@ -40,9 +22,8 @@ ASMJIT_BEGIN_NAMESPACE //! not be used outside of AsmJit and related projects like AsmTK. namespace Support { -// ============================================================================ -// [asmjit::Support - Architecture Features & Constraints] -// ============================================================================ +// Support - Architecture Features & Constraints +// ============================================= //! \cond INTERNAL static constexpr bool kUnalignedAccess16 = ASMJIT_ARCH_X86 != 0; @@ -50,9 +31,14 @@ static constexpr bool kUnalignedAccess32 = ASMJIT_ARCH_X86 != 0; static constexpr bool kUnalignedAccess64 = ASMJIT_ARCH_X86 != 0; //! \endcond -// ============================================================================ -// [asmjit::Support - Internal] -// ============================================================================ +// Support - Basic Traits +// ====================== + +#if ASMJIT_ARCH_X86 +typedef uint8_t FastUInt8; +#else +typedef uint32_t FastUInt8; +#endif //! \cond INTERNAL namespace Internal { @@ -90,27 +76,9 @@ namespace Internal { } //! \endcond -// ============================================================================ -// [asmjit::Support - Basic Traits] -// ============================================================================ - template<typename T> static constexpr bool isUnsigned() noexcept { return std::is_unsigned<T>::value; } -// ============================================================================ -// [asmjit::Support - FastUInt8] -// ============================================================================ - -#if ASMJIT_ARCH_X86 -typedef uint8_t FastUInt8; -#else -typedef unsigned int FastUInt8; -#endif - -// ============================================================================ -// [asmjit::Support - asInt / asUInt / asNormalized] -// ============================================================================ - //! Casts an integer `x` to either `int32_t` or `int64_t` depending on `T`. template<typename T> static constexpr typename Internal::Int32Or64<T, 0>::Type asInt(const T& x) noexcept { @@ -135,15 +103,33 @@ static constexpr typename Internal::StdInt<sizeof(T), isUnsigned<T>()>::Type asS return (typename Internal::StdInt<sizeof(T), isUnsigned<T>()>::Type)x; } -// ============================================================================ -// [asmjit::Support - BitCast] -// ============================================================================ +//! A helper class that can be used to iterate over enum values. +template<typename T, T from = (T)0, T to = T::kMaxValue> +struct EnumValues { + typedef typename std::underlying_type<T>::type ValueType; + + struct Iterator { + ValueType value; + + inline T operator*() const { return (T)value; } + inline void operator++() { ++value; } + + inline bool operator==(const Iterator& other) const noexcept { return value == other.value; } + inline bool operator!=(const Iterator& other) const noexcept { return value != other.value; } + }; + + inline Iterator begin() const noexcept { return Iterator{ValueType(from)}; } + inline Iterator end() const noexcept { return Iterator{ValueType(to) + 1}; } +}; + +// Support - BitCast +// ================= //! \cond namespace Internal { template<typename DstT, typename SrcT> union BitCastUnion { - ASMJIT_INLINE BitCastUnion(SrcT src) noexcept : src(src) {} + inline BitCastUnion(SrcT src) noexcept : src(src) {} SrcT src; DstT dst; }; @@ -156,9 +142,8 @@ namespace Internal { template<typename Dst, typename Src> static inline Dst bitCast(const Src& x) noexcept { return Internal::BitCastUnion<Dst, Src>(x).dst; } -// ============================================================================ -// [asmjit::Support - BitOps] -// ============================================================================ +// Support - BitOps +// ================ //! Storage used to store a pack of bits (should by compatible with a machine word). typedef Internal::StdInt<sizeof(uintptr_t), 1>::Type BitWord; @@ -226,16 +211,16 @@ static constexpr T lsbMask(const CountT& n) noexcept { template<typename T, typename IndexT> static constexpr bool bitTest(T x, IndexT n) noexcept { typedef typename std::make_unsigned<T>::type U; - return (U(x) & (U(1) << n)) != 0; + return (U(x) & (U(1) << asUInt(n))) != 0; } //! Returns a bit-mask that has `x` bit set. -template<typename T> -static constexpr uint32_t bitMask(T x) noexcept { return (1u << x); } +template<typename Index> +static constexpr uint32_t bitMask(const Index& x) noexcept { return (1u << asUInt(x)); } //! Returns a bit-mask that has `x` bit set (multiple arguments). -template<typename T, typename... Args> -static constexpr uint32_t bitMask(T x, Args... args) noexcept { return bitMask(x) | bitMask(args...); } +template<typename Index, typename... Args> +static constexpr uint32_t bitMask(const Index& x, Args... args) noexcept { return bitMask(x) | bitMask(args...); } //! Converts a boolean value `b` to zero or full mask (all bits set). template<typename DstT, typename SrcT> @@ -244,6 +229,10 @@ static constexpr DstT bitMaskFromBool(SrcT b) noexcept { return DstT(U(0) - U(b)); } +//! Tests whether `a & b` is non-zero. +template<typename A, typename B> +static inline constexpr bool test(A a, B b) noexcept { return (asUInt(a) & asUInt(b)) != 0; } + //! \cond namespace Internal { // Fills all trailing bits right from the first most significant bit set. @@ -264,9 +253,8 @@ static constexpr T fillTrailingBits(const T& x) noexcept { return T(Internal::fillTrailingBitsImpl(U(x))); } -// ============================================================================ -// [asmjit::Support - CTZ] -// ============================================================================ +// Support - Count Leading/Trailing Zeros +// ====================================== //! \cond namespace Internal { @@ -315,11 +303,8 @@ constexpr uint32_t ctzFallback(const T& x) noexcept { return BitScanCalc<T, bitSizeOf<T>() / 2u>::ctz(BitScanData<T>{x, 1}).n; } -template<typename T> constexpr uint32_t constClz(const T& x) noexcept { return clzFallback(asUInt(x)); } -template<typename T> constexpr uint32_t constCtz(const T& x) noexcept { return ctzFallback(asUInt(x)); } - -template<typename T> inline uint32_t clzImpl(const T& x) noexcept { return constClz(x); } -template<typename T> inline uint32_t ctzImpl(const T& x) noexcept { return constCtz(x); } +template<typename T> inline uint32_t clzImpl(const T& x) noexcept { return clzFallback(asUInt(x)); } +template<typename T> inline uint32_t ctzImpl(const T& x) noexcept { return ctzFallback(asUInt(x)); } #if !defined(ASMJIT_NO_INTRINSICS) # if defined(__GNUC__) @@ -347,23 +332,83 @@ template<> inline uint32_t ctzImpl(const uint64_t& x) noexcept { unsigned long i template<typename T> static inline uint32_t clz(T x) noexcept { return Internal::clzImpl(asUInt(x)); } -//! Count leading zeros in `x` (constant expression). -template<typename T> -static constexpr inline uint32_t constClz(T x) noexcept { return Internal::constClz(asUInt(x)); } - //! Count trailing zeros in `x` (returns a position of a first bit set in `x`). //! //! \note The input MUST NOT be zero, otherwise the result is undefined. template<typename T> static inline uint32_t ctz(T x) noexcept { return Internal::ctzImpl(asUInt(x)); } -//! Count trailing zeros in `x` (constant expression). -template<typename T> -static constexpr inline uint32_t constCtz(T x) noexcept { return Internal::constCtz(asUInt(x)); } +template<uint64_t kInput> +struct ConstCTZ { + static constexpr uint32_t value = + (kInput & (uint64_t(1) << 0)) ? 0 : + (kInput & (uint64_t(1) << 1)) ? 1 : + (kInput & (uint64_t(1) << 2)) ? 2 : + (kInput & (uint64_t(1) << 3)) ? 3 : + (kInput & (uint64_t(1) << 4)) ? 4 : + (kInput & (uint64_t(1) << 5)) ? 5 : + (kInput & (uint64_t(1) << 6)) ? 6 : + (kInput & (uint64_t(1) << 7)) ? 7 : + (kInput & (uint64_t(1) << 8)) ? 8 : + (kInput & (uint64_t(1) << 9)) ? 9 : + (kInput & (uint64_t(1) << 10)) ? 10 : + (kInput & (uint64_t(1) << 11)) ? 11 : + (kInput & (uint64_t(1) << 12)) ? 12 : + (kInput & (uint64_t(1) << 13)) ? 13 : + (kInput & (uint64_t(1) << 14)) ? 14 : + (kInput & (uint64_t(1) << 15)) ? 15 : + (kInput & (uint64_t(1) << 16)) ? 16 : + (kInput & (uint64_t(1) << 17)) ? 17 : + (kInput & (uint64_t(1) << 18)) ? 18 : + (kInput & (uint64_t(1) << 19)) ? 19 : + (kInput & (uint64_t(1) << 20)) ? 20 : + (kInput & (uint64_t(1) << 21)) ? 21 : + (kInput & (uint64_t(1) << 22)) ? 22 : + (kInput & (uint64_t(1) << 23)) ? 23 : + (kInput & (uint64_t(1) << 24)) ? 24 : + (kInput & (uint64_t(1) << 25)) ? 25 : + (kInput & (uint64_t(1) << 26)) ? 26 : + (kInput & (uint64_t(1) << 27)) ? 27 : + (kInput & (uint64_t(1) << 28)) ? 28 : + (kInput & (uint64_t(1) << 29)) ? 29 : + (kInput & (uint64_t(1) << 30)) ? 30 : + (kInput & (uint64_t(1) << 31)) ? 31 : + (kInput & (uint64_t(1) << 32)) ? 32 : + (kInput & (uint64_t(1) << 33)) ? 33 : + (kInput & (uint64_t(1) << 34)) ? 34 : + (kInput & (uint64_t(1) << 35)) ? 35 : + (kInput & (uint64_t(1) << 36)) ? 36 : + (kInput & (uint64_t(1) << 37)) ? 37 : + (kInput & (uint64_t(1) << 38)) ? 38 : + (kInput & (uint64_t(1) << 39)) ? 39 : + (kInput & (uint64_t(1) << 40)) ? 40 : + (kInput & (uint64_t(1) << 41)) ? 41 : + (kInput & (uint64_t(1) << 42)) ? 42 : + (kInput & (uint64_t(1) << 43)) ? 43 : + (kInput & (uint64_t(1) << 44)) ? 44 : + (kInput & (uint64_t(1) << 45)) ? 45 : + (kInput & (uint64_t(1) << 46)) ? 46 : + (kInput & (uint64_t(1) << 47)) ? 47 : + (kInput & (uint64_t(1) << 48)) ? 48 : + (kInput & (uint64_t(1) << 49)) ? 49 : + (kInput & (uint64_t(1) << 50)) ? 50 : + (kInput & (uint64_t(1) << 51)) ? 51 : + (kInput & (uint64_t(1) << 52)) ? 52 : + (kInput & (uint64_t(1) << 53)) ? 53 : + (kInput & (uint64_t(1) << 54)) ? 54 : + (kInput & (uint64_t(1) << 55)) ? 55 : + (kInput & (uint64_t(1) << 56)) ? 56 : + (kInput & (uint64_t(1) << 57)) ? 57 : + (kInput & (uint64_t(1) << 58)) ? 58 : + (kInput & (uint64_t(1) << 59)) ? 59 : + (kInput & (uint64_t(1) << 60)) ? 60 : + (kInput & (uint64_t(1) << 61)) ? 61 : + (kInput & (uint64_t(1) << 62)) ? 62 : + (kInput & (uint64_t(1) << 63)) ? 63 : 64; +}; -// ============================================================================ -// [asmjit::Support - PopCnt] -// ============================================================================ +// Support - PopCnt +// ================ // Based on the following resource: // http://graphics.stanford.edu/~seander/bithacks.html @@ -422,9 +467,8 @@ static inline uint32_t popcnt(T x) noexcept { return Internal::popcntImpl(asUInt template<typename T> static inline uint32_t constPopcnt(T x) noexcept { return Internal::constPopcntImpl(asUInt(x)); } -// ============================================================================ -// [asmjit::Support - Min/Max] -// ============================================================================ +// Support - Min/Max +// ================= // NOTE: These are constexpr `min()` and `max()` implementations that are not // exactly the same as `std::min()` and `std::max()`. The return value is not @@ -442,9 +486,8 @@ static constexpr T max(const T& a, const T& b) noexcept { return a < b ? b : a; template<typename T, typename... Args> static constexpr T max(const T& a, const T& b, Args&&... args) noexcept { return max(max(a, b), std::forward<Args>(args)...); } -// ============================================================================ -// [asmjit::Support - Immediate Helpers] -// ============================================================================ +// Support - Immediate Helpers +// =========================== namespace Internal { template<typename T, bool IsFloat> @@ -466,14 +509,13 @@ static inline int64_t immediateFromT(const T& x) noexcept { return Internal::Imm template<typename T> static inline T immediateToT(int64_t x) noexcept { return Internal::ImmConv<T, std::is_floating_point<T>::value>::toT(x); } -// ============================================================================ -// [asmjit::Support - Overflow Arithmetic] -// ============================================================================ +// Support - Overflow Arithmetic +// ============================= //! \cond namespace Internal { template<typename T> - ASMJIT_INLINE T addOverflowFallback(T x, T y, FastUInt8* of) noexcept { + inline T addOverflowFallback(T x, T y, FastUInt8* of) noexcept { typedef typename std::make_unsigned<T>::type U; U result = U(x) + U(y); @@ -482,7 +524,7 @@ namespace Internal { } template<typename T> - ASMJIT_INLINE T subOverflowFallback(T x, T y, FastUInt8* of) noexcept { + inline T subOverflowFallback(T x, T y, FastUInt8* of) noexcept { typedef typename std::make_unsigned<T>::type U; U result = U(x) - U(y); @@ -491,7 +533,7 @@ namespace Internal { } template<typename T> - ASMJIT_INLINE T mulOverflowFallback(T x, T y, FastUInt8* of) noexcept { + inline T mulOverflowFallback(T x, T y, FastUInt8* of) noexcept { typedef typename Internal::StdInt<sizeof(T) * 2, isUnsigned<T>()>::Type I; typedef typename std::make_unsigned<I>::type U; @@ -509,32 +551,32 @@ namespace Internal { } template<> - ASMJIT_INLINE int64_t mulOverflowFallback(int64_t x, int64_t y, FastUInt8* of) noexcept { + inline int64_t mulOverflowFallback(int64_t x, int64_t y, FastUInt8* of) noexcept { int64_t result = int64_t(uint64_t(x) * uint64_t(y)); *of = FastUInt8(*of | FastUInt8(x && (result / x != y))); return result; } template<> - ASMJIT_INLINE uint64_t mulOverflowFallback(uint64_t x, uint64_t y, FastUInt8* of) noexcept { + inline uint64_t mulOverflowFallback(uint64_t x, uint64_t y, FastUInt8* of) noexcept { uint64_t result = x * y; *of = FastUInt8(*of | FastUInt8(y != 0 && allOnes<uint64_t>() / y < x)); return result; } // These can be specialized. - template<typename T> ASMJIT_INLINE T addOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return addOverflowFallback(x, y, of); } - template<typename T> ASMJIT_INLINE T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); } - template<typename T> ASMJIT_INLINE T mulOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return mulOverflowFallback(x, y, of); } + template<typename T> inline T addOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return addOverflowFallback(x, y, of); } + template<typename T> inline T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); } + template<typename T> inline T mulOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return mulOverflowFallback(x, y, of); } #if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) #if defined(__clang__) || __GNUC__ >= 5 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ - template<> \ - ASMJIT_INLINE T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \ - RESULT_T result; \ - *of = FastUInt8(*of | (BUILTIN((RESULT_T)x, (RESULT_T)y, &result))); \ - return T(result); \ + #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ + template<> \ + inline T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \ + RESULT_T result; \ + *of = FastUInt8(*of | (BUILTIN((RESULT_T)x, (RESULT_T)y, &result))); \ + return T(result); \ } ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, int32_t , int , __builtin_sadd_overflow ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , __builtin_uadd_overflow ) @@ -554,12 +596,12 @@ namespace Internal { // There is a bug in MSVC that makes these specializations unusable, maybe in the future... #if defined(_MSC_VER) && 0 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ - template<> \ - ASMJIT_INLINE T FUNC(T x, T y, FastUInt8* of) noexcept { \ - ALT_T result; \ - *of = FastUInt8(*of | BUILTIN(0, (ALT_T)x, (ALT_T)y, &result)); \ - return T(result); \ + #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ + template<> \ + inline T FUNC(T x, T y, FastUInt8* of) noexcept { \ + ALT_T result; \ + *of = FastUInt8(*of | BUILTIN(0, (ALT_T)x, (ALT_T)y, &result)); \ + return T(result); \ } ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , _addcarry_u32 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint32_t, unsigned int , _subborrow_u32) @@ -573,17 +615,16 @@ namespace Internal { //! \endcond template<typename T> -static ASMJIT_INLINE T addOverflow(const T& x, const T& y, FastUInt8* of) noexcept { return T(Internal::addOverflowImpl(asStdInt(x), asStdInt(y), of)); } +static inline T addOverflow(const T& x, const T& y, FastUInt8* of) noexcept { return T(Internal::addOverflowImpl(asStdInt(x), asStdInt(y), of)); } template<typename T> -static ASMJIT_INLINE T subOverflow(const T& x, const T& y, FastUInt8* of) noexcept { return T(Internal::subOverflowImpl(asStdInt(x), asStdInt(y), of)); } +static inline T subOverflow(const T& x, const T& y, FastUInt8* of) noexcept { return T(Internal::subOverflowImpl(asStdInt(x), asStdInt(y), of)); } template<typename T> -static ASMJIT_INLINE T mulOverflow(const T& x, const T& y, FastUInt8* of) noexcept { return T(Internal::mulOverflowImpl(asStdInt(x), asStdInt(y), of)); } +static inline T mulOverflow(const T& x, const T& y, FastUInt8* of) noexcept { return T(Internal::mulOverflowImpl(asStdInt(x), asStdInt(y), of)); } -// ============================================================================ -// [asmjit::Support - Alignment] -// ============================================================================ +// Support - Alignment +// =================== template<typename X, typename Y> static constexpr bool isAligned(X base, Y alignment) noexcept { @@ -624,9 +665,8 @@ static constexpr X alignDown(X x, Y alignment) noexcept { return (X)( (U)x & ~((U)(alignment) - 1u) ); } -// ============================================================================ -// [asmjit::Support - NumGranularized] -// ============================================================================ +// Support - NumGranularized +// ========================= //! Calculates the number of elements that would be required if `base` is //! granularized by `granularity`. This function can be used to calculate @@ -637,9 +677,8 @@ static constexpr X numGranularized(X base, Y granularity) noexcept { return X((U(base) + U(granularity) - 1) / U(granularity)); } -// ============================================================================ -// [asmjit::Support - IsBetween] -// ============================================================================ +// Support - IsBetween +// =================== //! Checks whether `x` is greater than or equal to `a` and lesser than or equal to `b`. template<typename T> @@ -647,9 +686,8 @@ static constexpr bool isBetween(const T& x, const T& a, const T& b) noexcept { return x >= a && x <= b; } -// ============================================================================ -// [asmjit::Support - IsInt / IsUInt] -// ============================================================================ +// Support - IsInt & IsUInt +// ======================== //! Checks whether the given integer `x` can be casted to a 4-bit signed integer. template<typename T> @@ -779,17 +817,15 @@ static bool inline isEncodableOffset64(int64_t offset, uint32_t nBits) noexcept return Support::sar(Support::shl(offset, nRev), nRev) == offset; } -// ============================================================================ -// [asmjit::Support - ByteSwap] -// ============================================================================ +// Support - ByteSwap +// ================== static constexpr uint32_t byteswap32(uint32_t x) noexcept { return (x << 24) | (x >> 24) | ((x << 8) & 0x00FF0000u) | ((x >> 8) & 0x0000FF00); } -// ============================================================================ -// [asmjit::Support - BytePack / Unpack] -// ============================================================================ +// Support - BytePack & Unpack +// =========================== //! Pack four 8-bit integer into a 32-bit integer as it is an array of `{b0,b1,b2,b3}`. static constexpr uint32_t bytepack32_4x8(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { @@ -802,17 +838,15 @@ static constexpr uint32_t unpackU32At0(T x) noexcept { return ASMJIT_ARCH_LE ? u template<typename T> static constexpr uint32_t unpackU32At1(T x) noexcept { return ASMJIT_ARCH_BE ? uint32_t(uint64_t(x) & 0xFFFFFFFFu) : uint32_t(uint64_t(x) >> 32); } -// ============================================================================ -// [asmjit::Support - Position of byte (in bit-shift)] -// ============================================================================ +// Support - Position of byte (in bit-shift) +// ========================================= static inline uint32_t byteShiftOfDWordStruct(uint32_t index) noexcept { return ASMJIT_ARCH_LE ? index * 8 : (uint32_t(sizeof(uint32_t)) - 1u - index) * 8; } -// ============================================================================ -// [asmjit::Support - String Utilities] -// ============================================================================ +// Support - String Utilities +// ========================== template<typename T> static constexpr T asciiToLower(T c) noexcept { return T(c ^ T(T(c >= T('A') && c <= T('Z')) << 5)); } @@ -820,7 +854,7 @@ static constexpr T asciiToLower(T c) noexcept { return T(c ^ T(T(c >= T('A') && template<typename T> static constexpr T asciiToUpper(T c) noexcept { return T(c ^ T(T(c >= T('a') && c <= T('z')) << 5)); } -static ASMJIT_INLINE size_t strLen(const char* s, size_t maxSize) noexcept { +static ASMJIT_FORCE_INLINE size_t strLen(const char* s, size_t maxSize) noexcept { size_t i = 0; while (i < maxSize && s[i] != '\0') i++; @@ -839,7 +873,7 @@ static inline uint32_t hashString(const char* data, size_t size) noexcept { return hashCode; } -static ASMJIT_INLINE const char* findPackedString(const char* p, uint32_t id) noexcept { +static ASMJIT_FORCE_INLINE const char* findPackedString(const char* p, uint32_t id) noexcept { uint32_t i = 0; while (i < id) { while (p[0]) @@ -855,7 +889,7 @@ static ASMJIT_INLINE const char* findPackedString(const char* p, uint32_t id) no //! `a` is a null terminated instruction name from arch-specific `nameData[]` //! table. `b` is a possibly non-null terminated instruction name passed to //! `InstAPI::stringToInstId()`. -static ASMJIT_INLINE int cmpInstName(const char* a, const char* b, size_t size) noexcept { +static ASMJIT_FORCE_INLINE int cmpInstName(const char* a, const char* b, size_t size) noexcept { for (size_t i = 0; i < size; i++) { int c = int(uint8_t(a[i])) - int(uint8_t(b[i])); if (c != 0) return c; @@ -863,14 +897,13 @@ static ASMJIT_INLINE int cmpInstName(const char* a, const char* b, size_t size) return int(uint8_t(a[size])); } -// ============================================================================ -// [asmjit::Support - Read / Write] -// ============================================================================ +// Support - Memory Read & Write +// ============================= static inline uint32_t readU8(const void* p) noexcept { return uint32_t(static_cast<const uint8_t*>(p)[0]); } static inline int32_t readI8(const void* p) noexcept { return int32_t(static_cast<const int8_t*>(p)[0]); } -template<uint32_t BO, size_t Alignment> +template<ByteOrder BO, size_t Alignment> static inline uint32_t readU16x(const void* p) noexcept { if (BO == ByteOrder::kNative && (kUnalignedAccess16 || Alignment >= 2)) { typedef typename Internal::AlignedInt<uint16_t, Alignment>::T U16AlignedToN; @@ -883,7 +916,7 @@ static inline uint32_t readU16x(const void* p) noexcept { } } -template<uint32_t BO, size_t Alignment> +template<ByteOrder BO, size_t Alignment> static inline int32_t readI16x(const void* p) noexcept { if (BO == ByteOrder::kNative && (kUnalignedAccess16 || Alignment >= 2)) { typedef typename Internal::AlignedInt<uint16_t, Alignment>::T U16AlignedToN; @@ -896,7 +929,7 @@ static inline int32_t readI16x(const void* p) noexcept { } } -template<uint32_t BO = ByteOrder::kNative> +template<ByteOrder BO = ByteOrder::kNative> static inline uint32_t readU24u(const void* p) noexcept { uint32_t b0 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 2 : 0)); uint32_t b1 = readU8(static_cast<const uint8_t*>(p) + (BO == ByteOrder::kLE ? 1 : 1)); @@ -904,7 +937,7 @@ static inline uint32_t readU24u(const void* p) noexcept { return shl(b0, 16) | shl(b1, 8) | b2; } -template<uint32_t BO, size_t Alignment> +template<ByteOrder BO, size_t Alignment> static inline uint32_t readU32x(const void* p) noexcept { if (kUnalignedAccess32 || Alignment >= 4) { typedef typename Internal::AlignedInt<uint32_t, Alignment>::T U32AlignedToN; @@ -918,7 +951,7 @@ static inline uint32_t readU32x(const void* p) noexcept { } } -template<uint32_t BO, size_t Alignment> +template<ByteOrder BO, size_t Alignment> static inline uint64_t readU64x(const void* p) noexcept { if (BO == ByteOrder::kNative && (kUnalignedAccess64 || Alignment >= 8)) { typedef typename Internal::AlignedInt<uint64_t, Alignment>::T U64AlignedToN; @@ -931,10 +964,10 @@ static inline uint64_t readU64x(const void* p) noexcept { } } -template<uint32_t BO, size_t Alignment> +template<ByteOrder BO, size_t Alignment> static inline int32_t readI32x(const void* p) noexcept { return int32_t(readU32x<BO, Alignment>(p)); } -template<uint32_t BO, size_t Alignment> +template<ByteOrder BO, size_t Alignment> static inline int64_t readI64x(const void* p) noexcept { return int64_t(readU64x<BO, Alignment>(p)); } template<size_t Alignment> static inline int32_t readI16xLE(const void* p) noexcept { return readI16x<ByteOrder::kLE, Alignment>(p); } @@ -1001,7 +1034,7 @@ static inline uint64_t readU64uBE(const void* p) noexcept { return readU64xBE<1> static inline void writeU8(void* p, uint32_t x) noexcept { static_cast<uint8_t*>(p)[0] = uint8_t(x & 0xFFu); } static inline void writeI8(void* p, int32_t x) noexcept { static_cast<uint8_t*>(p)[0] = uint8_t(x & 0xFF); } -template<uint32_t BO = ByteOrder::kNative, size_t Alignment = 1> +template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeU16x(void* p, uint32_t x) noexcept { if (BO == ByteOrder::kNative && (kUnalignedAccess16 || Alignment >= 2)) { typedef typename Internal::AlignedInt<uint16_t, Alignment>::T U16AlignedToN; @@ -1013,14 +1046,14 @@ static inline void writeU16x(void* p, uint32_t x) noexcept { } } -template<uint32_t BO = ByteOrder::kNative> +template<ByteOrder BO = ByteOrder::kNative> static inline void writeU24u(void* p, uint32_t v) noexcept { static_cast<uint8_t*>(p)[0] = uint8_t((v >> (BO == ByteOrder::kLE ? 0 : 16)) & 0xFFu); static_cast<uint8_t*>(p)[1] = uint8_t((v >> (BO == ByteOrder::kLE ? 8 : 8)) & 0xFFu); static_cast<uint8_t*>(p)[2] = uint8_t((v >> (BO == ByteOrder::kLE ? 16 : 0)) & 0xFFu); } -template<uint32_t BO = ByteOrder::kNative, size_t Alignment = 1> +template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeU32x(void* p, uint32_t x) noexcept { if (kUnalignedAccess32 || Alignment >= 4) { typedef typename Internal::AlignedInt<uint32_t, Alignment>::T U32AlignedToN; @@ -1032,7 +1065,7 @@ static inline void writeU32x(void* p, uint32_t x) noexcept { } } -template<uint32_t BO = ByteOrder::kNative, size_t Alignment = 1> +template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeU64x(void* p, uint64_t x) noexcept { if (BO == ByteOrder::kNative && (kUnalignedAccess64 || Alignment >= 8)) { typedef typename Internal::AlignedInt<uint64_t, Alignment>::T U64AlignedToN; @@ -1044,9 +1077,9 @@ static inline void writeU64x(void* p, uint64_t x) noexcept { } } -template<uint32_t BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeI16x(void* p, int32_t x) noexcept { writeU16x<BO, Alignment>(p, uint32_t(x)); } -template<uint32_t BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeI32x(void* p, int32_t x) noexcept { writeU32x<BO, Alignment>(p, uint32_t(x)); } -template<uint32_t BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeI64x(void* p, int64_t x) noexcept { writeU64x<BO, Alignment>(p, uint64_t(x)); } +template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeI16x(void* p, int32_t x) noexcept { writeU16x<BO, Alignment>(p, uint32_t(x)); } +template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeI32x(void* p, int32_t x) noexcept { writeU32x<BO, Alignment>(p, uint32_t(x)); } +template<ByteOrder BO = ByteOrder::kNative, size_t Alignment = 1> static inline void writeI64x(void* p, int64_t x) noexcept { writeU64x<BO, Alignment>(p, uint64_t(x)); } template<size_t Alignment = 1> static inline void writeI16xLE(void* p, int32_t x) noexcept { writeI16x<ByteOrder::kLE, Alignment>(p, x); } template<size_t Alignment = 1> static inline void writeI16xBE(void* p, int32_t x) noexcept { writeI16x<ByteOrder::kBE, Alignment>(p, x); } @@ -1111,9 +1144,8 @@ static inline void writeI64uBE(void* p, int64_t x) noexcept { writeI64xBE<1>(p, static inline void writeU64aBE(void* p, uint64_t x) noexcept { writeU64xBE<8>(p, x); } static inline void writeU64uBE(void* p, uint64_t x) noexcept { writeU64xBE<1>(p, x); } -// ============================================================================ -// [asmjit::Support - Operators] -// ============================================================================ +// Support - Operators +// =================== //! \cond INTERNAL struct Set { template<typename T> static inline T op(T x, T y) noexcept { DebugUtils::unused(x); return y; } }; @@ -1129,9 +1161,8 @@ struct Min { template<typename T> static inline T op(T x, T y) noexcept { ret struct Max { template<typename T> static inline T op(T x, T y) noexcept { return max<T>(x, y); } }; //! \endcond -// ============================================================================ -// [asmjit::Support - BitWordIterator] -// ============================================================================ +// Support - BitWordIterator +// ========================= //! Iterates over each bit in a number which is set to 1. //! @@ -1149,13 +1180,13 @@ struct Max { template<typename T> static inline T op(T x, T y) noexcept { ret template<typename T> class BitWordIterator { public: - inline explicit BitWordIterator(T bitWord) noexcept + ASMJIT_FORCE_INLINE explicit BitWordIterator(T bitWord) noexcept : _bitWord(bitWord) {} - inline void init(T bitWord) noexcept { _bitWord = bitWord; } - inline bool hasNext() const noexcept { return _bitWord != 0; } + ASMJIT_FORCE_INLINE void init(T bitWord) noexcept { _bitWord = bitWord; } + ASMJIT_FORCE_INLINE bool hasNext() const noexcept { return _bitWord != 0; } - inline uint32_t next() noexcept { + ASMJIT_FORCE_INLINE uint32_t next() noexcept { ASMJIT_ASSERT(_bitWord != 0); uint32_t index = ctz(_bitWord); _bitWord ^= T(1u) << index; @@ -1165,20 +1196,19 @@ public: T _bitWord; }; -// ============================================================================ -// [asmjit::Support - BitWordFlipIterator] -// ============================================================================ +// Support - BitWordFlipIterator +// ============================= template<typename T> class BitWordFlipIterator { public: - inline explicit BitWordFlipIterator(T bitWord) noexcept + ASMJIT_FORCE_INLINE explicit BitWordFlipIterator(T bitWord) noexcept : _bitWord(bitWord) {} - inline void init(T bitWord) noexcept { _bitWord = bitWord; } - inline bool hasNext() const noexcept { return _bitWord != 0; } + ASMJIT_FORCE_INLINE void init(T bitWord) noexcept { _bitWord = bitWord; } + ASMJIT_FORCE_INLINE bool hasNext() const noexcept { return _bitWord != 0; } - inline uint32_t nextAndFlip() noexcept { + ASMJIT_FORCE_INLINE uint32_t nextAndFlip() noexcept { ASMJIT_ASSERT(_bitWord != 0); uint32_t index = ctz(_bitWord); _bitWord ^= T(1u) << index; @@ -1189,9 +1219,8 @@ public: T _xorMask; }; -// ============================================================================ -// [asmjit::Support - BitVectorOps] -// ============================================================================ +// Support - BitVectorOps +// ====================== //! \cond namespace Internal { @@ -1295,9 +1324,8 @@ static inline size_t bitVectorIndexOf(T* buf, size_t start, bool value) noexcept } } -// ============================================================================ -// [asmjit::Support - BitVectorIterator] -// ============================================================================ +// Support - BitVectorIterator +// =========================== template<typename T> class BitVectorIterator { @@ -1307,13 +1335,13 @@ public: size_t _end; T _current; - ASMJIT_INLINE BitVectorIterator(const BitVectorIterator& other) noexcept = default; + ASMJIT_FORCE_INLINE BitVectorIterator(const BitVectorIterator& other) noexcept = default; - ASMJIT_INLINE BitVectorIterator(const T* data, size_t numBitWords, size_t start = 0) noexcept { + ASMJIT_FORCE_INLINE BitVectorIterator(const T* data, size_t numBitWords, size_t start = 0) noexcept { init(data, numBitWords, start); } - ASMJIT_INLINE void init(const T* data, size_t numBitWords, size_t start = 0) noexcept { + ASMJIT_FORCE_INLINE void init(const T* data, size_t numBitWords, size_t start = 0) noexcept { const T* ptr = data + (start / bitSizeOf<T>()); size_t idx = alignDown(start, bitSizeOf<T>()); size_t end = numBitWords * bitSizeOf<T>(); @@ -1331,11 +1359,11 @@ public: _current = bitWord; } - ASMJIT_INLINE bool hasNext() const noexcept { + ASMJIT_FORCE_INLINE bool hasNext() const noexcept { return _current != T(0); } - ASMJIT_INLINE size_t next() noexcept { + ASMJIT_FORCE_INLINE size_t next() noexcept { T bitWord = _current; ASMJIT_ASSERT(bitWord != T(0)); @@ -1350,20 +1378,21 @@ public: return n; } - ASMJIT_INLINE size_t peekNext() const noexcept { + ASMJIT_FORCE_INLINE size_t peekNext() const noexcept { ASMJIT_ASSERT(_current != T(0)); return _idx + ctz(_current); } }; -// ============================================================================ -// [asmjit::Support - BitVectorOpIterator] -// ============================================================================ +// Support - BitVectorOpIterator +// ============================= template<typename T, class OperatorT> class BitVectorOpIterator { public: - static constexpr uint32_t kTSizeInBits = bitSizeOf<T>(); + enum : uint32_t { + kTSizeInBits = bitSizeOf<T>() + }; const T* _aPtr; const T* _bPtr; @@ -1371,11 +1400,11 @@ public: size_t _end; T _current; - ASMJIT_INLINE BitVectorOpIterator(const T* aData, const T* bData, size_t numBitWords, size_t start = 0) noexcept { + ASMJIT_FORCE_INLINE BitVectorOpIterator(const T* aData, const T* bData, size_t numBitWords, size_t start = 0) noexcept { init(aData, bData, numBitWords, start); } - ASMJIT_INLINE void init(const T* aData, const T* bData, size_t numBitWords, size_t start = 0) noexcept { + ASMJIT_FORCE_INLINE void init(const T* aData, const T* bData, size_t numBitWords, size_t start = 0) noexcept { const T* aPtr = aData + (start / bitSizeOf<T>()); const T* bPtr = bData + (start / bitSizeOf<T>()); size_t idx = alignDown(start, bitSizeOf<T>()); @@ -1395,11 +1424,11 @@ public: _current = bitWord; } - ASMJIT_INLINE bool hasNext() noexcept { + ASMJIT_FORCE_INLINE bool hasNext() noexcept { return _current != T(0); } - ASMJIT_INLINE size_t next() noexcept { + ASMJIT_FORCE_INLINE size_t next() noexcept { T bitWord = _current; ASMJIT_ASSERT(bitWord != T(0)); @@ -1415,29 +1444,29 @@ public: } }; -// ============================================================================ -// [asmjit::Support - Sorting] -// ============================================================================ +// Support - Sorting +// ================= //! Sort order. -enum SortOrder : uint32_t { - kSortAscending = 0, //!< Ascending. - kSortDescending = 1 //!< Descending. +enum class SortOrder : uint32_t { + //!< Ascending order. + kAscending = 0, + //!< Descending order. + kDescending = 1 }; //! A helper class that provides comparison of any user-defined type that //! implements `<` and `>` operators (primitive types are supported as well). -template<uint32_t Order = kSortAscending> +template<SortOrder kOrder = SortOrder::kAscending> struct Compare { template<typename A, typename B> inline int operator()(const A& a, const B& b) const noexcept { - return Order == kSortAscending ? int(a > b) - int(a < b) - : int(a < b) - int(a > b); + return kOrder == SortOrder::kAscending ? int(a > b) - int(a < b) : int(a < b) - int(a > b); } }; //! Insertion sort. -template<typename T, typename CompareT = Compare<kSortAscending>> +template<typename T, typename CompareT = Compare<SortOrder::kAscending>> static inline void iSort(T* base, size_t size, const CompareT& cmp = CompareT()) noexcept { for (T* pm = base + 1; pm < base + size; pm++) for (T* pl = pm; pl > base && cmp(pl[-1], pl[0]) > 0; pl--) @@ -1449,8 +1478,10 @@ namespace Internal { //! Quick-sort implementation. template<typename T, class CompareT> struct QSortImpl { - static constexpr size_t kStackSize = 64 * 2; - static constexpr size_t kISortThreshold = 7; + enum : size_t { + kStackSize = 64 * 2, + kISortThreshold = 7 + }; // Based on "PDCLib - Public Domain C Library" and rewritten to C++. static void sort(T* base, size_t size, const CompareT& cmp) noexcept { @@ -1515,31 +1546,162 @@ namespace Internal { //! Quick sort implementation. //! -//! The main reason to provide a custom qsort implementation is that we needed -//! something that will never throw `bad_alloc` exception. This implementation -//! doesn't use dynamic memory allocation. -template<typename T, class CompareT = Compare<kSortAscending>> +//! The main reason to provide a custom qsort implementation is that we needed something that will +//! never throw `bad_alloc` exception. This implementation doesn't use dynamic memory allocation. +template<typename T, class CompareT = Compare<SortOrder::kAscending>> static inline void qSort(T* base, size_t size, const CompareT& cmp = CompareT()) noexcept { Internal::QSortImpl<T, CompareT>::sort(base, size, cmp); } -// ============================================================================ -// [asmjit::Support::Temporary] -// ============================================================================ +// Support - Array +// =============== + +//! Array type, similar to std::array<T, N>, with the possibility to use enums in operator[]. +//! +//! \note The array has C semantics - the elements in the array are not initialized. +template<typename T, size_t N> +struct Array { + //! \name Members + //! \{ + + //! The underlying array data, use \ref data() to access it. + T _data[N]; + + //! \} + + //! \cond + // std compatibility. + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef value_type* pointer; + typedef const value_type* const_pointer; + + typedef pointer iterator; + typedef const_pointer const_iterator; + //! \endcond + + //! \name Overloaded Operators + //! \{ + + template<typename Index> + inline T& operator[](const Index& index) noexcept { + typedef typename Internal::StdInt<sizeof(Index), 1>::Type U; + ASMJIT_ASSERT(U(index) < N); + return _data[U(index)]; + } + + template<typename Index> + inline const T& operator[](const Index& index) const noexcept { + typedef typename Internal::StdInt<sizeof(Index), 1>::Type U; + ASMJIT_ASSERT(U(index) < N); + return _data[U(index)]; + } + + inline bool operator==(const Array& other) const noexcept { + for (size_t i = 0; i < N; i++) + if (_data[i] != other._data[i]) + return false; + return true; + } + + inline bool operator!=(const Array& other) const noexcept { + return !operator==(other); + } + + //! \} + + //! \name Accessors + //! \{ + + inline bool empty() const noexcept { return false; } + inline size_t size() const noexcept { return N; } + + inline T* data() noexcept { return _data; } + inline const T* data() const noexcept { return _data; } + + inline T& front() noexcept { return _data[0]; } + inline const T& front() const noexcept { return _data[0]; } + + inline T& back() noexcept { return _data[N - 1]; } + inline const T& back() const noexcept { return _data[N - 1]; } + + inline T* begin() noexcept { return _data; } + inline T* end() noexcept { return _data + N; } + + inline const T* begin() const noexcept { return _data; } + inline const T* end() const noexcept { return _data + N; } + + inline const T* cbegin() const noexcept { return _data; } + inline const T* cend() const noexcept { return _data + N; } + + //! \} + + //! \name Utilities + //! \{ + + inline void swap(Array& other) noexcept { + for (size_t i = 0; i < N; i++) + std::swap(_data[i], other._data[i]); + } + + inline void fill(const T& value) noexcept { + for (size_t i = 0; i < N; i++) + _data[i] = value; + } + + inline void copyFrom(const Array& other) noexcept { + for (size_t i = 0; i < N; i++) + _data[i] = other._data[i]; + } + + template<typename Operator> + inline void combine(const Array& other) noexcept { + for (size_t i = 0; i < N; i++) + _data[i] = Operator::op(_data[i], other._data[i]); + } + + template<typename Operator> + inline T aggregate(T initialValue = T()) const noexcept { + T value = initialValue; + for (size_t i = 0; i < N; i++) + value = Operator::op(value, _data[i]); + return value; + } + + template<typename Fn> + inline void forEach(Fn&& fn) noexcept { + for (size_t i = 0; i < N; i++) + fn(_data[i]); + } + //! \} +}; + +// Support::Temporary +// ================== //! Used to pass a temporary buffer to: //! //! - Containers that use user-passed buffer as an initial storage (still can grow). //! - Zone allocator that would use the temporary buffer as a first block. struct Temporary { + //! \name Members + //! \{ + void* _data; size_t _size; + //! \} + //! \name Construction & Destruction //! \{ - constexpr Temporary(const Temporary& other) noexcept = default; - constexpr Temporary(void* data, size_t size) noexcept + inline constexpr Temporary(const Temporary& other) noexcept = default; + inline constexpr Temporary(void* data, size_t size) noexcept : _data(data), _size(size) {} @@ -1557,9 +1719,9 @@ struct Temporary { //! Returns the data storage. template<typename T = void> - constexpr T* data() const noexcept { return static_cast<T*>(_data); } + inline constexpr T* data() const noexcept { return static_cast<T*>(_data); } //! Returns the data storage size in bytes. - constexpr size_t size() const noexcept { return _size; } + inline constexpr size_t size() const noexcept { return _size; } //! \} }; diff --git a/src/asmjit/core/target.cpp b/src/asmjit/core/target.cpp index 9ce94f3..fef025d 100644 --- a/src/asmjit/core/target.cpp +++ b/src/asmjit/core/target.cpp @@ -1,37 +1,14 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/target.h" ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Target - Construction / Destruction] -// ============================================================================ - -Target::Target() noexcept - : _environment() {} +Target::Target() noexcept : _environment() {} Target::~Target() noexcept {} ASMJIT_END_NAMESPACE diff --git a/src/asmjit/core/target.h b/src/asmjit/core/target.h index f2045c0..23b0c62 100644 --- a/src/asmjit/core/target.h +++ b/src/asmjit/core/target.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_TARGET_H_INCLUDED #define ASMJIT_CORE_TARGET_H_INCLUDED @@ -32,98 +14,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::CodeInfo] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED -//! Basic information about a code (or target). It describes its architecture, -//! code generation mode (or optimization level), and base address. -class ASMJIT_DEPRECATED_STRUCT("Use Environment instead of CodeInfo") CodeInfo { -public: - //!< Environment information. - Environment _environment; - //! Base address. - uint64_t _baseAddress; - - //! \name Construction & Destruction - //! \{ - - inline CodeInfo() noexcept - : _environment(), - _baseAddress(Globals::kNoBaseAddress) {} - - inline explicit CodeInfo(uint32_t arch, uint32_t subArch = 0, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept - : _environment(arch, subArch), - _baseAddress(baseAddress) {} - - inline explicit CodeInfo(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept - : _environment(environment), - _baseAddress(baseAddress) {} - - - inline CodeInfo(const CodeInfo& other) noexcept { init(other); } - - inline bool isInitialized() const noexcept { - return _environment.arch() != Environment::kArchUnknown; - } - - inline void init(const CodeInfo& other) noexcept { - *this = other; - } - - inline void init(uint32_t arch, uint32_t subArch = 0, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept { - _environment.init(arch, subArch); - _baseAddress = baseAddress; - } - - inline void reset() noexcept { - _environment.reset(); - _baseAddress = Globals::kNoBaseAddress; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline CodeInfo& operator=(const CodeInfo& other) noexcept = default; - - inline bool operator==(const CodeInfo& other) const noexcept { return ::memcmp(this, &other, sizeof(*this)) == 0; } - inline bool operator!=(const CodeInfo& other) const noexcept { return ::memcmp(this, &other, sizeof(*this)) != 0; } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the target environment information, see \ref Environment. - inline const Environment& environment() const noexcept { return _environment; } - - //! Returns the target architecture, see \ref Environment::Arch. - inline uint32_t arch() const noexcept { return _environment.arch(); } - //! Returns the target sub-architecture, see \ref Environment::SubArch. - inline uint32_t subArch() const noexcept { return _environment.subArch(); } - //! Returns the native size of the target's architecture GP register. - inline uint32_t gpSize() const noexcept { return _environment.registerSize(); } - - //! Tests whether this CodeInfo has a base address set. - inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } - //! Returns the base address or \ref Globals::kNoBaseAddress if it's not set. - inline uint64_t baseAddress() const noexcept { return _baseAddress; } - //! Sets base address to `p`. - inline void setBaseAddress(uint64_t p) noexcept { _baseAddress = p; } - //! Resets base address (implicitly sets it to \ref Globals::kNoBaseAddress). - inline void resetBaseAddress() noexcept { _baseAddress = Globals::kNoBaseAddress; } - - //! \} -}; -#endif // !ASMJIT_NO_DEPRECATED - -// ============================================================================ -// [asmjit::Target] -// ============================================================================ - //! Target is an abstract class that describes a machine code target. class ASMJIT_VIRTAPI Target { public: @@ -146,24 +36,12 @@ public: //! \name Accessors //! \{ - //! Returns CodeInfo of this target. - //! - //! CodeInfo can be used to setup a CodeHolder in case you plan to generate a - //! code compatible and executable by this Runtime. + //! Returns target's environment. inline const Environment& environment() const noexcept { return _environment; } - - //! Returns the target architecture, see \ref Environment::Arch. - inline uint32_t arch() const noexcept { return _environment.arch(); } - //! Returns the target sub-architecture, see \ref Environment::SubArch. - inline uint32_t subArch() const noexcept { return _environment.subArch(); } - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use environment() instead") - inline CodeInfo codeInfo() const noexcept { return CodeInfo(_environment); } - - ASMJIT_DEPRECATED("Use environment().format() instead") - inline uint32_t targetType() const noexcept { return _environment.format(); } -#endif // !ASMJIT_NO_DEPRECATED + //! Returns the target architecture. + inline Arch arch() const noexcept { return _environment.arch(); } + //! Returns the target sub-architecture. + inline SubArch subArch() const noexcept { return _environment.subArch(); } //! \} }; diff --git a/src/asmjit/core/type.cpp b/src/asmjit/core/type.cpp index a2bebf4..536fb88 100644 --- a/src/asmjit/core/type.cpp +++ b/src/asmjit/core/type.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/misc_p.h" @@ -27,58 +9,58 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Type] -// ============================================================================ - -namespace Type { +namespace TypeUtils { -template<uint32_t TYPE_ID> -struct BaseOfTypeId { - static constexpr uint32_t kTypeId = - isBase (TYPE_ID) ? TYPE_ID : - isMask8 (TYPE_ID) ? kIdU8 : - isMask16(TYPE_ID) ? kIdU16 : - isMask32(TYPE_ID) ? kIdU32 : - isMask64(TYPE_ID) ? kIdU64 : - isMmx32 (TYPE_ID) ? kIdI32 : - isMmx64 (TYPE_ID) ? kIdI64 : - isVec32 (TYPE_ID) ? TYPE_ID + kIdI8 - _kIdVec32Start : - isVec64 (TYPE_ID) ? TYPE_ID + kIdI8 - _kIdVec64Start : - isVec128(TYPE_ID) ? TYPE_ID + kIdI8 - _kIdVec128Start : - isVec256(TYPE_ID) ? TYPE_ID + kIdI8 - _kIdVec256Start : - isVec512(TYPE_ID) ? TYPE_ID + kIdI8 - _kIdVec512Start : 0; +template<uint32_t Index> +struct ScalarOfTypeId { + enum : uint32_t { + kTypeId = uint32_t( + isScalar(TypeId(Index)) ? TypeId(Index) : + isMask8 (TypeId(Index)) ? TypeId::kUInt8 : + isMask16(TypeId(Index)) ? TypeId::kUInt16 : + isMask32(TypeId(Index)) ? TypeId::kUInt32 : + isMask64(TypeId(Index)) ? TypeId::kUInt64 : + isMmx32 (TypeId(Index)) ? TypeId::kUInt32 : + isMmx64 (TypeId(Index)) ? TypeId::kUInt64 : + isVec32 (TypeId(Index)) ? TypeId((Index - uint32_t(TypeId::_kVec32Start ) + uint32_t(TypeId::kInt8)) & 0xFF) : + isVec64 (TypeId(Index)) ? TypeId((Index - uint32_t(TypeId::_kVec64Start ) + uint32_t(TypeId::kInt8)) & 0xFF) : + isVec128(TypeId(Index)) ? TypeId((Index - uint32_t(TypeId::_kVec128Start) + uint32_t(TypeId::kInt8)) & 0xFF) : + isVec256(TypeId(Index)) ? TypeId((Index - uint32_t(TypeId::_kVec256Start) + uint32_t(TypeId::kInt8)) & 0xFF) : + isVec512(TypeId(Index)) ? TypeId((Index - uint32_t(TypeId::_kVec512Start) + uint32_t(TypeId::kInt8)) & 0xFF) : TypeId::kVoid) + }; }; -template<uint32_t TYPE_ID> +template<uint32_t Index> struct SizeOfTypeId { - static constexpr uint32_t kTypeSize = - isInt8 (TYPE_ID) ? 1 : - isUInt8 (TYPE_ID) ? 1 : - isInt16 (TYPE_ID) ? 2 : - isUInt16 (TYPE_ID) ? 2 : - isInt32 (TYPE_ID) ? 4 : - isUInt32 (TYPE_ID) ? 4 : - isInt64 (TYPE_ID) ? 8 : - isUInt64 (TYPE_ID) ? 8 : - isFloat32(TYPE_ID) ? 4 : - isFloat64(TYPE_ID) ? 8 : - isFloat80(TYPE_ID) ? 10 : - isMask8 (TYPE_ID) ? 1 : - isMask16 (TYPE_ID) ? 2 : - isMask32 (TYPE_ID) ? 4 : - isMask64 (TYPE_ID) ? 8 : - isMmx32 (TYPE_ID) ? 4 : - isMmx64 (TYPE_ID) ? 8 : - isVec32 (TYPE_ID) ? 4 : - isVec64 (TYPE_ID) ? 8 : - isVec128 (TYPE_ID) ? 16 : - isVec256 (TYPE_ID) ? 32 : - isVec512 (TYPE_ID) ? 64 : 0; + enum : uint32_t { + kTypeSize = + isInt8 (TypeId(Index)) ? 1 : + isUInt8 (TypeId(Index)) ? 1 : + isInt16 (TypeId(Index)) ? 2 : + isUInt16 (TypeId(Index)) ? 2 : + isInt32 (TypeId(Index)) ? 4 : + isUInt32 (TypeId(Index)) ? 4 : + isInt64 (TypeId(Index)) ? 8 : + isUInt64 (TypeId(Index)) ? 8 : + isFloat32(TypeId(Index)) ? 4 : + isFloat64(TypeId(Index)) ? 8 : + isFloat80(TypeId(Index)) ? 10 : + isMask8 (TypeId(Index)) ? 1 : + isMask16 (TypeId(Index)) ? 2 : + isMask32 (TypeId(Index)) ? 4 : + isMask64 (TypeId(Index)) ? 8 : + isMmx32 (TypeId(Index)) ? 4 : + isMmx64 (TypeId(Index)) ? 8 : + isVec32 (TypeId(Index)) ? 4 : + isVec64 (TypeId(Index)) ? 8 : + isVec128 (TypeId(Index)) ? 16 : + isVec256 (TypeId(Index)) ? 32 : + isVec512 (TypeId(Index)) ? 64 : 0 + }; }; const TypeData _typeData = { - #define VALUE(x) BaseOfTypeId<x>::kTypeId + #define VALUE(x) TypeId(ScalarOfTypeId<x>::kTypeId) { ASMJIT_LOOKUP_TABLE_256(VALUE, 0) }, #undef VALUE @@ -87,6 +69,6 @@ const TypeData _typeData = { #undef VALUE }; -} // {Type} +} // {TypeUtils} ASMJIT_END_NAMESPACE diff --git a/src/asmjit/core/type.h b/src/asmjit/core/type.h index ef03ecb..3754959 100644 --- a/src/asmjit/core/type.h +++ b/src/asmjit/core/type.h @@ -1,210 +1,237 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_TYPE_H_INCLUDED #define ASMJIT_CORE_TYPE_H_INCLUDED #include "../core/globals.h" +#include "../core/support.h" ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_core //! \{ -// ============================================================================ -// [asmjit::Type] -// ============================================================================ - -//! Provides a minimalist type-system that is used by Asmjit library. -namespace Type { - -//! TypeId. +//! Type identifier provides a minimalist type system used across AsmJit library. //! -//! This is an additional information that can be used to describe a value-type -//! of physical or virtual register. it's used mostly by BaseCompiler to describe -//! register representation (the group of data stored in the register and the -//! width used) and it's also used by APIs that allow to describe and work with -//! function signatures. -enum Id : uint32_t { - kIdVoid = 0, //!< Void type. - - _kIdBaseStart = 32, - _kIdBaseEnd = 44, - - _kIdIntStart = 32, - _kIdIntEnd = 41, - - kIdIntPtr = 32, //!< Abstract signed integer type that has a native size. - kIdUIntPtr = 33, //!< Abstract unsigned integer type that has a native size. - - kIdI8 = 34, //!< 8-bit signed integer type. - kIdU8 = 35, //!< 8-bit unsigned integer type. - kIdI16 = 36, //!< 16-bit signed integer type. - kIdU16 = 37, //!< 16-bit unsigned integer type. - kIdI32 = 38, //!< 32-bit signed integer type. - kIdU32 = 39, //!< 32-bit unsigned integer type. - kIdI64 = 40, //!< 64-bit signed integer type. - kIdU64 = 41, //!< 64-bit unsigned integer type. - - _kIdFloatStart = 42, - _kIdFloatEnd = 44, - - kIdF32 = 42, //!< 32-bit floating point type. - kIdF64 = 43, //!< 64-bit floating point type. - kIdF80 = 44, //!< 80-bit floating point type. - - _kIdMaskStart = 45, - _kIdMaskEnd = 48, - - kIdMask8 = 45, //!< 8-bit opmask register (K). - kIdMask16 = 46, //!< 16-bit opmask register (K). - kIdMask32 = 47, //!< 32-bit opmask register (K). - kIdMask64 = 48, //!< 64-bit opmask register (K). - - _kIdMmxStart = 49, - _kIdMmxEnd = 50, - - kIdMmx32 = 49, //!< 64-bit MMX register only used for 32 bits. - kIdMmx64 = 50, //!< 64-bit MMX register. - - _kIdVec32Start = 51, - _kIdVec32End = 60, - - kIdI8x4 = 51, - kIdU8x4 = 52, - kIdI16x2 = 53, - kIdU16x2 = 54, - kIdI32x1 = 55, - kIdU32x1 = 56, - kIdF32x1 = 59, - - _kIdVec64Start = 61, - _kIdVec64End = 70, - - kIdI8x8 = 61, - kIdU8x8 = 62, - kIdI16x4 = 63, - kIdU16x4 = 64, - kIdI32x2 = 65, - kIdU32x2 = 66, - kIdI64x1 = 67, - kIdU64x1 = 68, - kIdF32x2 = 69, - kIdF64x1 = 70, - - _kIdVec128Start = 71, - _kIdVec128End = 80, - - kIdI8x16 = 71, - kIdU8x16 = 72, - kIdI16x8 = 73, - kIdU16x8 = 74, - kIdI32x4 = 75, - kIdU32x4 = 76, - kIdI64x2 = 77, - kIdU64x2 = 78, - kIdF32x4 = 79, - kIdF64x2 = 80, - - _kIdVec256Start = 81, - _kIdVec256End = 90, - - kIdI8x32 = 81, - kIdU8x32 = 82, - kIdI16x16 = 83, - kIdU16x16 = 84, - kIdI32x8 = 85, - kIdU32x8 = 86, - kIdI64x4 = 87, - kIdU64x4 = 88, - kIdF32x8 = 89, - kIdF64x4 = 90, - - _kIdVec512Start = 91, - _kIdVec512End = 100, - - kIdI8x64 = 91, - kIdU8x64 = 92, - kIdI16x32 = 93, - kIdU16x32 = 94, - kIdI32x16 = 95, - kIdU32x16 = 96, - kIdI64x8 = 97, - kIdU64x8 = 98, - kIdF32x16 = 99, - kIdF64x8 = 100, - - kIdCount = 101, - kIdMax = 255 +//! This is an additional information that can be used to describe a value-type of physical or virtual register. It's +//! used mostly by BaseCompiler to describe register representation (the group of data stored in the register and the +//! width used) and it's also used by APIs that allow to describe and work with function signatures. +enum class TypeId : uint8_t { + //! Void type. + kVoid = 0, + + _kBaseStart = 32, + _kBaseEnd = 44, + + _kIntStart = 32, + _kIntEnd = 41, + + //! Abstract signed integer type that has a native size. + kIntPtr = 32, + //! Abstract unsigned integer type that has a native size. + kUIntPtr = 33, + + //! 8-bit signed integer type. + kInt8 = 34, + //! 8-bit unsigned integer type. + kUInt8 = 35, + //! 16-bit signed integer type. + kInt16 = 36, + //! 16-bit unsigned integer type. + kUInt16 = 37, + //! 32-bit signed integer type. + kInt32 = 38, + //! 32-bit unsigned integer type. + kUInt32 = 39, + //! 64-bit signed integer type. + kInt64 = 40, + //! 64-bit unsigned integer type. + kUInt64 = 41, + + _kFloatStart = 42, + _kFloatEnd = 44, + + //! 32-bit floating point type. + kFloat32 = 42, + //! 64-bit floating point type. + kFloat64 = 43, + //! 80-bit floating point type. + kFloat80 = 44, + + _kMaskStart = 45, + _kMaskEnd = 48, + + //! 8-bit opmask register (K). + kMask8 = 45, + //! 16-bit opmask register (K). + kMask16 = 46, + //! 32-bit opmask register (K). + kMask32 = 47, + //! 64-bit opmask register (K). + kMask64 = 48, + + _kMmxStart = 49, + _kMmxEnd = 50, + + //! 64-bit MMX register only used for 32 bits. + kMmx32 = 49, + //! 64-bit MMX register. + kMmx64 = 50, + + _kVec32Start = 51, + _kVec32End = 60, + + kInt8x4 = 51, + kUInt8x4 = 52, + kInt16x2 = 53, + kUInt16x2 = 54, + kInt32x1 = 55, + kUInt32x1 = 56, + kFloat32x1 = 59, + + _kVec64Start = 61, + _kVec64End = 70, + + kInt8x8 = 61, + kUInt8x8 = 62, + kInt16x4 = 63, + kUInt16x4 = 64, + kInt32x2 = 65, + kUInt32x2 = 66, + kInt64x1 = 67, + kUInt64x1 = 68, + kFloat32x2 = 69, + kFloat64x1 = 70, + + _kVec128Start = 71, + _kVec128End = 80, + + kInt8x16 = 71, + kUInt8x16 = 72, + kInt16x8 = 73, + kUInt16x8 = 74, + kInt32x4 = 75, + kUInt32x4 = 76, + kInt64x2 = 77, + kUInt64x2 = 78, + kFloat32x4 = 79, + kFloat64x2 = 80, + + _kVec256Start = 81, + _kVec256End = 90, + + kInt8x32 = 81, + kUInt8x32 = 82, + kInt16x16 = 83, + kUInt16x16 = 84, + kInt32x8 = 85, + kUInt32x8 = 86, + kInt64x4 = 87, + kUInt64x4 = 88, + kFloat32x8 = 89, + kFloat64x4 = 90, + + _kVec512Start = 91, + _kVec512End = 100, + + kInt8x64 = 91, + kUInt8x64 = 92, + kInt16x32 = 93, + kUInt16x32 = 94, + kInt32x16 = 95, + kUInt32x16 = 96, + kInt64x8 = 97, + kUInt64x8 = 98, + kFloat32x16 = 99, + kFloat64x8 = 100, + + kLastAssigned = kFloat64x8, + + kMaxValue = 255 }; +ASMJIT_DEFINE_ENUM_COMPARE(TypeId) + +//! Type identifier utilities. +namespace TypeUtils { struct TypeData { - uint8_t baseOf[kIdMax + 1]; - uint8_t sizeOf[kIdMax + 1]; + TypeId scalarOf[uint32_t(TypeId::kMaxValue) + 1]; + uint8_t sizeOf[uint32_t(TypeId::kMaxValue) + 1]; }; ASMJIT_VARAPI const TypeData _typeData; -static constexpr bool isVoid(uint32_t typeId) noexcept { return typeId == 0; } -static constexpr bool isValid(uint32_t typeId) noexcept { return typeId >= _kIdIntStart && typeId <= _kIdVec512End; } -static constexpr bool isBase(uint32_t typeId) noexcept { return typeId >= _kIdBaseStart && typeId <= _kIdBaseEnd; } -static constexpr bool isAbstract(uint32_t typeId) noexcept { return typeId >= kIdIntPtr && typeId <= kIdUIntPtr; } - -static constexpr bool isInt(uint32_t typeId) noexcept { return typeId >= _kIdIntStart && typeId <= _kIdIntEnd; } -static constexpr bool isInt8(uint32_t typeId) noexcept { return typeId == kIdI8; } -static constexpr bool isUInt8(uint32_t typeId) noexcept { return typeId == kIdU8; } -static constexpr bool isInt16(uint32_t typeId) noexcept { return typeId == kIdI16; } -static constexpr bool isUInt16(uint32_t typeId) noexcept { return typeId == kIdU16; } -static constexpr bool isInt32(uint32_t typeId) noexcept { return typeId == kIdI32; } -static constexpr bool isUInt32(uint32_t typeId) noexcept { return typeId == kIdU32; } -static constexpr bool isInt64(uint32_t typeId) noexcept { return typeId == kIdI64; } -static constexpr bool isUInt64(uint32_t typeId) noexcept { return typeId == kIdU64; } - -static constexpr bool isGp8(uint32_t typeId) noexcept { return typeId >= kIdI8 && typeId <= kIdU8; } -static constexpr bool isGp16(uint32_t typeId) noexcept { return typeId >= kIdI16 && typeId <= kIdU16; } -static constexpr bool isGp32(uint32_t typeId) noexcept { return typeId >= kIdI32 && typeId <= kIdU32; } -static constexpr bool isGp64(uint32_t typeId) noexcept { return typeId >= kIdI64 && typeId <= kIdU64; } - -static constexpr bool isFloat(uint32_t typeId) noexcept { return typeId >= _kIdFloatStart && typeId <= _kIdFloatEnd; } -static constexpr bool isFloat32(uint32_t typeId) noexcept { return typeId == kIdF32; } -static constexpr bool isFloat64(uint32_t typeId) noexcept { return typeId == kIdF64; } -static constexpr bool isFloat80(uint32_t typeId) noexcept { return typeId == kIdF80; } - -static constexpr bool isMask(uint32_t typeId) noexcept { return typeId >= _kIdMaskStart && typeId <= _kIdMaskEnd; } -static constexpr bool isMask8(uint32_t typeId) noexcept { return typeId == kIdMask8; } -static constexpr bool isMask16(uint32_t typeId) noexcept { return typeId == kIdMask16; } -static constexpr bool isMask32(uint32_t typeId) noexcept { return typeId == kIdMask32; } -static constexpr bool isMask64(uint32_t typeId) noexcept { return typeId == kIdMask64; } - -static constexpr bool isMmx(uint32_t typeId) noexcept { return typeId >= _kIdMmxStart && typeId <= _kIdMmxEnd; } -static constexpr bool isMmx32(uint32_t typeId) noexcept { return typeId == kIdMmx32; } -static constexpr bool isMmx64(uint32_t typeId) noexcept { return typeId == kIdMmx64; } - -static constexpr bool isVec(uint32_t typeId) noexcept { return typeId >= _kIdVec32Start && typeId <= _kIdVec512End; } -static constexpr bool isVec32(uint32_t typeId) noexcept { return typeId >= _kIdVec32Start && typeId <= _kIdVec32End; } -static constexpr bool isVec64(uint32_t typeId) noexcept { return typeId >= _kIdVec64Start && typeId <= _kIdVec64End; } -static constexpr bool isVec128(uint32_t typeId) noexcept { return typeId >= _kIdVec128Start && typeId <= _kIdVec128End; } -static constexpr bool isVec256(uint32_t typeId) noexcept { return typeId >= _kIdVec256Start && typeId <= _kIdVec256End; } -static constexpr bool isVec512(uint32_t typeId) noexcept { return typeId >= _kIdVec512Start && typeId <= _kIdVec512End; } +//! Returns the scalar type of `typeId`. +static inline TypeId scalarOf(TypeId typeId) noexcept { return _typeData.scalarOf[uint32_t(typeId)]; } + +//! Returns the size [in bytes] of `typeId`. +static inline uint32_t sizeOf(TypeId typeId) noexcept { return _typeData.sizeOf[uint32_t(typeId)]; } + +//! Tests whether a given type `typeId` is between `a` and `b`. +static inline constexpr bool isBetween(TypeId typeId, TypeId a, TypeId b) noexcept { + return Support::isBetween(uint32_t(typeId), uint32_t(a), uint32_t(b)); +} + +//! Tests whether a given type `typeId` is \ref TypeId::kVoid. +static inline constexpr bool isVoid(TypeId typeId) noexcept { return typeId == TypeId::kVoid; } +//! Tests whether a given type `typeId` is a valid non-void type. +static inline constexpr bool isValid(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kVec512End); } +//! Tests whether a given type `typeId` is scalar (has no vector part). +static inline constexpr bool isScalar(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kBaseStart, TypeId::_kBaseEnd); } +//! Tests whether a given type `typeId` is abstract, which means that its size depends on register size. +static inline constexpr bool isAbstract(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kIntPtr, TypeId::kUIntPtr); } + +//! Tests whether a given type is a scalar integer (signed or unsigned) of any size. +static inline constexpr bool isInt(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kIntEnd); } +//! Tests whether a given type is a scalar 8-bit integer (signed). +static inline constexpr bool isInt8(TypeId typeId) noexcept { return typeId == TypeId::kInt8; } +//! Tests whether a given type is a scalar 8-bit integer (unsigned). +static inline constexpr bool isUInt8(TypeId typeId) noexcept { return typeId == TypeId::kUInt8; } +//! Tests whether a given type is a scalar 16-bit integer (signed). +static inline constexpr bool isInt16(TypeId typeId) noexcept { return typeId == TypeId::kInt16; } +//! Tests whether a given type is a scalar 16-bit integer (unsigned). +static inline constexpr bool isUInt16(TypeId typeId) noexcept { return typeId == TypeId::kUInt16; } +//! Tests whether a given type is a scalar 32-bit integer (signed). +static inline constexpr bool isInt32(TypeId typeId) noexcept { return typeId == TypeId::kInt32; } +//! Tests whether a given type is a scalar 32-bit integer (unsigned). +static inline constexpr bool isUInt32(TypeId typeId) noexcept { return typeId == TypeId::kUInt32; } +//! Tests whether a given type is a scalar 64-bit integer (signed). +static inline constexpr bool isInt64(TypeId typeId) noexcept { return typeId == TypeId::kInt64; } +//! Tests whether a given type is a scalar 64-bit integer (unsigned). +static inline constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; } + +static inline constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); } +static inline constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); } +static inline constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); } +static inline constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); } + +//! Tests whether a given type is a scalar floating point of any size. +static inline constexpr bool isFloat(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kFloatStart, TypeId::_kFloatEnd); } +//! Tests whether a given type is a scalar 32-bit float. +static inline constexpr bool isFloat32(TypeId typeId) noexcept { return typeId == TypeId::kFloat32; } +//! Tests whether a given type is a scalar 64-bit float. +static inline constexpr bool isFloat64(TypeId typeId) noexcept { return typeId == TypeId::kFloat64; } +//! Tests whether a given type is a scalar 80-bit float. +static inline constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; } + +static inline constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); } +static inline constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; } +static inline constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; } +static inline constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; } +static inline constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; } + +static inline constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); } +static inline constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; } +static inline constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; } + +static inline constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); } +static inline constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); } +static inline constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); } +static inline constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); } +static inline constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); } +static inline constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); } //! \cond enum TypeCategory : uint32_t { @@ -215,157 +242,174 @@ enum TypeCategory : uint32_t { kTypeCategoryFunction = 4 }; -template<typename T, uint32_t Category> -struct IdOfT_ByCategory {}; // Fails if not specialized. +template<typename T, TypeCategory kCategory> +struct TypeIdOfT_ByCategory {}; // Fails if not specialized. template<typename T> -struct IdOfT_ByCategory<T, kTypeCategoryIntegral> { +struct TypeIdOfT_ByCategory<T, kTypeCategoryIntegral> { enum : uint32_t { - kTypeId = (sizeof(T) == 1 && std::is_signed<T>::value) ? kIdI8 : - (sizeof(T) == 1 && !std::is_signed<T>::value) ? kIdU8 : - (sizeof(T) == 2 && std::is_signed<T>::value) ? kIdI16 : - (sizeof(T) == 2 && !std::is_signed<T>::value) ? kIdU16 : - (sizeof(T) == 4 && std::is_signed<T>::value) ? kIdI32 : - (sizeof(T) == 4 && !std::is_signed<T>::value) ? kIdU32 : - (sizeof(T) == 8 && std::is_signed<T>::value) ? kIdI64 : - (sizeof(T) == 8 && !std::is_signed<T>::value) ? kIdU64 : kIdVoid + kTypeId = uint32_t( + (sizeof(T) == 1 && std::is_signed<T>::value) ? TypeId::kInt8 : + (sizeof(T) == 1 && !std::is_signed<T>::value) ? TypeId::kUInt8 : + (sizeof(T) == 2 && std::is_signed<T>::value) ? TypeId::kInt16 : + (sizeof(T) == 2 && !std::is_signed<T>::value) ? TypeId::kUInt16 : + (sizeof(T) == 4 && std::is_signed<T>::value) ? TypeId::kInt32 : + (sizeof(T) == 4 && !std::is_signed<T>::value) ? TypeId::kUInt32 : + (sizeof(T) == 8 && std::is_signed<T>::value) ? TypeId::kInt64 : + (sizeof(T) == 8 && !std::is_signed<T>::value) ? TypeId::kUInt64 : TypeId::kVoid) }; }; template<typename T> -struct IdOfT_ByCategory<T, kTypeCategoryFloatingPoint> { +struct TypeIdOfT_ByCategory<T, kTypeCategoryFloatingPoint> { enum : uint32_t { - kTypeId = (sizeof(T) == 4 ) ? kIdF32 : - (sizeof(T) == 8 ) ? kIdF64 : - (sizeof(T) >= 10) ? kIdF80 : kIdVoid + kTypeId = uint32_t( + (sizeof(T) == 4 ) ? TypeId::kFloat32 : + (sizeof(T) == 8 ) ? TypeId::kFloat64 : + (sizeof(T) >= 10) ? TypeId::kFloat80 : TypeId::kVoid) }; }; template<typename T> -struct IdOfT_ByCategory<T, kTypeCategoryEnum> - : public IdOfT_ByCategory<typename std::underlying_type<T>::type, kTypeCategoryIntegral> {}; +struct TypeIdOfT_ByCategory<T, kTypeCategoryEnum> + : public TypeIdOfT_ByCategory<typename std::underlying_type<T>::type, kTypeCategoryIntegral> {}; template<typename T> -struct IdOfT_ByCategory<T, kTypeCategoryFunction> { - enum: uint32_t { kTypeId = kIdUIntPtr }; +struct TypeIdOfT_ByCategory<T, kTypeCategoryFunction> { + enum : uint32_t { + kTypeId = uint32_t(TypeId::kUIntPtr) + }; }; //! \endcond -//! IdOfT<> template allows to get a TypeId from a C++ type `T`. -template<typename T> -struct IdOfT +//! TypeIdOfT<> template allows to get a TypeId from a C++ type `T`. #ifdef _DOXYGEN +template<typename T> +struct TypeIdOfT { //! TypeId of C++ type `T`. - static constexpr uint32_t kTypeId = _TypeIdDeducedAtCompileTime_; + static constexpr TypeId kTypeId = _TypeIdDeducedAtCompileTime_; +}; #else - : public IdOfT_ByCategory<T, +template<typename T> +struct TypeIdOfT + : public TypeIdOfT_ByCategory<T, std::is_enum<T>::value ? kTypeCategoryEnum : std::is_integral<T>::value ? kTypeCategoryIntegral : std::is_floating_point<T>::value ? kTypeCategoryFloatingPoint : - std::is_function<T>::value ? kTypeCategoryFunction : kTypeCategoryUnknown> + std::is_function<T>::value ? kTypeCategoryFunction : kTypeCategoryUnknown> {}; #endif -{}; //! \cond template<typename T> -struct IdOfT<T*> { enum : uint32_t { kTypeId = kIdUIntPtr }; }; +struct TypeIdOfT<T*> { + enum : uint32_t { + kTypeId = uint32_t(TypeId::kUIntPtr) + }; +}; template<typename T> -struct IdOfT<T&> { enum : uint32_t { kTypeId = kIdUIntPtr }; }; +struct TypeIdOfT<T&> { + enum : uint32_t { + kTypeId = uint32_t(TypeId::kUIntPtr) + }; +}; //! \endcond -static inline uint32_t baseOf(uint32_t typeId) noexcept { - ASMJIT_ASSERT(typeId <= kIdMax); - return _typeData.baseOf[typeId]; -} - -static inline uint32_t sizeOf(uint32_t typeId) noexcept { - ASMJIT_ASSERT(typeId <= kIdMax); - return _typeData.sizeOf[typeId]; -} +//! Returns a corresponding \ref TypeId of `T` type. +template<typename T> +static inline constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>::kTypeId); } -//! Returns offset needed to convert a `kIntPtr` and `kUIntPtr` TypeId -//! into a type that matches `registerSize` (general-purpose register size). -//! If you find such TypeId it's then only about adding the offset to it. +//! Returns offset needed to convert a `kIntPtr` and `kUIntPtr` TypeId into a type that matches `registerSize` +//! (general-purpose register size). If you find such TypeId it's then only about adding the offset to it. //! //! For example: //! //! ``` -//! uint32_t registerSize = '4' or '8'; -//! uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize); +//! uint32_t registerSize = /* 4 or 8 */; +//! uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize); //! -//! uint32_t typeId = 'some type-id'; +//! TypeId typeId = 'some type-id'; //! //! // Normalize some typeId into a non-abstract typeId. -//! if (Type::isAbstract(typeId)) typeId += deabstractDelta; +//! if (TypeUtils::isAbstract(typeId)) typeId += deabstractDelta; //! -//! // The same, but by using Type::deabstract() function. -//! typeId = Type::deabstract(typeId, deabstractDelta); +//! // The same, but by using TypeUtils::deabstract() function. +//! typeId = TypeUtils::deabstract(typeId, deabstractDelta); //! ``` -static constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept { - return registerSize >= 8 ? kIdI64 - kIdIntPtr : kIdI32 - kIdIntPtr; +static inline constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept { + return registerSize >= 8 ? uint32_t(TypeId::kInt64) - uint32_t(TypeId::kIntPtr) + : uint32_t(TypeId::kInt32) - uint32_t(TypeId::kIntPtr); +} + +//! Deabstracts a given `typeId` into a native type by using `deabstractDelta`, which was previously +//! calculated by calling \ref deabstractDeltaOfSize() with a target native register size. +static inline constexpr TypeId deabstract(TypeId typeId, uint32_t deabstractDelta) noexcept { + return isAbstract(typeId) ? TypeId(uint32_t(typeId) + deabstractDelta) : typeId; } -static constexpr uint32_t deabstract(uint32_t typeId, uint32_t deabstractDelta) noexcept { - return isAbstract(typeId) ? typeId + deabstractDelta : typeId; +static inline constexpr TypeId scalarToVector(TypeId scalarTypeId, TypeId vecStartId) noexcept { + return TypeId(uint32_t(vecStartId) + uint32_t(scalarTypeId) - uint32_t(TypeId::kInt8)); } +} // {TypeUtils} + +//! Provides type identifiers that can be used in templates instead of native types. +namespace Type { + //! bool as C++ type-name. struct Bool {}; //! int8_t as C++ type-name. -struct I8 {}; +struct Int8 {}; //! uint8_t as C++ type-name. -struct U8 {}; +struct UInt8 {}; //! int16_t as C++ type-name. -struct I16 {}; +struct Int16 {}; //! uint16_t as C++ type-name. -struct U16 {}; +struct UInt16 {}; //! int32_t as C++ type-name. -struct I32 {}; +struct Int32 {}; //! uint32_t as C++ type-name. -struct U32 {}; +struct UInt32 {}; //! int64_t as C++ type-name. -struct I64 {}; +struct Int64 {}; //! uint64_t as C++ type-name. -struct U64 {}; +struct UInt64 {}; //! intptr_t as C++ type-name. -struct IPtr {}; +struct IntPtr {}; //! uintptr_t as C++ type-name. -struct UPtr {}; +struct UIntPtr {}; //! float as C++ type-name. -struct F32 {}; +struct Float32 {}; //! double as C++ type-name. -struct F64 {}; +struct Float64 {}; } // {Type} -// ============================================================================ -// [ASMJIT_DEFINE_TYPE_ID] -// ============================================================================ - //! \cond -#define ASMJIT_DEFINE_TYPE_ID(T, TYPE_ID) \ -namespace Type { \ - template<> \ - struct IdOfT<T> { \ - enum : uint32_t { kTypeId = TYPE_ID }; \ - }; \ +#define ASMJIT_DEFINE_TYPE_ID(T, TYPE_ID) \ +namespace TypeUtils { \ + template<> \ + struct TypeIdOfT<T> { \ + enum : uint32_t { \ + kTypeId = uint32_t(TYPE_ID) \ + }; \ + }; \ } -ASMJIT_DEFINE_TYPE_ID(void, kIdVoid); -ASMJIT_DEFINE_TYPE_ID(Bool, kIdU8); -ASMJIT_DEFINE_TYPE_ID(I8 , kIdI8); -ASMJIT_DEFINE_TYPE_ID(U8 , kIdU8); -ASMJIT_DEFINE_TYPE_ID(I16 , kIdI16); -ASMJIT_DEFINE_TYPE_ID(U16 , kIdU16); -ASMJIT_DEFINE_TYPE_ID(I32 , kIdI32); -ASMJIT_DEFINE_TYPE_ID(U32 , kIdU32); -ASMJIT_DEFINE_TYPE_ID(I64 , kIdI64); -ASMJIT_DEFINE_TYPE_ID(U64 , kIdU64); -ASMJIT_DEFINE_TYPE_ID(IPtr, kIdIntPtr); -ASMJIT_DEFINE_TYPE_ID(UPtr, kIdUIntPtr); -ASMJIT_DEFINE_TYPE_ID(F32 , kIdF32); -ASMJIT_DEFINE_TYPE_ID(F64 , kIdF64); +ASMJIT_DEFINE_TYPE_ID(void , TypeId::kVoid); +ASMJIT_DEFINE_TYPE_ID(Type::Bool , TypeId::kUInt8); +ASMJIT_DEFINE_TYPE_ID(Type::Int8 , TypeId::kInt8); +ASMJIT_DEFINE_TYPE_ID(Type::UInt8 , TypeId::kUInt8); +ASMJIT_DEFINE_TYPE_ID(Type::Int16 , TypeId::kInt16); +ASMJIT_DEFINE_TYPE_ID(Type::UInt16 , TypeId::kUInt16); +ASMJIT_DEFINE_TYPE_ID(Type::Int32 , TypeId::kInt32); +ASMJIT_DEFINE_TYPE_ID(Type::UInt32 , TypeId::kUInt32); +ASMJIT_DEFINE_TYPE_ID(Type::Int64 , TypeId::kInt64); +ASMJIT_DEFINE_TYPE_ID(Type::UInt64 , TypeId::kUInt64); +ASMJIT_DEFINE_TYPE_ID(Type::IntPtr , TypeId::kIntPtr); +ASMJIT_DEFINE_TYPE_ID(Type::UIntPtr, TypeId::kUIntPtr); +ASMJIT_DEFINE_TYPE_ID(Type::Float32, TypeId::kFloat32); +ASMJIT_DEFINE_TYPE_ID(Type::Float64, TypeId::kFloat64); //! \endcond //! \} diff --git a/src/asmjit/core/virtmem.cpp b/src/asmjit/core/virtmem.cpp index 4ac00e6..8259f9c 100644 --- a/src/asmjit/core/virtmem.cpp +++ b/src/asmjit/core/virtmem.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_JIT @@ -44,9 +26,11 @@ // Apple recently introduced MAP_JIT flag, which we want to use. #if defined(__APPLE__) + #include <pthread.h> #include <TargetConditionals.h> #if TARGET_OS_OSX #include <sys/utsname.h> + #include <libkern/OSCacheControl.h> // sys_icache_invalidate(). #endif // Older SDK doesn't define `MAP_JIT`. #ifndef MAP_JIT @@ -54,7 +38,7 @@ #endif #endif - // BSD/OSX: `MAP_ANONYMOUS` is not defined, `MAP_ANON` is. + // BSD/MAC: `MAP_ANONYMOUS` is not defined, `MAP_ANON` is. #if !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif @@ -75,22 +59,25 @@ #define ASMJIT_VM_SHM_AVAILABLE 1 #endif -ASMJIT_BEGIN_NAMESPACE +#if defined(__APPLE__) && ASMJIT_ARCH_ARM >= 64 + #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP +#endif + +ASMJIT_BEGIN_SUB_NAMESPACE(VirtMem) -// ============================================================================ -// [asmjit::VirtMem - Utilities] -// ============================================================================ +// Virtual Memory Utilities +// ======================== -static const uint32_t VirtMem_dualMappingFilter[2] = { - VirtMem::kAccessWrite | VirtMem::kMMapMaxAccessWrite, - VirtMem::kAccessExecute | VirtMem::kMMapMaxAccessExecute +static const MemoryFlags dualMappingFilter[2] = { + MemoryFlags::kAccessWrite | MemoryFlags::kMMapMaxAccessWrite, + MemoryFlags::kAccessExecute | MemoryFlags::kMMapMaxAccessExecute }; -// ============================================================================ -// [asmjit::VirtMem - Virtual Memory [Windows]] -// ============================================================================ +// Virtual Memory [Windows] +// ======================== #if defined(_WIN32) + struct ScopedHandle { inline ScopedHandle() noexcept : value(nullptr) {} @@ -103,7 +90,7 @@ struct ScopedHandle { HANDLE value; }; -static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { +static void getVMInfo(Info& vmInfo) noexcept { SYSTEM_INFO systemInfo; ::GetSystemInfo(&systemInfo); @@ -111,15 +98,15 @@ static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { vmInfo.pageGranularity = systemInfo.dwAllocationGranularity; } -// Returns windows-specific protectFlags from \ref VirtMem::Flags. -static DWORD VirtMem_winProtectFlagsFromFlags(uint32_t flags) noexcept { +// Returns windows-specific protectFlags from \ref MemoryFlags. +static DWORD protectFlagsFromMemoryFlags(MemoryFlags memoryFlags) noexcept { DWORD protectFlags; // READ|WRITE|EXECUTE. - if (flags & VirtMem::kAccessExecute) - protectFlags = (flags & VirtMem::kAccessWrite) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; - else if (flags & VirtMem::kAccessRW) - protectFlags = (flags & VirtMem::kAccessWrite) ? PAGE_READWRITE : PAGE_READONLY; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) + protectFlags = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; + else if (Support::test(memoryFlags, MemoryFlags::kAccessRW)) + protectFlags = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? PAGE_READWRITE : PAGE_READONLY; else protectFlags = PAGE_NOACCESS; @@ -127,19 +114,23 @@ static DWORD VirtMem_winProtectFlagsFromFlags(uint32_t flags) noexcept { return protectFlags; } -static DWORD VirtMem_winDesiredAccessFromFlags(uint32_t flags) noexcept { - DWORD access = (flags & VirtMem::kAccessWrite) ? FILE_MAP_WRITE : FILE_MAP_READ; - if (flags & VirtMem::kAccessExecute) +static DWORD desiredAccessFromMemoryFlags(MemoryFlags memoryFlags) noexcept { + DWORD access = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? FILE_MAP_WRITE : FILE_MAP_READ; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) access |= FILE_MAP_EXECUTE; return access; } -Error VirtMem::alloc(void** p, size_t size, uint32_t flags) noexcept { +static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { + return HardenedRuntimeFlags::kNone; +} + +Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { *p = nullptr; if (size == 0) return DebugUtils::errored(kErrorInvalidArgument); - DWORD protectFlags = VirtMem_winProtectFlagsFromFlags(flags); + DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags); void* result = ::VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, protectFlags); if (!result) @@ -149,15 +140,15 @@ Error VirtMem::alloc(void** p, size_t size, uint32_t flags) noexcept { return kErrorOk; } -Error VirtMem::release(void* p, size_t size) noexcept { +Error release(void* p, size_t size) noexcept { DebugUtils::unused(size); if (ASMJIT_UNLIKELY(!::VirtualFree(p, 0, MEM_RELEASE))) return DebugUtils::errored(kErrorInvalidArgument); return kErrorOk; } -Error VirtMem::protect(void* p, size_t size, uint32_t flags) noexcept { - DWORD protectFlags = VirtMem_winProtectFlagsFromFlags(flags); +Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept { + DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags); DWORD oldFlags; if (::VirtualProtect(p, size, protectFlags, &oldFlags)) @@ -166,8 +157,8 @@ Error VirtMem::protect(void* p, size_t size, uint32_t flags) noexcept { return DebugUtils::errored(kErrorInvalidArgument); } -Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) noexcept { - dm->ro = nullptr; +Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { + dm->rx = nullptr; dm->rw = nullptr; if (size == 0) @@ -187,8 +178,8 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) no void* ptr[2]; for (uint32_t i = 0; i < 2; i++) { - uint32_t accessFlags = flags & ~VirtMem_dualMappingFilter[i]; - DWORD desiredAccess = VirtMem_winDesiredAccessFromFlags(accessFlags); + MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i]; + DWORD desiredAccess = desiredAccessFromMemoryFlags(accessFlags); ptr[i] = ::MapViewOfFile(handle.value, desiredAccess, 0, 0, size); if (ptr[i] == nullptr) { @@ -198,37 +189,36 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) no } } - dm->ro = ptr[0]; + dm->rx = ptr[0]; dm->rw = ptr[1]; return kErrorOk; } -Error VirtMem::releaseDualMapping(DualMapping* dm, size_t size) noexcept { +Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { DebugUtils::unused(size); bool failed = false; - if (!::UnmapViewOfFile(dm->ro)) + if (!::UnmapViewOfFile(dm->rx)) failed = true; - if (dm->ro != dm->rw && !UnmapViewOfFile(dm->rw)) + if (dm->rx != dm->rw && !UnmapViewOfFile(dm->rw)) failed = true; if (failed) return DebugUtils::errored(kErrorInvalidArgument); - dm->ro = nullptr; + dm->rx = nullptr; dm->rw = nullptr; return kErrorOk; } #endif -// ============================================================================ -// [asmjit::VirtMem - Virtual Memory [Posix]] -// ============================================================================ +// Virtual Memory [Posix] +// ====================== #if !defined(_WIN32) -static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { +static void getVMInfo(Info& vmInfo) noexcept { uint32_t pageSize = uint32_t(::getpagesize()); vmInfo.pageSize = pageSize; @@ -236,14 +226,14 @@ static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { } #if !defined(SHM_ANON) -static const char* VirtMem_getTmpDir() noexcept { +static const char* getTmpDir() noexcept { const char* tmpDir = getenv("TMPDIR"); return tmpDir ? tmpDir : "/tmp"; } #endif // Translates libc errors specific to VirtualMemory mapping to `asmjit::Error`. -static Error VirtMem_asmjitErrorFromErrno(int e) noexcept { +static Error asmjitErrorFromErrno(int e) noexcept { switch (e) { case EACCES: case EAGAIN: @@ -265,16 +255,14 @@ static Error VirtMem_asmjitErrorFromErrno(int e) noexcept { } } -// Some operating systems don't allow /dev/shm to be executable. On Linux this -// happens when /dev/shm is mounted with 'noexec', which is enforced by systemd. -// Other operating systems like MacOS also restrict executable permissions regarding -// /dev/shm, so we use a runtime detection before attempting to allocate executable -// memory. Sometimes we don't need the detection as we know it would always result -// in `kShmStrategyTmpDir`. -enum ShmStrategy : uint32_t { - kShmStrategyUnknown = 0, - kShmStrategyDevShm = 1, - kShmStrategyTmpDir = 2 +// Some operating systems don't allow /dev/shm to be executable. On Linux this happens when /dev/shm is mounted with +// 'noexec', which is enforced by systemd. Other operating systems like MacOS also restrict executable permissions +// regarding /dev/shm, so we use a runtime detection before attempting to allocate executable memory. Sometimes we +// don't need the detection as we know it would always result in `ShmStrategy::kTmpDir`. +enum class ShmStrategy : uint32_t { + kUnknown = 0, + kDevShm = 1, + kTmpDir = 2 }; class AnonymousMemory { @@ -289,17 +277,17 @@ public: FileType _fileType; StringTmp<128> _tmpName; - ASMJIT_INLINE AnonymousMemory() noexcept + inline AnonymousMemory() noexcept : _fd(-1), _fileType(kFileTypeNone), _tmpName() {} - ASMJIT_INLINE ~AnonymousMemory() noexcept { + inline ~AnonymousMemory() noexcept { unlink(); close(); } - ASMJIT_INLINE int fd() const noexcept { return _fd; } + inline int fd() const noexcept { return _fd; } Error open(bool preferTmpOverDevShm) noexcept { #if defined(__linux__) && defined(__NR_memfd_create) @@ -319,7 +307,7 @@ public: if (e == ENOSYS) memfd_create_not_supported = 1; else - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } #endif @@ -331,13 +319,12 @@ public: if (ASMJIT_LIKELY(_fd >= 0)) return kErrorOk; else - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(errno)); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); #else - // POSIX API. We have to generate somehow a unique name. This is nothing - // cryptographic, just using a bit from the stack address to always have - // a different base for different threads (as threads have their own stack) - // and retries for avoiding collisions. We use `shm_open()` with flags that - // require creation of the file so we never open an existing shared memory. + // POSIX API. We have to generate somehow a unique name. This is nothing cryptographic, just using a bit from + // the stack address to always have a different base for different threads (as threads have their own stack) + // and retries for avoiding collisions. We use `shm_open()` with flags that require creation of the file so we + // never open an existing shared memory. static std::atomic<uint32_t> internalCounter; const char* kShmFormat = "/shm-id-%016llX"; @@ -351,7 +338,7 @@ public: bool useTmp = !ASMJIT_VM_SHM_DETECT || preferTmpOverDevShm; if (useTmp) { - _tmpName.assign(VirtMem_getTmpDir()); + _tmpName.assign(getTmpDir()); _tmpName.appendFormat(kShmFormat, (unsigned long long)bits); _fd = ::open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, 0); if (ASMJIT_LIKELY(_fd >= 0)) { @@ -372,7 +359,7 @@ public: int e = errno; if (e != EEXIST) - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } return DebugUtils::errored(kErrorFailedToOpenAnonymousMemory); @@ -406,17 +393,30 @@ public: Error allocate(size_t size) noexcept { // TODO: Improve this by using `posix_fallocate()` when available. if (ftruncate(_fd, off_t(size)) != 0) - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(errno)); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); return kErrorOk; } }; +// Returns `mmap()` protection flags from \ref MemoryFlags. +static int mmProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { + int protection = 0; + if (Support::test(memoryFlags, MemoryFlags::kAccessRead)) protection |= PROT_READ; + if (Support::test(memoryFlags, MemoryFlags::kAccessWrite)) protection |= PROT_READ | PROT_WRITE; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) protection |= PROT_READ | PROT_EXEC; + return protection; +} + #if defined(__APPLE__) -// Detects whether the current process is hardened, which means that pages that -// have WRITE and EXECUTABLE flags cannot be allocated without MAP_JIT flag. -static ASMJIT_INLINE bool VirtMem_isHardened() noexcept { - static volatile uint32_t globalHardenedFlag; +// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags cannot +// be allocated without MAP_JIT flag. +static inline bool hasHardenedRuntimeMacOS() noexcept { +#if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 + // MacOS on AArch64 has always hardened runtime enabled. + return true; +#else + static std::atomic<uint32_t> globalHardenedFlag; enum HardenedFlag : uint32_t { kHardenedFlagUnknown = 0, @@ -424,37 +424,40 @@ static ASMJIT_INLINE bool VirtMem_isHardened() noexcept { kHardenedFlagEnabled = 2 }; - uint32_t flag = globalHardenedFlag; + uint32_t flag = globalHardenedFlag.load(); if (flag == kHardenedFlagUnknown) { - VirtMem::Info memInfo; - VirtMem_getInfo(memInfo); + size_t pageSize = ::getpagesize(); - void* ptr = mmap(nullptr, memInfo.pageSize, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + void* ptr = mmap(nullptr, pageSize, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (ptr == MAP_FAILED) { flag = kHardenedFlagEnabled; } else { flag = kHardenedFlagDisabled; - munmap(ptr, memInfo.pageSize); + munmap(ptr, pageSize); } - globalHardenedFlag = flag; + globalHardenedFlag.store(flag); } return flag == kHardenedFlagEnabled; +#endif } -// MAP_JIT flag required to run unsigned JIT code is only supported by kernel -// version 10.14+ (Mojave) and IOS. -static ASMJIT_INLINE bool VirtMem_hasMapJitSupport() noexcept { -#if TARGET_OS_OSX - static volatile int globalVersion; +static inline bool hasMapJitSupportMacOS() noexcept { +#if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 + // MacOS for 64-bit AArch architecture always uses hardened runtime. Some documentation can be found here: + // - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon + return true; +#elif TARGET_OS_OSX + // MAP_JIT flag required to run unsigned JIT code is only supported by kernel version 10.14+ (Mojave) and IOS. + static std::atomic<uint32_t> globalVersion; - int ver = globalVersion; + int ver = globalVersion.load(); if (!ver) { - struct utsname osname; + struct utsname osname {}; uname(&osname); ver = atoi(osname.release); - globalVersion = ver; + globalVersion.store(ver); } return ver >= 18; #else @@ -462,53 +465,63 @@ static ASMJIT_INLINE bool VirtMem_hasMapJitSupport() noexcept { return true; #endif } +#endif // __APPLE__ + +// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags +// cannot be normally allocated. On MacOS such allocation requires MAP_JIT flag. +static inline bool hasHardenedRuntime() noexcept { +#if defined(__APPLE__) + return hasHardenedRuntimeMacOS(); +#else + return false; #endif +} -// Returns `mmap()` protection flags from \ref VirtMem::Flags. -static int VirtMem_mmProtFromFlags(uint32_t flags) noexcept { - int protection = 0; - if (flags & VirtMem::kAccessRead) protection |= PROT_READ; - if (flags & VirtMem::kAccessWrite) protection |= PROT_READ | PROT_WRITE; - if (flags & VirtMem::kAccessExecute) protection |= PROT_READ | PROT_EXEC; - return protection; +// Detects whether MAP_JIT is available. +static inline bool hasMapJitSupport() noexcept { +#if defined(__APPLE__) + return hasMapJitSupportMacOS(); +#else + return false; +#endif } // Returns either MAP_JIT or 0 based on `flags` and the host operating system. -static ASMJIT_INLINE int VirtMem_mmMapJitFromFlags(uint32_t flags) noexcept { +static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #if defined(__APPLE__) - // Always use MAP_JIT flag if user asked for it (could be used for testing - // on non-hardened processes) and detect whether it must be used when the - // process is actually hardened (in that case it doesn't make sense to rely - // on user `flags`). - bool useMapJit = (flags & VirtMem::kMMapEnableMapJit) != 0 || VirtMem_isHardened(); + // Always use MAP_JIT flag if user asked for it (could be used for testing on non-hardened processes) and detect + // whether it must be used when the process is actually hardened (in that case it doesn't make sense to rely on + // user `memoryFlags`). + bool useMapJit = Support::test(memoryFlags, MemoryFlags::kMMapEnableMapJit) || hasHardenedRuntime(); if (useMapJit) - return VirtMem_hasMapJitSupport() ? int(MAP_JIT) : 0; + return hasMapJitSupport() ? int(MAP_JIT) : 0; else return 0; #else - DebugUtils::unused(flags); + DebugUtils::unused(memoryFlags); return 0; #endif } // Returns BSD-specific `PROT_MAX()` flags. -static ASMJIT_INLINE int VirtMem_mmMaxProtFromFlags(uint32_t flags) noexcept { +static inline int mmMaxProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #if defined(PROT_MAX) - static constexpr uint32_t kMaxProtShift = Support::constCtz(VirtMem::kMMapMaxAccessRead); - if (flags & (VirtMem::kMMapMaxAccessReadWrite | VirtMem::kMMapMaxAccessExecute)) - return PROT_MAX(VirtMem_mmProtFromFlags(flags >> kMaxProtShift)); + static constexpr uint32_t kMaxProtShift = Support::ConstCTZ<uint32_t(MemoryFlags::kMMapMaxAccessRead)>::value; + + if (Support::test(memoryFlags, MemoryFlags::kMMapMaxAccessReadWrite | MemoryFlags::kMMapMaxAccessExecute)) + return PROT_MAX(mmProtFromMemoryFlags((MemoryFlags)(uint32_t(memoryFlags) >> kMaxProtShift))); else return 0; #else - DebugUtils::unused(flags); + DebugUtils::unused(memoryFlags); return 0; #endif } #if ASMJIT_VM_SHM_DETECT -static Error VirtMem_detectShmStrategy(uint32_t* strategyOut) noexcept { +static Error detectShmStrategy(ShmStrategy* strategyOut) noexcept { AnonymousMemory anonMem; - VirtMem::Info vmInfo = VirtMem::info(); + Info vmInfo = info(); ASMJIT_PROPAGATE(anonMem.open(false)); ASMJIT_PROPAGATE(anonMem.allocate(vmInfo.pageSize)); @@ -517,46 +530,57 @@ static Error VirtMem_detectShmStrategy(uint32_t* strategyOut) noexcept { if (ptr == MAP_FAILED) { int e = errno; if (e == EINVAL) { - *strategyOut = kShmStrategyTmpDir; + *strategyOut = ShmStrategy::kTmpDir; return kErrorOk; } - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } else { munmap(ptr, vmInfo.pageSize); - *strategyOut = kShmStrategyDevShm; + *strategyOut = ShmStrategy::kDevShm; return kErrorOk; } } #endif -static Error VirtMem_getShmStrategy(uint32_t* strategyOut) noexcept { +static Error getShmStrategy(ShmStrategy* strategyOut) noexcept { #if ASMJIT_VM_SHM_DETECT - // Initially don't assume anything. It has to be tested whether - // '/dev/shm' was mounted with 'noexec' flag or not. - static volatile uint32_t globalShmStrategy = kShmStrategyUnknown; - - uint32_t strategy = globalShmStrategy; - if (strategy == kShmStrategyUnknown) { - ASMJIT_PROPAGATE(VirtMem_detectShmStrategy(&strategy)); - globalShmStrategy = strategy; + // Initially don't assume anything. It has to be tested whether '/dev/shm' was mounted with 'noexec' flag or not. + static std::atomic<uint32_t> globalShmStrategy; + + ShmStrategy strategy = static_cast<ShmStrategy>(globalShmStrategy.load()); + if (strategy == ShmStrategy::kUnknown) { + ASMJIT_PROPAGATE(detectShmStrategy(&strategy)); + globalShmStrategy.store(static_cast<uint32_t>(strategy)); } *strategyOut = strategy; return kErrorOk; #else - *strategyOut = kShmStrategyTmpDir; + *strategyOut = ShmStrategy::kTmpDir; return kErrorOk; #endif } -Error VirtMem::alloc(void** p, size_t size, uint32_t flags) noexcept { +static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { + HardenedRuntimeFlags hrFlags = HardenedRuntimeFlags::kNone; + + if (hasHardenedRuntime()) + hrFlags |= HardenedRuntimeFlags::kEnabled; + + if (hasMapJitSupport()) + hrFlags |= HardenedRuntimeFlags::kMapJit; + + return hrFlags; +} + +Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { *p = nullptr; if (size == 0) return DebugUtils::errored(kErrorInvalidArgument); - int protection = VirtMem_mmProtFromFlags(flags) | VirtMem_mmMaxProtFromFlags(flags); - int mmFlags = MAP_PRIVATE | MAP_ANONYMOUS | VirtMem_mmMapJitFromFlags(flags); + int protection = mmProtFromMemoryFlags(memoryFlags) | mmMaxProtFromMemoryFlags(memoryFlags); + int mmFlags = MAP_PRIVATE | MAP_ANONYMOUS | mmMapJitFromMemoryFlags(memoryFlags); void* ptr = mmap(nullptr, size, protection, mmFlags, -1, 0); if (ptr == MAP_FAILED) @@ -566,7 +590,7 @@ Error VirtMem::alloc(void** p, size_t size, uint32_t flags) noexcept { return kErrorOk; } -Error VirtMem::release(void* p, size_t size) noexcept { +Error release(void* p, size_t size) noexcept { if (ASMJIT_UNLIKELY(munmap(p, size) != 0)) return DebugUtils::errored(kErrorInvalidArgument); @@ -574,26 +598,26 @@ Error VirtMem::release(void* p, size_t size) noexcept { } -Error VirtMem::protect(void* p, size_t size, uint32_t flags) noexcept { - int protection = VirtMem_mmProtFromFlags(flags); +Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept { + int protection = mmProtFromMemoryFlags(memoryFlags); if (mprotect(p, size, protection) == 0) return kErrorOk; return DebugUtils::errored(kErrorInvalidArgument); } -Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) noexcept { - dm->ro = nullptr; +Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { + dm->rx = nullptr; dm->rw = nullptr; if (off_t(size) <= 0) return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge); - bool preferTmpOverDevShm = (flags & kMappingPreferTmp) != 0; + bool preferTmpOverDevShm = Support::test(memoryFlags, MemoryFlags::kMappingPreferTmp); if (!preferTmpOverDevShm) { - uint32_t strategy; - ASMJIT_PROPAGATE(VirtMem_getShmStrategy(&strategy)); - preferTmpOverDevShm = (strategy == kShmStrategyTmpDir); + ShmStrategy strategy; + ASMJIT_PROPAGATE(getShmStrategy(&strategy)); + preferTmpOverDevShm = (strategy == ShmStrategy::kTmpDir); } AnonymousMemory anonMem; @@ -602,8 +626,8 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) no void* ptr[2]; for (uint32_t i = 0; i < 2; i++) { - uint32_t accessFlags = flags & ~VirtMem_dualMappingFilter[i]; - int protection = VirtMem_mmProtFromFlags(accessFlags) | VirtMem_mmMaxProtFromFlags(accessFlags); + MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i]; + int protection = mmProtFromMemoryFlags(accessFlags) | mmMaxProtFromMemoryFlags(accessFlags); ptr[i] = mmap(nullptr, size, protection, MAP_SHARED, anonMem.fd(), 0); if (ptr[i] == MAP_FAILED) { @@ -611,40 +635,61 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) no int e = errno; if (i == 1) munmap(ptr[0], size); - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } } - dm->ro = ptr[0]; + dm->rx = ptr[0]; dm->rw = ptr[1]; return kErrorOk; } -Error VirtMem::releaseDualMapping(DualMapping* dm, size_t size) noexcept { - Error err = release(dm->ro, size); - if (dm->ro != dm->rw) +Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { + Error err = release(dm->rx, size); + if (dm->rx != dm->rw) err |= release(dm->rw, size); if (err) return DebugUtils::errored(kErrorInvalidArgument); - dm->ro = nullptr; + dm->rx = nullptr; dm->rw = nullptr; return kErrorOk; } #endif -// ============================================================================ -// [asmjit::VirtMem - Virtual Memory [Memory Info]] -// ============================================================================ +// Virtual Memory - Flush Instruction Cache +// ======================================== + +void flushInstructionCache(void* p, size_t size) noexcept { +#if ASMJIT_ARCH_X86 + // X86/X86_64 architecture doesn't require to do anything to flush instruction cache. + DebugUtils::unused(p, size); +#elif defined(__APPLE__) + sys_icache_invalidate(p, size); +#elif defined(_WIN32) + // Windows has a built-in support in `kernel32.dll`. + FlushInstructionCache(GetCurrentProcess(), p, size); +#elif defined(__GNUC__) + char* start = static_cast<char*>(p); + char* end = start + size; + __builtin___clear_cache(start, end); +#else + #pragma message("asmjit::VirtMem::flushInstructionCache() doesn't have implementation for the target OS and compiler") + DebugUtils::unused(p, size); +#endif +} + +// Virtual Memory - Memory Info +// ============================ -VirtMem::Info VirtMem::info() noexcept { - static VirtMem::Info vmInfo; +Info info() noexcept { static std::atomic<uint32_t> vmInfoInitialized; + static Info vmInfo; if (!vmInfoInitialized.load()) { - VirtMem::Info localMemInfo; - VirtMem_getInfo(localMemInfo); + Info localMemInfo; + getVMInfo(localMemInfo); vmInfo = localMemInfo; vmInfoInitialized.store(1u); @@ -653,6 +698,24 @@ VirtMem::Info VirtMem::info() noexcept { return vmInfo; } -ASMJIT_END_NAMESPACE +// Virtual Memory - Hardened Runtime Info +// ====================================== + +HardenedRuntimeInfo hardenedRuntimeInfo() noexcept { + return HardenedRuntimeInfo { getHardenedRuntimeFlags() }; +} + +// Virtual Memory - Project JIT Memory +// =================================== + +void protectJitMemory(ProtectJitAccess access) noexcept { +#if defined(ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP) + pthread_jit_write_protect_np(static_cast<uint32_t>(access)); +#else + DebugUtils::unused(access); +#endif +} + +ASMJIT_END_SUB_NAMESPACE #endif diff --git a/src/asmjit/core/virtmem.h b/src/asmjit/core/virtmem.h index 07a2dff..50f0945 100644 --- a/src/asmjit/core/virtmem.h +++ b/src/asmjit/core/virtmem.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_VIRTMEM_H_INCLUDED #define ASMJIT_CORE_VIRTMEM_H_INCLUDED @@ -34,127 +16,222 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_virtual_memory //! \{ -// ============================================================================ -// [asmjit::VirtMem] -// ============================================================================ - //! Virtual memory management. namespace VirtMem { +//! Flushes instruction cache in the given region. +//! +//! Only useful on non-x86 architectures, however, it's a good practice to call it on any platform to make your +//! code more portable. +ASMJIT_API void flushInstructionCache(void* p, size_t size) noexcept; + +//! Virtual memory information. +struct Info { + //! Virtual memory page size. + uint32_t pageSize; + //! Virtual memory page granularity. + uint32_t pageGranularity; +}; + +//! Returns virtual memory information, see `VirtMem::Info` for more details. +ASMJIT_API Info info() noexcept; + //! Virtual memory access and mmap-specific flags. -enum Flags : uint32_t { - //! No access flags. - kAccessNone = 0x00000000u, +enum class MemoryFlags : uint32_t { + //! No flags. + kNone = 0, + //! Memory is readable. kAccessRead = 0x00000001u, + //! Memory is writable. kAccessWrite = 0x00000002u, + //! Memory is executable. kAccessExecute = 0x00000004u, - //! A combination of \ref kAccessRead and \ref kAccessWrite. + //! A combination of \ref MemoryFlags::kAccessRead and \ref MemoryFlags::kAccessWrite. kAccessReadWrite = kAccessRead | kAccessWrite, - //! A combination of \ref kAccessRead, \ref kAccessWrite. + + //! A combination of \ref MemoryFlags::kAccessRead, \ref MemoryFlags::kAccessWrite. kAccessRW = kAccessRead | kAccessWrite, - //! A combination of \ref kAccessRead and \ref kAccessExecute. + + //! A combination of \ref MemoryFlags::kAccessRead and \ref MemoryFlags::kAccessExecute. kAccessRX = kAccessRead | kAccessExecute, - //! A combination of \ref kAccessRead, \ref kAccessWrite, and \ref kAccessExecute. + + //! A combination of \ref MemoryFlags::kAccessRead, \ref MemoryFlags::kAccessWrite, and + //! \ref MemoryFlags::kAccessExecute. kAccessRWX = kAccessRead | kAccessWrite | kAccessExecute, - //! Use a `MAP_JIT` flag available on Apple platforms (introduced by Mojave), - //! which allows JIT code to be executed in MAC bundles. This flag is not turned - //! on by default, because when a process uses `fork()` the child process - //! has no access to the pages mapped with `MAP_JIT`, which could break code - //! that doesn't expect this behavior. + //! Use a `MAP_JIT` flag available on Apple platforms (introduced by Mojave), which allows JIT code to be executed + //! in MAC bundles. This flag is not turned on by default, because when a process uses `fork()` the child process + //! has no access to the pages mapped with `MAP_JIT`, which could break code that doesn't expect this behavior. + //! + //! \note This flag can only be used with \ref VirtMem::alloc(). kMMapEnableMapJit = 0x00000010u, //! Pass `PROT_MAX(PROT_READ)` to mmap() on platforms that support `PROT_MAX`. + //! + //! \note This flag can only be used with \ref VirtMem::alloc(). kMMapMaxAccessRead = 0x00000020u, //! Pass `PROT_MAX(PROT_WRITE)` to mmap() on platforms that support `PROT_MAX`. + //! + //! \note This flag can only be used with \ref VirtMem::alloc(). kMMapMaxAccessWrite = 0x00000040u, //! Pass `PROT_MAX(PROT_EXEC)` to mmap() on platforms that support `PROT_MAX`. + //! + //! \note This flag can only be used with \ref VirtMem::alloc(). kMMapMaxAccessExecute = 0x00000080u, - //! A combination of \ref kMMapMaxAccessRead and \ref kMMapMaxAccessWrite. + //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessWrite. kMMapMaxAccessReadWrite = kMMapMaxAccessRead | kMMapMaxAccessWrite, - //! A combination of \ref kMMapMaxAccessRead and \ref kMMapMaxAccessWrite. + + //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessWrite. kMMapMaxAccessRW = kMMapMaxAccessRead | kMMapMaxAccessWrite, - //! A combination of \ref kMMapMaxAccessRead and \ref kMMapMaxAccessExecute. + + //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessExecute. kMMapMaxAccessRX = kMMapMaxAccessRead | kMMapMaxAccessExecute, - //! A combination of \ref kMMapMaxAccessRead, \ref kMMapMaxAccessWrite, \ref kMMapMaxAccessExecute. + + //! A combination of \ref MemoryFlags::kMMapMaxAccessRead, \ref MemoryFlags::kMMapMaxAccessWrite, \ref + //! MemoryFlags::kMMapMaxAccessExecute. kMMapMaxAccessRWX = kMMapMaxAccessRead | kMMapMaxAccessWrite | kMMapMaxAccessExecute, - //! Not an access flag, only used by `allocDualMapping()` to override the - //! default allocation strategy to always use a 'tmp' directory instead of - //! "/dev/shm" (on POSIX platforms). Please note that this flag will be - //! ignored if the operating system allows to allocate an executable memory - //! by a different API than `open()` or `shm_open()`. For example on Linux - //! `memfd_create()` is preferred and on BSDs `shm_open(SHM_ANON, ...)` is - //! used if SHM_ANON is defined. + //! Not an access flag, only used by `allocDualMapping()` to override the default allocation strategy to always use + //! a 'tmp' directory instead of "/dev/shm" (on POSIX platforms). Please note that this flag will be ignored if the + //! operating system allows to allocate an executable memory by a different API than `open()` or `shm_open()`. For + //! example on Linux `memfd_create()` is preferred and on BSDs `shm_open(SHM_ANON, ...)` is used if SHM_ANON is + //! defined. + //! + //! \note This flag can only be used with \ref VirtMem::alloc(). kMappingPreferTmp = 0x80000000u }; +ASMJIT_DEFINE_ENUM_FLAGS(MemoryFlags) -//! Virtual memory information. -struct Info { - //! Virtual memory page size. - uint32_t pageSize; - //! Virtual memory page granularity. - uint32_t pageGranularity; -}; - -//! Dual memory mapping used to map an anonymous memory into two memory regions -//! where one region is read-only, but executable, and the second region is -//! read+write, but not executable. Please see \ref VirtMem::allocDualMapping() -//! for more details. -struct DualMapping { - //! Pointer to data with 'Read' or 'Read+Execute' access. - void* ro; - //! Pointer to data with 'Read-Write' access, but never 'Write+Execute'. - void* rw; -}; - -//! Returns virtual memory information, see `VirtMem::Info` for more details. -ASMJIT_API Info info() noexcept; - -//! Allocates virtual memory by either using `mmap()` (POSIX) or `VirtualAlloc()` -//! (Windows). +//! Allocates virtual memory by either using `mmap()` (POSIX) or `VirtualAlloc()` (Windows). //! -//! \note `size` should be aligned to page size, use \ref VirtMem::info() -//! to obtain it. Invalid size will not be corrected by the implementation -//! and the allocation would not succeed in such case. -ASMJIT_API Error alloc(void** p, size_t size, uint32_t flags) noexcept; +//! \note `size` should be aligned to page size, use \ref VirtMem::info() to obtain it. Invalid size will not be +//! corrected by the implementation and the allocation would not succeed in such case. +ASMJIT_API Error alloc(void** p, size_t size, MemoryFlags flags) noexcept; //! Releases virtual memory previously allocated by \ref VirtMem::alloc(). //! -//! \note The size must be the same as used by \ref VirtMem::alloc(). If the -//! size is not the same value the call will fail on any POSIX system, but -//! pass on Windows, because it's implemented differently. +//! \note The size must be the same as used by \ref VirtMem::alloc(). If the size is not the same value the call +//! will fail on any POSIX system, but pass on Windows, because it's implemented differently. ASMJIT_API Error release(void* p, size_t size) noexcept; -//! A cross-platform wrapper around `mprotect()` (POSIX) and `VirtualProtect()` -//! (Windows). -ASMJIT_API Error protect(void* p, size_t size, uint32_t flags) noexcept; +//! A cross-platform wrapper around `mprotect()` (POSIX) and `VirtualProtect()` (Windows). +ASMJIT_API Error protect(void* p, size_t size, MemoryFlags flags) noexcept; + +//! Dual memory mapping used to map an anonymous memory into two memory regions where one region is read-only, but +//! executable, and the second region is read+write, but not executable. See \ref VirtMem::allocDualMapping() for +//! more details. +struct DualMapping { + //! Pointer to data with 'Read+Execute' access (this memory is not writable). + void* rx; + //! Pointer to data with 'Read+Write' access (this memory is not executable). + void* rw; +}; -//! Allocates virtual memory and creates two views of it where the first view -//! has no write access. This is an addition to the API that should be used -//! in cases in which the operating system either enforces W^X security policy -//! or the application wants to use this policy by default to improve security -//! and prevent an accidental (or purposed) self-modifying code. +//! Allocates virtual memory and creates two views of it where the first view has no write access. This is an addition +//! to the API that should be used in cases in which the operating system either enforces W^X security policy or the +//! application wants to use this policy by default to improve security and prevent an accidental (or purposed) +//! self-modifying code. //! -//! The memory returned in the `dm` are two independent mappings of the same -//! shared memory region. You must use \ref VirtMem::releaseDualMapping() to -//! release it when it's no longer needed. Never use `VirtMem::release()` to -//! release the memory returned by `allocDualMapping()` as that would fail on -//! Windows. +//! The memory returned in the `dm` are two independent mappings of the same shared memory region. You must use +//! \ref VirtMem::releaseDualMapping() to release it when it's no longer needed. Never use `VirtMem::release()` to +//! release the memory returned by `allocDualMapping()` as that would fail on Windows. //! //! \remarks Both pointers in `dm` would be set to `nullptr` if the function fails. -ASMJIT_API Error allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) noexcept; +ASMJIT_API Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags flags) noexcept; //! Releases virtual memory mapping previously allocated by \ref VirtMem::allocDualMapping(). //! //! \remarks Both pointers in `dm` would be set to `nullptr` if the function succeeds. ASMJIT_API Error releaseDualMapping(DualMapping* dm, size_t size) noexcept; +//! Hardened runtime flags. +enum class HardenedRuntimeFlags : uint32_t { + //! No flags. + kNone = 0, + + //! Hardened runtime is enabled - it's not possible to have "Write & Execute" memory protection. The runtime + //! enforces W^X (either write or execute). + //! + //! \note If the runtime is hardened it means that an operating system specific protection is used. For example on + //! MacOS platform it's possible to allocate memory with MAP_JIT flag and then use `pthread_jit_write_protect_np()` + //! to temporarily swap access permissions for the current thread. Dual mapping is also a possibility on X86/X64 + //! architecture. + kEnabled = 0x00000001u, + + //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific). + kMapJit = 0x00000002u +}; +ASMJIT_DEFINE_ENUM_FLAGS(HardenedRuntimeFlags) + +//! Hardened runtime information. +struct HardenedRuntimeInfo { + //! Hardened runtime flags. + HardenedRuntimeFlags flags; +}; + +//! Returns runtime features provided by the OS. +ASMJIT_API HardenedRuntimeInfo hardenedRuntimeInfo() noexcept; + +//! Values that can be used with `protectJitMemory()` function. +enum class ProtectJitAccess : uint32_t { + //! Protect JIT memory with Read+Write permissions. + kReadWrite = 0, + //! Protect JIT memory with Read+Execute permissions. + kReadExecute = 1 +}; + +//! Protects access of memory mapped with MAP_JIT flag for the current thread. +//! +//! \note This feature is only available on Apple hardware (AArch64) at the moment and and uses a non-portable +//! `pthread_jit_write_protect_np()` call when available. +//! +//! This function must be called before and after a memory mapped with MAP_JIT flag is modified. Example: +//! +//! ``` +//! void* codePtr = ...; +//! size_t codeSize = ...; +//! +//! VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite); +//! memcpy(codePtr, source, codeSize); +//! VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute); +//! VirtMem::flushInstructionCache(codePtr, codeSize); +//! ``` +//! +//! See \ref ProtectJitReadWriteScope, which makes it simpler than the code above. +ASMJIT_API void protectJitMemory(ProtectJitAccess access) noexcept; + +//! JIT protection scope that prepares the given memory block to be written to in the current thread. +//! +//! It calls `VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite)` at construction time and +//! `VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute)` combined with `flushInstructionCache()` +//! in destructor. The purpose of this class is to make writing to JIT memory easier. +class ProtectJitReadWriteScope { +public: + void* _rxPtr; + size_t _size; + + //! Makes the given memory block RW protected. + ASMJIT_FORCE_INLINE ProtectJitReadWriteScope(void* rxPtr, size_t size) noexcept + : _rxPtr(rxPtr), + _size(size) { + protectJitMemory(ProtectJitAccess::kReadWrite); + } + + // Not copyable. + ProtectJitReadWriteScope(const ProtectJitReadWriteScope& other) = delete; + + //! Makes the memory block RX protected again and flushes instruction cache. + ASMJIT_FORCE_INLINE ~ProtectJitReadWriteScope() noexcept { + protectJitMemory(ProtectJitAccess::kReadExecute); + flushInstructionCache(_rxPtr, _size); + } +}; + } // VirtMem //! \} diff --git a/src/asmjit/core/zone.cpp b/src/asmjit/core/zone.cpp index 61f7cec..d68e110 100644 --- a/src/asmjit/core/zone.cpp +++ b/src/asmjit/core/zone.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/support.h" @@ -27,17 +9,15 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::Zone - Statics] -// ============================================================================ +// Zone - Globals +// ============== -// Zero size block used by `Zone` that doesn't have any memory allocated. -// Should be allocated in read-only memory and should never be modified. +// Zero size block used by `Zone` that doesn't have any memory allocated. Should be allocated in read-only memory +// and should never be modified. const Zone::Block Zone::_zeroBlock = { nullptr, nullptr, 0 }; -// ============================================================================ -// [asmjit::Zone - Init / Reset] -// ============================================================================ +// Zone - Init & Reset +// =================== void Zone::_init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept { ASMJIT_ASSERT(blockSize >= kMinBlockSize); @@ -66,28 +46,27 @@ void Zone::_init(size_t blockSize, size_t blockAlignment, const Support::Tempora } } -void Zone::reset(uint32_t resetPolicy) noexcept { +void Zone::reset(ResetPolicy resetPolicy) noexcept { Block* cur = _block; // Can't be altered. if (cur == &_zeroBlock) return; - if (resetPolicy == Globals::kResetHard) { + if (resetPolicy == ResetPolicy::kHard) { Block* initial = const_cast<Zone::Block*>(&_zeroBlock); _ptr = initial->data(); _end = initial->data(); _block = initial; - // Since cur can be in the middle of the double-linked list, we have to - // traverse both directions (`prev` and `next`) separately to visit all. + // Since cur can be in the middle of the double-linked list, we have to traverse both directions (`prev` and + // `next`) separately to visit all. Block* next = cur->next; do { Block* prev = cur->prev; - // If this is the first block and this ZoneTmp is temporary then the - // first block is statically allocated. We cannot free it and it makes - // sense to keep it even when this is hard reset. + // If this is the first block and this ZoneTmp is temporary then the first block is statically allocated. + // We cannot free it and it makes sense to keep it even when this is hard reset. if (prev == nullptr && _isTemporary) { cur->prev = nullptr; cur->next = nullptr; @@ -113,9 +92,8 @@ void Zone::reset(uint32_t resetPolicy) noexcept { } } -// ============================================================================ -// [asmjit::Zone - Alloc] -// ============================================================================ +// Zone - Alloc +// ============ void* Zone::_alloc(size_t size, size_t alignment) noexcept { Block* curBlock = _block; @@ -124,10 +102,9 @@ void* Zone::_alloc(size_t size, size_t alignment) noexcept { size_t rawBlockAlignment = blockAlignment(); size_t minimumAlignment = Support::max<size_t>(alignment, rawBlockAlignment); - // If the `Zone` has been cleared the current block doesn't have to be the - // last one. Check if there is a block that can be used instead of allocating - // a new one. If there is a `next` block it's completely unused, we don't have - // to check for remaining bytes in that case. + // If the `Zone` has been cleared the current block doesn't have to be the last one. Check if there is a block + // that can be used instead of allocating a new one. If there is a `next` block it's completely unused, we don't + // have to check for remaining bytes in that case. if (next) { uint8_t* ptr = Support::alignUp(next->data(), minimumAlignment); uint8_t* end = Support::alignDown(next->data() + next->size, rawBlockAlignment); @@ -147,18 +124,16 @@ void* Zone::_alloc(size_t size, size_t alignment) noexcept { if (ASMJIT_UNLIKELY(newSize > SIZE_MAX - kBlockSize - blockAlignmentOverhead)) return nullptr; - // Allocate new block - we add alignment overhead to `newSize`, which becomes the - // new block size, and we also add `kBlockOverhead` to the allocator as it includes - // members of `Zone::Block` structure. + // Allocate new block - we add alignment overhead to `newSize`, which becomes the new block size, and we also add + // `kBlockOverhead` to the allocator as it includes members of `Zone::Block` structure. newSize += blockAlignmentOverhead; Block* newBlock = static_cast<Block*>(::malloc(newSize + kBlockSize)); if (ASMJIT_UNLIKELY(!newBlock)) return nullptr; - // Align the pointer to `minimumAlignment` and adjust the size of this block - // accordingly. It's the same as using `minimumAlignment - Support::alignUpDiff()`, - // just written differently. + // Align the pointer to `minimumAlignment` and adjust the size of this block accordingly. It's the same as using + // `minimumAlignment - Support::alignUpDiff()`, just written differently. { newBlock->prev = nullptr; newBlock->next = nullptr; @@ -168,9 +143,8 @@ void* Zone::_alloc(size_t size, size_t alignment) noexcept { newBlock->prev = curBlock; curBlock->next = newBlock; - // Does only happen if there is a next block, but the requested memory - // can't fit into it. In this case a new buffer is allocated and inserted - // between the current block and the next one. + // Does only happen if there is a next block, but the requested memory can't fit into it. In this case a new + // buffer is allocated and inserted between the current block and the next one. if (next) { newBlock->next = next; next->prev = newBlock; @@ -226,9 +200,8 @@ char* Zone::sformat(const char* fmt, ...) noexcept { return static_cast<char*>(dup(buf, size)); } -// ============================================================================ -// [asmjit::ZoneAllocator - Helpers] -// ============================================================================ +// ZoneAllocator - Utilities +// ========================= #if defined(ASMJIT_BUILD_DEBUG) static bool ZoneAllocator_hasDynamicBlock(ZoneAllocator* self, ZoneAllocator::DynamicBlock* block) noexcept { @@ -242,9 +215,8 @@ static bool ZoneAllocator_hasDynamicBlock(ZoneAllocator* self, ZoneAllocator::Dy } #endif -// ============================================================================ -// [asmjit::ZoneAllocator - Init / Reset] -// ============================================================================ +// ZoneAllocator - Init & Reset +// ============================ void ZoneAllocator::reset(Zone* zone) noexcept { // Free dynamic blocks. @@ -260,9 +232,8 @@ void ZoneAllocator::reset(Zone* zone) noexcept { _zone = zone; } -// ============================================================================ -// [asmjit::ZoneAllocator - Alloc / Release] -// ============================================================================ +// asmjit::ZoneAllocator - Alloc & Release +// ======================================= void* ZoneAllocator::_alloc(size_t size, size_t& allocatedSize) noexcept { ASMJIT_ASSERT(isInitialized()); diff --git a/src/asmjit/core/zone.h b/src/asmjit/core/zone.h index 8947519..eaea252 100644 --- a/src/asmjit/core/zone.h +++ b/src/asmjit/core/zone.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ZONE_H_INCLUDED #define ASMJIT_CORE_ZONE_H_INCLUDED @@ -31,20 +13,14 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::Zone] -// ============================================================================ - //! Zone memory. //! -//! Zone is an incremental memory allocator that allocates memory by simply -//! incrementing a pointer. It allocates blocks of memory by using C's `malloc()`, -//! but divides these blocks into smaller segments requested by calling +//! Zone is an incremental memory allocator that allocates memory by simply incrementing a pointer. It allocates +//! blocks of memory by using C's `malloc()`, but divides these blocks into smaller segments requested by calling //! `Zone::alloc()` and friends. //! -//! Zone has no function to release the allocated memory. It has to be released -//! all at once by calling `reset()`. If you need a more friendly allocator that -//! also supports `release()`, consider using `Zone` with `ZoneAllocator`. +//! Zone has no function to release the allocated memory. It has to be released all at once by calling `reset()`. +//! If you need a more friendly allocator that also supports `release()`, consider using `Zone` with `ZoneAllocator`. class Zone { public: ASMJIT_NONCOPYABLE(Zone) @@ -103,28 +79,31 @@ public: //! Creates a new Zone. //! - //! The `blockSize` parameter describes the default size of the block. If the - //! `size` parameter passed to `alloc()` is greater than the default size - //! `Zone` will allocate and use a larger block, but it will not change the + //! The `blockSize` parameter describes the default size of the block. If the `size` parameter passed to `alloc()` + //! is greater than the default size `Zone` will allocate and use a larger block, but it will not change the //! default `blockSize`. //! - //! It's not required, but it's good practice to set `blockSize` to a - //! reasonable value that depends on the usage of `Zone`. Greater block sizes - //! are generally safer and perform better than unreasonably low block sizes. - ASMJIT_INLINE explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept { + //! It's not required, but it's good practice to set `blockSize` to a reasonable value that depends on the usage + //! of `Zone`. Greater block sizes are generally safer and perform better than unreasonably low block sizes. + inline explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept { _init(blockSize, blockAlignment, nullptr); } - ASMJIT_INLINE Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept { + //! Creates a new Zone with a first block pointing to a `temporary` memory. + inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept { _init(blockSize, blockAlignment, &temporary); } + //! \overload + inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept { + _init(blockSize, blockAlignment, temporary); + } + //! Moves an existing `Zone`. //! - //! \note You cannot move an existing `ZoneTmp` as it uses embedded storage. - //! Attempting to move `ZoneTmp` would result in assertion failure in debug - //! mode and undefined behavior in release mode. - ASMJIT_INLINE Zone(Zone&& other) noexcept + //! \note You cannot move an existing `ZoneTmp` as it uses embedded storage. Attempting to move `ZoneTmp` would + //! result in assertion failure in debug mode and undefined behavior in release mode. + inline Zone(Zone&& other) noexcept : _ptr(other._ptr), _end(other._end), _block(other._block), @@ -137,16 +116,16 @@ public: //! Destroys the `Zone` instance. //! - //! This will destroy the `Zone` instance and release all blocks of memory - //! allocated by it. It performs implicit `reset(Globals::kResetHard)`. - ASMJIT_INLINE ~Zone() noexcept { reset(Globals::kResetHard); } + //! This will destroy the `Zone` instance and release all blocks of memory allocated by it. It performs implicit + //! `reset(ResetPolicy::kHard)`. + inline ~Zone() noexcept { reset(ResetPolicy::kHard); } ASMJIT_API void _init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept; //! Resets the `Zone` invalidating all blocks allocated. //! //! See `Globals::ResetPolicy` for more details. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; + ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept; //! \} @@ -154,29 +133,28 @@ public: //! \{ //! Tests whether this `Zone` is actually a `ZoneTmp` that uses temporary memory. - ASMJIT_INLINE bool isTemporary() const noexcept { return _isTemporary != 0; } + inline bool isTemporary() const noexcept { return _isTemporary != 0; } //! Returns the default block size. - ASMJIT_INLINE size_t blockSize() const noexcept { return _blockSize; } + inline size_t blockSize() const noexcept { return _blockSize; } //! Returns the default block alignment. - ASMJIT_INLINE size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; } + inline size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; } //! Returns remaining size of the current block. - ASMJIT_INLINE size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); } + inline size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); } //! Returns the current zone cursor (dangerous). //! - //! This is a function that can be used to get exclusive access to the current - //! block's memory buffer. + //! This is a function that can be used to get exclusive access to the current block's memory buffer. template<typename T = uint8_t> - ASMJIT_INLINE T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); } + inline T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); } //! Returns the end of the current zone block, only useful if you use `ptr()`. template<typename T = uint8_t> - ASMJIT_INLINE T* end() noexcept { return reinterpret_cast<T*>(_end); } + inline T* end() noexcept { return reinterpret_cast<T*>(_end); } //! Sets the current zone pointer to `ptr` (must be within the current block). template<typename T> - ASMJIT_INLINE void setPtr(T* ptr) noexcept { + inline void setPtr(T* ptr) noexcept { uint8_t* p = reinterpret_cast<uint8_t*>(ptr); ASMJIT_ASSERT(p >= _ptr && p <= _end); _ptr = p; @@ -184,7 +162,7 @@ public: //! Sets the end zone pointer to `end` (must be within the current block). template<typename T> - ASMJIT_INLINE void setEnd(T* end) noexcept { + inline void setEnd(T* end) noexcept { uint8_t* p = reinterpret_cast<uint8_t*>(end); ASMJIT_ASSERT(p >= _ptr && p <= _end); _end = p; @@ -195,7 +173,7 @@ public: //! \name Utilities //! \{ - ASMJIT_INLINE void swap(Zone& other) noexcept { + inline void swap(Zone& other) noexcept { // This could lead to a disaster. ASMJIT_ASSERT(!this->isTemporary()); ASMJIT_ASSERT(!other.isTemporary()); @@ -207,30 +185,29 @@ public: } //! Aligns the current pointer to `alignment`. - ASMJIT_INLINE void align(size_t alignment) noexcept { + inline void align(size_t alignment) noexcept { _ptr = Support::min(Support::alignUp(_ptr, alignment), _end); } //! Ensures the remaining size is at least equal or greater than `size`. //! - //! \note This function doesn't respect any alignment. If you need to ensure - //! there is enough room for an aligned allocation you need to call `align()` - //! before calling `ensure()`. - ASMJIT_INLINE Error ensure(size_t size) noexcept { + //! \note This function doesn't respect any alignment. If you need to ensure there is enough room for an aligned + //! allocation you need to call `align()` before calling `ensure()`. + inline Error ensure(size_t size) noexcept { if (size <= remainingSize()) return kErrorOk; else return _alloc(0, 1) ? kErrorOk : DebugUtils::errored(kErrorOutOfMemory); } - ASMJIT_INLINE void _assignBlock(Block* block) noexcept { + inline void _assignBlock(Block* block) noexcept { size_t alignment = blockAlignment(); _ptr = Support::alignUp(block->data(), alignment); _end = Support::alignDown(block->data() + block->size, alignment); _block = block; } - ASMJIT_INLINE void _assignZeroBlock() noexcept { + inline void _assignZeroBlock() noexcept { Block* block = const_cast<Block*>(&_zeroBlock); _ptr = block->data(); _end = block->data(); @@ -244,9 +221,8 @@ public: //! Allocates the requested memory specified by `size`. //! - //! Pointer returned is valid until the `Zone` instance is destroyed or reset - //! by calling `reset()`. If you plan to make an instance of C++ from the - //! given pointer use placement `new` and `delete` operators: + //! Pointer returned is valid until the `Zone` instance is destroyed or reset by calling `reset()`. If you plan to + //! make an instance of C++ from the given pointer use placement `new` and `delete` operators: //! //! ``` //! using namespace asmjit; @@ -274,7 +250,7 @@ public: //! // Reset or destroy `Zone`. //! zone.reset(); //! ``` - ASMJIT_INLINE void* alloc(size_t size) noexcept { + inline void* alloc(size_t size) noexcept { if (ASMJIT_UNLIKELY(size > remainingSize())) return _alloc(size, 1); @@ -284,7 +260,7 @@ public: } //! Allocates the requested memory specified by `size` and `alignment`. - ASMJIT_INLINE void* alloc(size_t size, size_t alignment) noexcept { + inline void* alloc(size_t size, size_t alignment) noexcept { ASMJIT_ASSERT(Support::isPowerOf2(alignment)); uint8_t* ptr = Support::alignUp(_ptr, alignment); @@ -298,7 +274,7 @@ public: //! Allocates the requested memory specified by `size` without doing any checks. //! //! Can only be called if `remainingSize()` returns size at least equal to `size`. - ASMJIT_INLINE void* allocNoCheck(size_t size) noexcept { + inline void* allocNoCheck(size_t size) noexcept { ASMJIT_ASSERT(remainingSize() >= size); uint8_t* ptr = _ptr; @@ -309,7 +285,7 @@ public: //! Allocates the requested memory specified by `size` and `alignment` without doing any checks. //! //! Performs the same operation as `Zone::allocNoCheck(size)` with `alignment` applied. - ASMJIT_INLINE void* allocNoCheck(size_t size, size_t alignment) noexcept { + inline void* allocNoCheck(size_t size, size_t alignment) noexcept { ASMJIT_ASSERT(Support::isPowerOf2(alignment)); uint8_t* ptr = Support::alignUp(_ptr, alignment); @@ -324,25 +300,25 @@ public: //! Like `alloc()`, but the return pointer is casted to `T*`. template<typename T> - ASMJIT_INLINE T* allocT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept { + inline T* allocT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept { return static_cast<T*>(alloc(size, alignment)); } //! Like `allocNoCheck()`, but the return pointer is casted to `T*`. template<typename T> - ASMJIT_INLINE T* allocNoCheckT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept { + inline T* allocNoCheckT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept { return static_cast<T*>(allocNoCheck(size, alignment)); } //! Like `allocZeroed()`, but the return pointer is casted to `T*`. template<typename T> - ASMJIT_INLINE T* allocZeroedT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept { + inline T* allocZeroedT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept { return static_cast<T*>(allocZeroed(size, alignment)); } //! Like `new(std::nothrow) T(...)`, but allocated by `Zone`. template<typename T> - ASMJIT_INLINE T* newT() noexcept { + inline T* newT() noexcept { void* p = alloc(sizeof(T), alignof(T)); if (ASMJIT_UNLIKELY(!p)) return nullptr; @@ -351,7 +327,7 @@ public: //! Like `new(std::nothrow) T(...)`, but allocated by `Zone`. template<typename T, typename... Args> - ASMJIT_INLINE T* newT(Args&&... args) noexcept { + inline T* newT(Args&&... args) noexcept { void* p = alloc(sizeof(T), alignof(T)); if (ASMJIT_UNLIKELY(!p)) return nullptr; @@ -368,7 +344,7 @@ public: ASMJIT_API void* dup(const void* data, size_t size, bool nullTerminate = false) noexcept; //! Helper to duplicate data. - ASMJIT_INLINE void* dupAligned(const void* data, size_t size, size_t alignment, bool nullTerminate = false) noexcept { + inline void* dupAligned(const void* data, size_t size, size_t alignment, bool nullTerminate = false) noexcept { align(alignment); return dup(data, size, nullTerminate); } @@ -379,15 +355,10 @@ public: //! \} }; -// ============================================================================ -// [b2d::ZoneTmp] -// ============================================================================ - //! \ref Zone with `N` bytes of a static storage, used for the initial block. //! -//! Temporary zones are used in cases where it's known that some memory will be -//! required, but in many cases it won't exceed N bytes, so the whole operation -//! can be performed without a dynamic memory allocation. +//! Temporary zones are used in cases where it's known that some memory will be required, but in many cases it won't +//! exceed N bytes, so the whole operation can be performed without a dynamic memory allocation. template<size_t N> class ZoneTmp : public Zone { public: @@ -399,35 +370,29 @@ public: } _storage; //! Creates a temporary zone. Dynamic block size is specified by `blockSize`. - ASMJIT_INLINE explicit ZoneTmp(size_t blockSize, size_t blockAlignment = 1) noexcept + inline explicit ZoneTmp(size_t blockSize, size_t blockAlignment = 1) noexcept : Zone(blockSize, blockAlignment, Support::Temporary(_storage.data, N)) {} }; -// ============================================================================ -// [asmjit::ZoneAllocator] -// ============================================================================ - -//! Zone-based memory allocator that uses an existing `Zone` and provides a -//! `release()` functionality on top of it. It uses `Zone` only for chunks -//! that can be pooled, and uses libc `malloc()` for chunks that are large. +//! Zone-based memory allocator that uses an existing `Zone` and provides a `release()` functionality on top of it. +//! It uses `Zone` only for chunks that can be pooled, and uses libc `malloc()` for chunks that are large. //! -//! The advantage of ZoneAllocator is that it can allocate small chunks of memory -//! really fast, and these chunks, when released, will be reused by consecutive -//! calls to `alloc()`. Also, since ZoneAllocator uses `Zone`, you can turn any -//! `Zone` into a `ZoneAllocator`, and use it in your `Pass` when necessary. +//! The advantage of ZoneAllocator is that it can allocate small chunks of memory really fast, and these chunks, +//! when released, will be reused by consecutive calls to `alloc()`. Also, since ZoneAllocator uses `Zone`, you can +//! turn any `Zone` into a `ZoneAllocator`, and use it in your `Pass` when necessary. //! -//! ZoneAllocator is used by AsmJit containers to make containers having only -//! few elements fast (and lightweight) and to allow them to grow and use -//! dynamic blocks when require more storage. +//! ZoneAllocator is used by AsmJit containers to make containers having only few elements fast (and lightweight) +//! and to allow them to grow and use dynamic blocks when require more storage. class ZoneAllocator { public: ASMJIT_NONCOPYABLE(ZoneAllocator) //! \cond INTERNAL - enum { - // In short, we pool chunks of these sizes: - // [32, 64, 96, 128, 192, 256, 320, 384, 448, 512] + // In short, we pool chunks of these sizes: + // [32, 64, 96, 128, 192, 256, 320, 384, 448, 512] + + enum : uint32_t { //! How many bytes per a low granularity pool (has to be at least 16). kLoGranularity = 32, //! Number of slots of a low granularity pool. @@ -452,9 +417,8 @@ public: Slot* next; }; - //! A block of memory that has been allocated dynamically and is not part of - //! block-list used by the allocator. This is used to keep track of all these - //! blocks so they can be freed by `reset()` if not freed explicitly. + //! A block of memory that has been allocated dynamically and is not part of block-list used by the allocator. + //! This is used to keep track of all these blocks so they can be freed by `reset()` if not freed explicitly. struct DynamicBlock { DynamicBlock* prev; DynamicBlock* next; @@ -462,6 +426,9 @@ public: //! \endcond + //! \name Members + //! \{ + //! Zone used to allocate memory that fits into slots. Zone* _zone; //! Indexed slots containing released memory. @@ -469,6 +436,8 @@ public: //! Dynamic blocks for larger allocations (no slots). DynamicBlock* _dynamicBlocks; + //! \} + //! \name Construction & Destruction //! \{ @@ -496,9 +465,9 @@ public: //! It's the same as calling `reset(zone)`. inline void init(Zone* zone) noexcept { reset(zone); } - //! Resets this `ZoneAllocator` and also forget about the current `Zone` which - //! is attached (if any). Reset optionally attaches a new `zone` passed, or - //! keeps the `ZoneAllocator` in an uninitialized state, if `zone` is null. + //! Resets this `ZoneAllocator` and also forget about the current `Zone` which is attached (if any). Reset + //! optionally attaches a new `zone` passed, or keeps the `ZoneAllocator` in an uninitialized state, if + //! `zone` is null. ASMJIT_API void reset(Zone* zone = nullptr) noexcept; //! \} @@ -506,8 +475,7 @@ public: //! \name Accessors //! \{ - //! Returns the assigned `Zone` of this allocator or null if this `ZoneAllocator` - //! is not initialized. + //! Returns the assigned `Zone` of this allocator or null if this `ZoneAllocator` is not initialized. inline Zone* zone() const noexcept { return _zone; } //! \} @@ -516,10 +484,10 @@ public: //! \name Internals //! \{ - //! Returns the slot index to be used for `size`. Returns `true` if a valid slot - //! has been written to `slot` and `allocatedSize` has been filled with slot - //! exact size (`allocatedSize` can be equal or slightly greater than `size`). - static ASMJIT_INLINE bool _getSlotIndex(size_t size, uint32_t& slot) noexcept { + //! Returns the slot index to be used for `size`. Returns `true` if a valid slot has been written to `slot` and + //! `allocatedSize` has been filled with slot exact size (`allocatedSize` can be equal or slightly greater than + //! `size`). + static inline bool _getSlotIndex(size_t size, uint32_t& slot) noexcept { ASMJIT_ASSERT(size > 0); if (size > kHiMaxSize) return false; @@ -533,7 +501,7 @@ public: } //! \overload - static ASMJIT_INLINE bool _getSlotIndex(size_t size, uint32_t& slot, size_t& allocatedSize) noexcept { + static inline bool _getSlotIndex(size_t size, uint32_t& slot, size_t& allocatedSize) noexcept { ASMJIT_ASSERT(size > 0); if (size > kHiMaxSize) return false; @@ -571,9 +539,8 @@ public: return _alloc(size, allocatedSize); } - //! Like `alloc(size)`, but provides a second argument `allocatedSize` that - //! provides a way to know how big the block returned actually is. This is - //! useful for containers to prevent growing too early. + //! Like `alloc(size)`, but provides a second argument `allocatedSize` that provides a way to know how big + //! the block returned actually is. This is useful for containers to prevent growing too early. inline void* alloc(size_t size, size_t& allocatedSize) noexcept { ASMJIT_ASSERT(isInitialized()); return _alloc(size, allocatedSize); @@ -621,9 +588,8 @@ public: return new(p) T(std::forward<Args>(args)...); } - //! Releases the memory previously allocated by `alloc()`. The `size` argument - //! has to be the same as used to call `alloc()` or `allocatedSize` returned - //! by `alloc()`. + //! Releases the memory previously allocated by `alloc()`. The `size` argument has to be the same as used to call + //! `alloc()` or `allocatedSize` returned by `alloc()`. inline void release(void* p, size_t size) noexcept { ASMJIT_ASSERT(isInitialized()); ASMJIT_ASSERT(p != nullptr); diff --git a/src/asmjit/core/zonehash.cpp b/src/asmjit/core/zonehash.cpp index fb48d85..3778fbe 100644 --- a/src/asmjit/core/zonehash.cpp +++ b/src/asmjit/core/zonehash.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/support.h" @@ -28,9 +10,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ZoneHashBase - Helpers] -// ============================================================================ +// ZoneHashBase - Prime Numbers +// ============================ #define ASMJIT_POPULATE_PRIMES(ENTRY) \ ENTRY(2 , 0x80000000, 32), /* [N * 0x80000000 >> 32] (rcp=2147483648) */ \ @@ -183,9 +164,8 @@ static const uint8_t ZoneHash_primeShift[] = { #undef E }; -// ============================================================================ -// [asmjit::ZoneHashBase - Rehash] -// ============================================================================ +// ZoneHashBase - Rehash +// ===================== void ZoneHashBase::_rehash(ZoneAllocator* allocator, uint32_t primeIndex) noexcept { ASMJIT_ASSERT(primeIndex < ASMJIT_ARRAY_SIZE(ZoneHash_primeArray)); @@ -225,9 +205,8 @@ void ZoneHashBase::_rehash(ZoneAllocator* allocator, uint32_t primeIndex) noexce allocator->release(oldData, oldCount * sizeof(ZoneHashNode*)); } -// ============================================================================ -// [asmjit::ZoneHashBase - Ops] -// ============================================================================ +// ZoneHashBase - Operations +// ========================= ZoneHashNode* ZoneHashBase::_insert(ZoneAllocator* allocator, ZoneHashNode* node) noexcept { uint32_t hashMod = _calcMod(node->_hashCode); @@ -266,9 +245,8 @@ ZoneHashNode* ZoneHashBase::_remove(ZoneAllocator* allocator, ZoneHashNode* node return nullptr; } -// ============================================================================ -// [asmjit::ZoneHash - Unit] -// ============================================================================ +// ZoneHashBase - Tests +// ==================== #if defined(ASMJIT_TEST) struct MyHashNode : public ZoneHashNode { diff --git a/src/asmjit/core/zonehash.h b/src/asmjit/core/zonehash.h index dbad427..f332290 100644 --- a/src/asmjit/core/zonehash.h +++ b/src/asmjit/core/zonehash.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ZONEHASH_H_INCLUDED #define ASMJIT_CORE_ZONEHASH_H_INCLUDED @@ -31,14 +13,9 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::ZoneHashNode] -// ============================================================================ - //! Node used by \ref ZoneHash template. //! -//! You must provide function `bool eq(const Key& key)` in order to make -//! `ZoneHash::get()` working. +//! You must provide function `bool eq(const Key& key)` in order to make `ZoneHash::get()` working. class ZoneHashNode { public: ASMJIT_NONCOPYABLE(ZoneHashNode) @@ -56,10 +33,6 @@ public: uint32_t _customData; }; -// ============================================================================ -// [asmjit::ZoneHashBase] -// ============================================================================ - //! Base class used by \ref ZoneHash template class ZoneHashBase { public: @@ -162,16 +135,11 @@ public: //! \} }; -// ============================================================================ -// [asmjit::ZoneHash] -// ============================================================================ - //! Low-level hash table specialized for storing string keys and POD values. //! -//! This hash table allows duplicates to be inserted (the API is so low -//! level that it's up to you if you allow it or not, as you should first -//! `get()` the node and then modify it or insert a new node by using `insert()`, -//! depending on the intention). +//! This hash table allows duplicates to be inserted (the API is so low level that it's up to you if you allow it or +//! not, as you should first `get()` the node and then modify it or insert a new node by using `insert()`, depending +//! on the intention). template<typename NodeT> class ZoneHash : public ZoneHashBase { public: diff --git a/src/asmjit/core/zonelist.cpp b/src/asmjit/core/zonelist.cpp index 3496aa8..d4b311d 100644 --- a/src/asmjit/core/zonelist.cpp +++ b/src/asmjit/core/zonelist.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/zone.h" @@ -27,9 +9,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ZoneList - Unit] -// ============================================================================ +// ZoneList - Tests +// ================ #if defined(ASMJIT_TEST) class MyListNode : public ZoneListNode<MyListNode> {}; diff --git a/src/asmjit/core/zonelist.h b/src/asmjit/core/zonelist.h index d7fb1dd..c5e0013 100644 --- a/src/asmjit/core/zonelist.h +++ b/src/asmjit/core/zonelist.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ZONELIST_H_INCLUDED #define ASMJIT_CORE_ZONELIST_H_INCLUDED @@ -31,17 +13,28 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::ZoneListNode] -// ============================================================================ - //! Node used by \ref ZoneList template. template<typename NodeT> class ZoneListNode { public: ASMJIT_NONCOPYABLE(ZoneListNode) - NodeT* _listNodes[Globals::kLinkCount]; + //! \name Constants + //! \{ + + enum : size_t { + kNodeIndexPrev = 0, + kNodeIndexNext = 1 + }; + + //! \} + + //! \name Members + //! \{ + + NodeT* _listNodes[2]; + + //! \} //! \name Construction & Destruction //! \{ @@ -57,26 +50,37 @@ public: //! \name Accessors //! \{ - inline bool hasPrev() const noexcept { return _listNodes[Globals::kLinkPrev] != nullptr; } - inline bool hasNext() const noexcept { return _listNodes[Globals::kLinkNext] != nullptr; } + inline bool hasPrev() const noexcept { return _listNodes[kNodeIndexPrev] != nullptr; } + inline bool hasNext() const noexcept { return _listNodes[kNodeIndexNext] != nullptr; } - inline NodeT* prev() const noexcept { return _listNodes[Globals::kLinkPrev]; } - inline NodeT* next() const noexcept { return _listNodes[Globals::kLinkNext]; } + inline NodeT* prev() const noexcept { return _listNodes[kNodeIndexPrev]; } + inline NodeT* next() const noexcept { return _listNodes[kNodeIndexNext]; } //! \} }; -// ============================================================================ -// [asmjit::ZoneList<T>] -// ============================================================================ - //! Zone allocated list container that uses nodes of `NodeT` type. template <typename NodeT> class ZoneList { public: ASMJIT_NONCOPYABLE(ZoneList) - NodeT* _nodes[Globals::kLinkCount]; + //! \name Constants + //! \{ + + enum : size_t { + kNodeIndexFirst = 0, + kNodeIndexLast = 1 + }; + + //! \} + + //! \name Members + //! \{ + + NodeT* _nodes[2]; + + //! \} //! \name Construction & Destruction //! \{ @@ -98,8 +102,8 @@ public: //! \{ inline bool empty() const noexcept { return _nodes[0] == nullptr; } - inline NodeT* first() const noexcept { return _nodes[Globals::kLinkFirst]; } - inline NodeT* last() const noexcept { return _nodes[Globals::kLinkLast]; } + inline NodeT* first() const noexcept { return _nodes[kNodeIndexFirst]; } + inline NodeT* last() const noexcept { return _nodes[kNodeIndexLast]; } //! \} @@ -140,11 +144,11 @@ public: node->_listNodes[ dir] = next; } - inline void append(NodeT* node) noexcept { _addNode(node, Globals::kLinkLast); } - inline void prepend(NodeT* node) noexcept { _addNode(node, Globals::kLinkFirst); } + inline void append(NodeT* node) noexcept { _addNode(node, kNodeIndexLast); } + inline void prepend(NodeT* node) noexcept { _addNode(node, kNodeIndexFirst); } - inline void insertAfter(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, Globals::kLinkNext); } - inline void insertBefore(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, Globals::kLinkPrev); } + inline void insertAfter(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexNext); } + inline void insertBefore(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexPrev); } inline NodeT* unlink(NodeT* node) noexcept { NodeT* prev = node->prev(); diff --git a/src/asmjit/core/zonestack.cpp b/src/asmjit/core/zonestack.cpp index 52841b5..77e6f20 100644 --- a/src/asmjit/core/zonestack.cpp +++ b/src/asmjit/core/zonestack.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/zone.h" @@ -27,15 +9,14 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ZoneStackBase - Init / Reset] -// ============================================================================ +// ZoneStackBase - Init & Reset +// ============================ Error ZoneStackBase::_init(ZoneAllocator* allocator, size_t middleIndex) noexcept { ZoneAllocator* oldAllocator = _allocator; if (oldAllocator) { - Block* block = _block[Globals::kLinkFirst]; + Block* block = _block[kBlockIndexFirst]; while (block) { Block* next = block->next(); oldAllocator->release(block, kBlockSize); @@ -43,8 +24,8 @@ Error ZoneStackBase::_init(ZoneAllocator* allocator, size_t middleIndex) noexcep } _allocator = nullptr; - _block[Globals::kLinkLeft] = nullptr; - _block[Globals::kLinkRight] = nullptr; + _block[kBlockIndexFirst] = nullptr; + _block[kBlockIndexLast] = nullptr; } if (allocator) { @@ -52,22 +33,21 @@ Error ZoneStackBase::_init(ZoneAllocator* allocator, size_t middleIndex) noexcep if (ASMJIT_UNLIKELY(!block)) return DebugUtils::errored(kErrorOutOfMemory); - block->_link[Globals::kLinkLeft] = nullptr; - block->_link[Globals::kLinkRight] = nullptr; + block->_link[kBlockIndexPrev] = nullptr; + block->_link[kBlockIndexNext] = nullptr; block->_start = (uint8_t*)block + middleIndex; block->_end = (uint8_t*)block + middleIndex; _allocator = allocator; - _block[Globals::kLinkLeft] = block; - _block[Globals::kLinkRight] = block; + _block[kBlockIndexFirst] = block; + _block[kBlockIndexLast] = block; } return kErrorOk; } -// ============================================================================ -// [asmjit::ZoneStackBase - Ops] -// ============================================================================ +// ZoneStackBase - Operations +// ========================== Error ZoneStackBase::_prepareBlock(uint32_t side, size_t initialIndex) noexcept { ASMJIT_ASSERT(isInitialized()); @@ -109,9 +89,8 @@ void ZoneStackBase::_cleanupBlock(uint32_t side, size_t middleIndex) noexcept { } } -// ============================================================================ -// [asmjit::ZoneStack - Unit] -// ============================================================================ +// ZoneStack - Tests +// ================= #if defined(ASMJIT_TEST) template<typename T> diff --git a/src/asmjit/core/zonestack.h b/src/asmjit/core/zonestack.h index e2aaa6f..aea7b68 100644 --- a/src/asmjit/core/zonestack.h +++ b/src/asmjit/core/zonestack.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ZONESTACK_H_INCLUDED #define ASMJIT_CORE_ZONESTACK_H_INCLUDED @@ -31,24 +13,43 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::ZoneStackBase] -// ============================================================================ - //! Base class used by \ref ZoneStack. class ZoneStackBase { public: ASMJIT_NONCOPYABLE(ZoneStackBase) - static constexpr uint32_t kBlockSize = ZoneAllocator::kHiMaxSize; + //! \name Constants + //! \{ + + enum : size_t { + kBlockIndexPrev = 0, + kBlockIndexNext = 1, + + kBlockIndexFirst = 0, + kBlockIndexLast = 1, + + kBlockSize = ZoneAllocator::kHiMaxSize + }; + + //! \} + + //! \name Types + //! \{ struct Block { + //! Next and previous blocks. + Block* _link[2]; + //! Pointer to the start of the array. + void* _start; + //! Pointer to the end of the array. + void* _end; + inline bool empty() const noexcept { return _start == _end; } - inline Block* prev() const noexcept { return _link[Globals::kLinkLeft]; } - inline Block* next() const noexcept { return _link[Globals::kLinkRight]; } + inline Block* prev() const noexcept { return _link[kBlockIndexPrev]; } + inline Block* next() const noexcept { return _link[kBlockIndexNext]; } - inline void setPrev(Block* block) noexcept { _link[Globals::kLinkLeft] = block; } - inline void setNext(Block* block) noexcept { _link[Globals::kLinkRight] = block; } + inline void setPrev(Block* block) noexcept { _link[kBlockIndexPrev] = block; } + inline void setNext(Block* block) noexcept { _link[kBlockIndexNext] = block; } template<typename T> inline T* start() const noexcept { return static_cast<T*>(_start); } @@ -74,18 +75,21 @@ public: return (uintptr_t)_end <= ((uintptr_t)this + kEndBlockIndex - sizeof(T)); } - - Block* _link[Globals::kLinkCount]; //!< Next and previous blocks. - void* _start; //!< Pointer to the start of the array. - void* _end; //!< Pointer to the end of the array. }; + //! \} + + //! \name Members + //! \{ + //! Allocator used to allocate data. ZoneAllocator* _allocator; //! First and last blocks. - Block* _block[Globals::kLinkCount]; + Block* _block[2]; - //! \name Construction / Destruction + //! \} + + //! \name Construction & Destruction //! \{ inline ZoneStackBase() noexcept { @@ -125,16 +129,15 @@ public: //! \endcond }; -// ============================================================================ -// [asmjit::ZoneStack<T>] -// ============================================================================ - //! Zone allocated stack container. template<typename T> class ZoneStack : public ZoneStackBase { public: ASMJIT_NONCOPYABLE(ZoneStack) + //! \name Constants + //! \{ + enum : uint32_t { kNumBlockItems = uint32_t((kBlockSize - sizeof(Block)) / sizeof(T)), kStartBlockIndex = uint32_t(sizeof(Block)), @@ -142,7 +145,9 @@ public: kEndBlockIndex = uint32_t(kStartBlockIndex + (kNumBlockItems ) * sizeof(T)) }; - //! \name Construction / Destruction + //! \} + + //! \name Construction & Destruction //! \{ inline ZoneStack() noexcept {} @@ -155,13 +160,13 @@ public: //! \name Utilities //! \{ - ASMJIT_INLINE Error prepend(T item) noexcept { + inline Error prepend(T item) noexcept { ASMJIT_ASSERT(isInitialized()); - Block* block = _block[Globals::kLinkFirst]; + Block* block = _block[kBlockIndexFirst]; if (!block->canPrepend<T>()) { - ASMJIT_PROPAGATE(_prepareBlock(Globals::kLinkFirst, kEndBlockIndex)); - block = _block[Globals::kLinkFirst]; + ASMJIT_PROPAGATE(_prepareBlock(kBlockIndexFirst, kEndBlockIndex)); + block = _block[kBlockIndexFirst]; } T* ptr = block->start<T>() - 1; @@ -171,13 +176,13 @@ public: return kErrorOk; } - ASMJIT_INLINE Error append(T item) noexcept { + inline Error append(T item) noexcept { ASMJIT_ASSERT(isInitialized()); - Block* block = _block[Globals::kLinkLast]; + Block* block = _block[kBlockIndexLast]; if (!block->canAppend<T>()) { - ASMJIT_PROPAGATE(_prepareBlock(Globals::kLinkLast, kStartBlockIndex)); - block = _block[Globals::kLinkLast]; + ASMJIT_PROPAGATE(_prepareBlock(kBlockIndexLast, kStartBlockIndex)); + block = _block[kBlockIndexLast]; } T* ptr = block->end<T>(); @@ -188,11 +193,11 @@ public: return kErrorOk; } - ASMJIT_INLINE T popFirst() noexcept { + inline T popFirst() noexcept { ASMJIT_ASSERT(isInitialized()); ASMJIT_ASSERT(!empty()); - Block* block = _block[Globals::kLinkFirst]; + Block* block = _block[kBlockIndexFirst]; ASMJIT_ASSERT(!block->empty()); T* ptr = block->start<T>(); @@ -200,16 +205,16 @@ public: block->setStart(ptr); if (block->empty()) - _cleanupBlock(Globals::kLinkFirst, kMidBlockIndex); + _cleanupBlock(kBlockIndexFirst, kMidBlockIndex); return item; } - ASMJIT_INLINE T pop() noexcept { + inline T pop() noexcept { ASMJIT_ASSERT(isInitialized()); ASMJIT_ASSERT(!empty()); - Block* block = _block[Globals::kLinkLast]; + Block* block = _block[kBlockIndexLast]; ASMJIT_ASSERT(!block->empty()); T* ptr = block->end<T>(); @@ -219,7 +224,7 @@ public: block->setEnd(ptr); if (block->empty()) - _cleanupBlock(Globals::kLinkLast, kMidBlockIndex); + _cleanupBlock(kBlockIndexLast, kMidBlockIndex); return item; } diff --git a/src/asmjit/core/zonestring.h b/src/asmjit/core/zonestring.h index cb25b29..01f5bd8 100644 --- a/src/asmjit/core/zonestring.h +++ b/src/asmjit/core/zonestring.h @@ -1,28 +1,10 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib -#ifndef ASMJIT_CORE_SMALLSTRING_H_INCLUDED -#define ASMJIT_CORE_SMALLSTRING_H_INCLUDED +#ifndef ASMJIT_CORE_ZONESTRING_H_INCLUDED +#define ASMJIT_CORE_ZONESTRING_H_INCLUDED #include "../core/globals.h" #include "../core/zone.h" @@ -32,10 +14,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::ZoneStringBase] -// ============================================================================ - //! A helper class used by \ref ZoneString implementation. struct ZoneStringBase { union { @@ -74,28 +52,34 @@ struct ZoneStringBase { } }; -// ============================================================================ -// [asmjit::ZoneString<N>] -// ============================================================================ - //! A string template that can be zone allocated. //! -//! Helps with creating strings that can be either statically allocated if they -//! are small, or externally allocated in case their size exceeds the limit. -//! The `N` represents the size of the whole `ZoneString` structure, based on +//! Helps with creating strings that can be either statically allocated if they are small, or externally allocated +//! in case their size exceeds the limit. The `N` represents the size of the whole `ZoneString` structure, based on //! that size the maximum size of the internal buffer is determined. template<size_t N> class ZoneString { public: - static constexpr uint32_t kWholeSize = - (N > sizeof(ZoneStringBase)) ? uint32_t(N) : uint32_t(sizeof(ZoneStringBase)); - static constexpr uint32_t kMaxEmbeddedSize = kWholeSize - 5; + //! \name Constants + //! \{ + + enum : uint32_t { + kWholeSize = (N > sizeof(ZoneStringBase)) ? uint32_t(N) : uint32_t(sizeof(ZoneStringBase)), + kMaxEmbeddedSize = kWholeSize - 5 + }; + + //! \} + + //! \name Members + //! \{ union { ZoneStringBase _base; char _wholeData[kWholeSize]; }; + //! \} + //! \name Construction & Destruction //! \{ @@ -120,9 +104,8 @@ public: //! Copies a new `data` of the given `size` to the string. //! - //! If the `size` exceeds the internal buffer the given `zone` will be - //! used to duplicate the data, otherwise the internal buffer will be - //! used as a storage. + //! If the `size` exceeds the internal buffer the given `zone` will be used to duplicate the data, otherwise + //! the internal buffer will be used as a storage. inline Error setData(Zone* zone, const char* data, size_t size) noexcept { return _base.setData(zone, kMaxEmbeddedSize, data, size); } @@ -134,4 +117,4 @@ public: ASMJIT_END_NAMESPACE -#endif // ASMJIT_CORE_SMALLSTRING_H_INCLUDED +#endif // ASMJIT_CORE_ZONESTRING_H_INCLUDED diff --git a/src/asmjit/core/zonetree.cpp b/src/asmjit/core/zonetree.cpp index a16f092..8c42af8 100644 --- a/src/asmjit/core/zonetree.cpp +++ b/src/asmjit/core/zonetree.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/support.h" @@ -28,9 +10,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ZoneTree - Unit] -// ============================================================================ +// ZoneTreeBase - Tests +// ==================== #if defined(ASMJIT_TEST) template<typename NodeT> diff --git a/src/asmjit/core/zonetree.h b/src/asmjit/core/zonetree.h index 1877919..41c4e0e 100644 --- a/src/asmjit/core/zonetree.h +++ b/src/asmjit/core/zonetree.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ZONETREE_H_INCLUDED #define ASMJIT_CORE_ZONETREE_H_INCLUDED @@ -31,10 +13,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::ZoneTreeNode] -// ============================================================================ - //! RB-Tree node. //! //! The color is stored in a least significant bit of the `left` node. @@ -44,12 +22,22 @@ class ZoneTreeNode { public: ASMJIT_NONCOPYABLE(ZoneTreeNode) + //! \name Constants + //! \{ + enum : uintptr_t { kRedMask = 0x1, kPtrMask = ~kRedMask }; - uintptr_t _rbNodeData[Globals::kLinkCount]; + //! \} + + //! \name Members + //! \{ + + uintptr_t _rbNodeData[2]; + + //! \} //! \name Construction & Destruction //! \{ @@ -123,10 +111,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::ZoneTree] -// ============================================================================ - //! RB-Tree. template<typename NodeT> class ZoneTree { @@ -164,7 +148,7 @@ public: std::swap(_root, other._root); } - template<typename CompareT = Support::Compare<Support::kSortAscending>> + template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>> void insert(NodeT* node, const CompareT& cmp = CompareT()) noexcept { // Node to insert must not contain garbage. ASMJIT_ASSERT(!node->hasLeft()); @@ -176,18 +160,18 @@ public: return; } - ZoneTreeNode head; // False root node, - head._setRight(_root); // having root on the right. + ZoneTreeNode head; // False root node, + head._setRight(_root); // having root on the right. - ZoneTreeNode* g = nullptr; // Grandparent. - ZoneTreeNode* p = nullptr; // Parent. - ZoneTreeNode* t = &head; // Iterator. - ZoneTreeNode* q = _root; // Query. + ZoneTreeNode* g = nullptr; // Grandparent. + ZoneTreeNode* p = nullptr; // Parent. + ZoneTreeNode* t = &head; // Iterator. + ZoneTreeNode* q = _root; // Query. - size_t dir = 0; // Direction for accessing child nodes. - size_t last = 0; // Not needed to initialize, but makes some tools happy. + size_t dir = 0; // Direction for accessing child nodes. + size_t last = 0; // Not needed to initialize, but makes some tools happy. - node->_makeRed(); // New nodes are always red and violations fixed appropriately. + node->_makeRed(); // New nodes are always red and violations fixed appropriately. // Search down the tree. for (;;) { @@ -229,7 +213,7 @@ public: } //! Remove node from RBTree. - template<typename CompareT = Support::Compare<Support::kSortAscending>> + template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>> void remove(ZoneTreeNode* node, const CompareT& cmp = CompareT()) noexcept { ZoneTreeNode head; // False root node, head._setRight(_root); // having root on the right. @@ -304,10 +288,9 @@ public: p->_setChild(p->_getRight() == q, q->_getChild(q->_getLeft() == nullptr)); - // NOTE: The original algorithm used a trick to just copy 'key/value' to - // `f` and mark `q` for deletion. But this is unacceptable here as we - // really want to destroy the passed `node`. So, we have to make sure that - // we have really removed `f` and not `q`. + // NOTE: The original algorithm used a trick to just copy 'key/value' to `f` and mark `q` for deletion. But this + // is unacceptable here as we really want to destroy the passed `node`. So, we have to make sure that we have + // really removed `f` and not `q`. if (f != q) { ASMJIT_ASSERT(f != &head); ASMJIT_ASSERT(f != gf); @@ -337,8 +320,8 @@ public: if (_root) _root->_makeBlack(); } - template<typename KeyT, typename CompareT = Support::Compare<Support::kSortAscending>> - ASMJIT_INLINE NodeT* get(const KeyT& key, const CompareT& cmp = CompareT()) const noexcept { + template<typename KeyT, typename CompareT = Support::Compare<Support::SortOrder::kAscending>> + inline NodeT* get(const KeyT& key, const CompareT& cmp = CompareT()) const noexcept { ZoneTreeNode* node = _root; while (node) { auto result = cmp(*static_cast<const NodeT*>(node), key); @@ -359,7 +342,7 @@ public: static inline bool _isValidRed(ZoneTreeNode* node) noexcept { return ZoneTreeNode::_isValidRed(node); } //! Single rotation. - static ASMJIT_INLINE ZoneTreeNode* _singleRotate(ZoneTreeNode* root, size_t dir) noexcept { + static inline ZoneTreeNode* _singleRotate(ZoneTreeNode* root, size_t dir) noexcept { ZoneTreeNode* save = root->_getChild(!dir); root->_setChild(!dir, save->_getChild(dir)); save->_setChild( dir, root); @@ -369,7 +352,7 @@ public: } //! Double rotation. - static ASMJIT_INLINE ZoneTreeNode* _doubleRotate(ZoneTreeNode* root, size_t dir) noexcept { + static inline ZoneTreeNode* _doubleRotate(ZoneTreeNode* root, size_t dir) noexcept { root->_setChild(!dir, _singleRotate(root->_getChild(!dir), !dir)); return _singleRotate(root, dir); } diff --git a/src/asmjit/core/zonevector.cpp b/src/asmjit/core/zonevector.cpp index 160ac59..dfec5d5 100644 --- a/src/asmjit/core/zonevector.cpp +++ b/src/asmjit/core/zonevector.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #include "../core/support.h" @@ -28,9 +10,8 @@ ASMJIT_BEGIN_NAMESPACE -// ============================================================================ -// [asmjit::ZoneVectorBase - Helpers] -// ============================================================================ +// ZoneVectorBase - Helpers +// ======================== Error ZoneVectorBase::_grow(ZoneAllocator* allocator, uint32_t sizeOfT, uint32_t n) noexcept { uint32_t threshold = Globals::kGrowThreshold / sizeOfT; @@ -112,9 +93,8 @@ Error ZoneVectorBase::_resize(ZoneAllocator* allocator, uint32_t sizeOfT, uint32 return kErrorOk; } -// ============================================================================ -// [asmjit::ZoneBitVector - Ops] -// ============================================================================ +// ZoneBitVector - Operations +// ========================== Error ZoneBitVector::copyFrom(ZoneAllocator* allocator, const ZoneBitVector& other) noexcept { BitWord* data = _data; @@ -280,9 +260,8 @@ Error ZoneBitVector::_append(ZoneAllocator* allocator, bool value) noexcept { return _resize(allocator, newSize, idealCapacity, value); } -// ============================================================================ -// [asmjit::ZoneVector / ZoneBitVector - Unit] -// ============================================================================ +// ZoneVector / ZoneBitVector - Tests +// ================================== #if defined(ASMJIT_TEST) template<typename T> diff --git a/src/asmjit/core/zonevector.h b/src/asmjit/core/zonevector.h index 1340bf8..447c08c 100644 --- a/src/asmjit/core/zonevector.h +++ b/src/asmjit/core/zonevector.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_ZONEVECTOR_H_INCLUDED #define ASMJIT_CORE_ZONEVECTOR_H_INCLUDED @@ -32,10 +14,6 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_zone //! \{ -// ============================================================================ -// [asmjit::ZoneVectorBase] -// ============================================================================ - //! Base class used by \ref ZoneVector template. class ZoneVectorBase { public: @@ -129,10 +107,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::ZoneVector<T>] -// ============================================================================ - //! Template used to store and manage array of Zone allocated data. //! //! This template has these advantages over other std::vector<>: @@ -213,10 +187,10 @@ public: //! \{ //! Swaps this vector with `other`. - inline void swap(ZoneVector<T>& other) noexcept { _swap(other); } + ASMJIT_FORCE_INLINE void swap(ZoneVector<T>& other) noexcept { _swap(other); } //! Prepends `item` to the vector. - inline Error prepend(ZoneAllocator* allocator, const T& item) noexcept { + ASMJIT_FORCE_INLINE Error prepend(ZoneAllocator* allocator, const T& item) noexcept { if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); @@ -228,7 +202,7 @@ public: } //! Inserts an `item` at the specified `index`. - inline Error insert(ZoneAllocator* allocator, size_t index, const T& item) noexcept { + ASMJIT_FORCE_INLINE Error insert(ZoneAllocator* allocator, size_t index, const T& item) noexcept { ASMJIT_ASSERT(index <= _size); if (ASMJIT_UNLIKELY(_size == _capacity)) @@ -243,7 +217,7 @@ public: } //! Appends `item` to the vector. - inline Error append(ZoneAllocator* allocator, const T& item) noexcept { + ASMJIT_FORCE_INLINE Error append(ZoneAllocator* allocator, const T& item) noexcept { if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); @@ -254,7 +228,7 @@ public: } //! Appends `other` vector at the end of this vector. - inline Error concat(ZoneAllocator* allocator, const ZoneVector<T>& other) noexcept { + ASMJIT_FORCE_INLINE Error concat(ZoneAllocator* allocator, const ZoneVector<T>& other) noexcept { uint32_t size = other._size; if (_capacity - _size < size) ASMJIT_PROPAGATE(grow(allocator, size)); @@ -269,10 +243,9 @@ public: //! Prepends `item` to the vector (unsafe case). //! - //! Can only be used together with `willGrow()`. If `willGrow(N)` returns - //! `kErrorOk` then N elements can be added to the vector without checking - //! if there is a place for them. Used mostly internally. - inline void prependUnsafe(const T& item) noexcept { + //! Can only be used together with `willGrow()`. If `willGrow(N)` returns `kErrorOk` then N elements + //! can be added to the vector without checking if there is a place for them. Used mostly internally. + ASMJIT_FORCE_INLINE void prependUnsafe(const T& item) noexcept { ASMJIT_ASSERT(_size < _capacity); T* data = static_cast<T*>(_data); @@ -285,10 +258,9 @@ public: //! Append s`item` to the vector (unsafe case). //! - //! Can only be used together with `willGrow()`. If `willGrow(N)` returns - //! `kErrorOk` then N elements can be added to the vector without checking - //! if there is a place for them. Used mostly internally. - inline void appendUnsafe(const T& item) noexcept { + //! Can only be used together with `willGrow()`. If `willGrow(N)` returns `kErrorOk` then N elements + //! can be added to the vector without checking if there is a place for them. Used mostly internally. + ASMJIT_FORCE_INLINE void appendUnsafe(const T& item) noexcept { ASMJIT_ASSERT(_size < _capacity); memcpy(static_cast<T*>(_data) + _size, &item, sizeof(T)); @@ -296,7 +268,7 @@ public: } //! Inserts an `item` at the specified `index` (unsafe case). - inline void insertUnsafe(size_t index, const T& item) noexcept { + ASMJIT_FORCE_INLINE void insertUnsafe(size_t index, const T& item) noexcept { ASMJIT_ASSERT(_size < _capacity); ASMJIT_ASSERT(index <= _size); @@ -306,7 +278,7 @@ public: _size++; } //! Concatenates all items of `other` at the end of the vector. - inline void concatUnsafe(const ZoneVector<T>& other) noexcept { + ASMJIT_FORCE_INLINE void concatUnsafe(const ZoneVector<T>& other) noexcept { uint32_t size = other._size; ASMJIT_ASSERT(_capacity - _size >= size); @@ -317,7 +289,7 @@ public: } //! Returns index of the given `val` or `Globals::kNotFound` if it doesn't exist. - inline uint32_t indexOf(const T& val) const noexcept { + ASMJIT_FORCE_INLINE uint32_t indexOf(const T& val) const noexcept { const T* data = static_cast<const T*>(_data); uint32_t size = _size; @@ -351,7 +323,7 @@ public: return data()[index]; } - template<typename CompareT = Support::Compare<Support::kSortAscending>> + template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>> inline void sort(const CompareT& cmp = CompareT()) noexcept { Support::qSort<T, CompareT>(data(), size(), cmp); } @@ -370,18 +342,16 @@ public: //! Returns a reference to the first element of the vector. //! - //! \note The vector must have at least one element. Attempting to use - //! `first()` on empty vector will trigger an assertion failure in debug - //! builds. + //! \note The vector must have at least one element. Attempting to use `first()` on empty vector will trigger + //! an assertion failure in debug builds. inline T& first() noexcept { return operator[](0); } //! \overload inline const T& first() const noexcept { return operator[](0); } //! Returns a reference to the last element of the vector. //! - //! \note The vector must have at least one element. Attempting to use - //! `last()` on empty vector will trigger an assertion failure in debug - //! builds. + //! \note The vector must have at least one element. Attempting to use `last()` on empty vector will trigger + //! an assertion failure in debug builds. inline T& last() noexcept { return operator[](_size - 1); } //! \overload inline const T& last() const noexcept { return operator[](_size - 1); } @@ -403,9 +373,8 @@ public: //! Resizes the vector to hold `n` elements. //! - //! If `n` is greater than the current size then the additional elements' - //! content will be initialized to zero. If `n` is less than the current - //! size then the vector will be truncated to exactly `n` elements. + //! If `n` is greater than the current size then the additional elements' content will be initialized to zero. + //! If `n` is less than the current size then the vector will be truncated to exactly `n` elements. inline Error resize(ZoneAllocator* allocator, uint32_t n) noexcept { return ZoneVectorBase::_resize(allocator, sizeof(T), n); } @@ -422,15 +391,24 @@ public: //! \} }; -// ============================================================================ -// [asmjit::ZoneBitVector] -// ============================================================================ - //! Zone-allocated bit vector. class ZoneBitVector { public: typedef Support::BitWord BitWord; - static constexpr uint32_t kBitWordSizeInBits = Support::kBitWordSizeInBits; + + ASMJIT_NONCOPYABLE(ZoneBitVector) + + //! \name Constants + //! \{ + + enum : uint32_t { + kBitWordSizeInBits = Support::kBitWordSizeInBits + }; + + //! \} + + //! \name Members + //! \{ //! Bits. BitWord* _data = nullptr; @@ -439,7 +417,7 @@ public: //! Capacity of the bit-vector (in bits). uint32_t _capacity = 0; - ASMJIT_NONCOPYABLE(ZoneBitVector) + //! \} //! \cond INTERNAL //! \name Internal @@ -548,7 +526,7 @@ public: Support::bitVectorFlipBit(_data, index); } - ASMJIT_INLINE Error append(ZoneAllocator* allocator, bool value) noexcept { + ASMJIT_FORCE_INLINE Error append(ZoneAllocator* allocator, bool value) noexcept { uint32_t index = _size; if (ASMJIT_UNLIKELY(index >= _capacity)) return _append(allocator, value); @@ -567,35 +545,34 @@ public: ASMJIT_API Error copyFrom(ZoneAllocator* allocator, const ZoneBitVector& other) noexcept; - inline void clearAll() noexcept { + ASMJIT_FORCE_INLINE void clearAll() noexcept { _zeroBits(_data, _wordsPerBits(_size)); } - inline void fillAll() noexcept { + ASMJIT_FORCE_INLINE void fillAll() noexcept { _fillBits(_data, _wordsPerBits(_size)); _clearUnusedBits(); } - inline void clearBits(uint32_t start, uint32_t count) noexcept { + ASMJIT_FORCE_INLINE void clearBits(uint32_t start, uint32_t count) noexcept { ASMJIT_ASSERT(start <= _size); ASMJIT_ASSERT(_size - start >= count); Support::bitVectorClear(_data, start, count); } - inline void fillBits(uint32_t start, uint32_t count) noexcept { + ASMJIT_FORCE_INLINE void fillBits(uint32_t start, uint32_t count) noexcept { ASMJIT_ASSERT(start <= _size); ASMJIT_ASSERT(_size - start >= count); Support::bitVectorFill(_data, start, count); } - //! Performs a logical bitwise AND between bits specified in this array and bits - //! in `other`. If `other` has less bits than `this` then all remaining bits are - //! set to zero. + //! Performs a logical bitwise AND between bits specified in this array and bits in `other`. If `other` has less + //! bits than `this` then all remaining bits are set to zero. //! //! \note The size of the BitVector is unaffected by this operation. - inline void and_(const ZoneBitVector& other) noexcept { + ASMJIT_FORCE_INLINE void and_(const ZoneBitVector& other) noexcept { BitWord* dst = _data; const BitWord* src = other._data; @@ -615,12 +592,11 @@ public: } } - //! Performs a logical bitwise AND between bits specified in this array and - //! negated bits in `other`. If `other` has less bits than `this` then all - //! remaining bits are kept intact. + //! Performs a logical bitwise AND between bits specified in this array and negated bits in `other`. If `other` + //! has less bits than `this` then all remaining bits are kept intact. //! //! \note The size of the BitVector is unaffected by this operation. - inline void andNot(const ZoneBitVector& other) noexcept { + ASMJIT_FORCE_INLINE void andNot(const ZoneBitVector& other) noexcept { BitWord* dst = _data; const BitWord* src = other._data; @@ -629,12 +605,11 @@ public: dst[i] = dst[i] & ~src[i]; } - //! Performs a logical bitwise OP between bits specified in this array and bits - //! in `other`. If `other` has less bits than `this` then all remaining bits - //! are kept intact. + //! Performs a logical bitwise OP between bits specified in this array and bits in `other`. If `other` has less + //! bits than `this` then all remaining bits are kept intact. //! //! \note The size of the BitVector is unaffected by this operation. - inline void or_(const ZoneBitVector& other) noexcept { + ASMJIT_FORCE_INLINE void or_(const ZoneBitVector& other) noexcept { BitWord* dst = _data; const BitWord* src = other._data; @@ -644,15 +619,16 @@ public: _clearUnusedBits(); } - inline void _clearUnusedBits() noexcept { + ASMJIT_FORCE_INLINE void _clearUnusedBits() noexcept { uint32_t idx = _size / kBitWordSizeInBits; uint32_t bit = _size % kBitWordSizeInBits; - if (!bit) return; + if (!bit) + return; _data[idx] &= (BitWord(1) << bit) - 1u; } - inline bool eq(const ZoneBitVector& other) const noexcept { + ASMJIT_FORCE_INLINE bool eq(const ZoneBitVector& other) const noexcept { if (_size != other._size) return false; @@ -691,14 +667,14 @@ public: class ForEachBitSet : public Support::BitVectorIterator<BitWord> { public: - ASMJIT_INLINE explicit ForEachBitSet(const ZoneBitVector& bitVector) noexcept + inline explicit ForEachBitSet(const ZoneBitVector& bitVector) noexcept : Support::BitVectorIterator<BitWord>(bitVector.data(), bitVector.sizeInBitWords()) {} }; template<class Operator> class ForEachBitOp : public Support::BitVectorOpIterator<BitWord, Operator> { public: - ASMJIT_INLINE ForEachBitOp(const ZoneBitVector& a, const ZoneBitVector& b) noexcept + inline ForEachBitOp(const ZoneBitVector& a, const ZoneBitVector& b) noexcept : Support::BitVectorOpIterator<BitWord, Operator>(a.data(), b.data(), a.sizeInBitWords()) { ASMJIT_ASSERT(a.size() == b.size()); } diff --git a/src/asmjit/x86.h b/src/asmjit/x86.h index 2c49518..84bc84b 100644 --- a/src/asmjit/x86.h +++ b/src/asmjit/x86.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_H_INCLUDED #define ASMJIT_X86_H_INCLUDED @@ -40,15 +22,14 @@ //! ### Supported Instructions //! //! - Emitters: -//! - \ref x86::EmitterExplicitT - Provides all instructions that use -//! explicit operands, provides also utility functions. The member -//! functions provided are part of all X86 emitters. -//! - \ref x86::EmitterImplicitT - Provides all instructions that use -//! implicit operands, these cannot be used with \ref x86::Compiler. +//! - \ref x86::EmitterExplicitT - Provides all instructions that use explicit operands, provides also utility +//! functions. The member functions provided are part of all X86 emitters. +//! - \ref x86::EmitterImplicitT - Provides all instructions that use implicit operands, these cannot be used +//! with \ref x86::Compiler. //! //! - Instruction representation: -//! - \ref x86::Inst::Id - instruction identifiers. -//! - \ref x86::Inst::Options - instruction options. +//! - \ref x86::Inst::Id - Provides instruction identifiers for both X86/X86_64 architectures. +//! - \ref InstOptions - Provides generic and X86/X86_64 specific options. //! //! ### Register Operands //! @@ -74,34 +55,28 @@ //! //! ### Memory Operands //! -//! - \ref x86::Mem - X86/X64 memory operand that provides support for all -//! X86 and X64 addressing features including absolute addresses, index -//! scales, and segment override prefixes. -//! -//! ### Other -//! -//! - \ref x86::Features - X86/X64 CPU features on top of \ref BaseFeatures. +//! - \ref x86::Mem - X86/X64 memory operand that provides support for all X86 and X64 addressing features +//! including absolute addresses, index scales, and segment override prefixes. //! //! ### Status and Control Words //! -//! - \ref asmjit::x86::FpuWord::Status - FPU status word. -//! - \ref asmjit::x86::FpuWord::Control - FPU control word. -//! -//! ### Predicates -//! -//! - \ref x86::Predicate - namespace that provides X86/X64 predicates. -//! - \ref x86::Predicate::Cmp - `CMP[PD|PS|SD|SS]` predicate (SSE+). -//! - \ref x86::Predicate::PCmpStr - `[V]PCMP[I|E]STR[I|M]` predicate (SSE4.1+). -//! - \ref x86::Predicate::Round - `ROUND[PD|PS|SD|SS]` predicate (SSE+). -//! - \ref x86::Predicate::VCmp - `VCMP[PD|PS|SD|SS]` predicate (AVX+). -//! - \ref x86::Predicate::VFixupImm - `VFIXUPIMM[PD|PS|SD|SS]` predicate (AVX512+). -//! - \ref x86::Predicate::VFPClass - `VFPCLASS[PD|PS|SD|SS]` predicate (AVX512+). -//! - \ref x86::Predicate::VGetMant - `VGETMANT[PD|PS|SD|SS]` predicate (AVX512+). -//! - \ref x86::Predicate::VPCmp - `VPCMP[U][B|W|D|Q]` predicate (AVX512+). -//! - \ref x86::Predicate::VPCom - `VPCOM[U][B|W|D|Q]` predicate (XOP). -//! - \ref x86::Predicate::VRange - `VRANGE[PD|PS|SD|SS]` predicate (AVX512+). -//! - \ref x86::Predicate::VReduce - `REDUCE[PD|PS|SD|SS]` predicate (AVX512+). -//! - \ref x86::TLog - namespace that provides `VPTERNLOG[D|Q]` predicate / operations. +//! - \ref x86::FpuStatusWord - FPU status word bits / decomposition. +//! - \ref x86::FpuControlWord - FPU control word bits / decomposition. +//! +//! ### Predicates (immediate values) +//! +//! - \ref x86::CmpImm - `CMP[PD|PS|SD|SS]` predicate (SSE+). +//! - \ref x86::PCmpStrImm - `[V]PCMP[I|E]STR[I|M]` predicate (SSE4.1+, AVX+). +//! - \ref x86::RoundImm - `[V]ROUND[PD|PS|SD|SS]` predicate (SSE+, AVX+). +//! - \ref x86::VCmpImm - `VCMP[PD|PS|SD|SS]` predicate (AVX+). +//! - \ref x86::VFixupImm - `VFIXUPIMM[PD|PS|SD|SS]` predicate (AVX512+). +//! - \ref x86::VFPClassImm - `VFPCLASS[PD|PS|SD|SS]` predicate (AVX512+). +//! - \ref x86::VGetMantImm - `VGETMANT[PD|PS|SD|SS]` predicate (AVX512+). +//! - \ref x86::VPCmpImm - `VPCMP[U][B|W|D|Q]` predicate (AVX512+). +//! - \ref x86::VPComImm - `VPCOM[U][B|W|D|Q]` predicate (XOP). +//! - \ref x86::VRangeImm - `VRANGE[PD|PS|SD|SS]` predicate (AVX512+). +//! - \ref x86::VReduceImm - `REDUCE[PD|PS|SD|SS]` predicate (AVX512+). +//! - \ref x86::TLogImm - `VPTERNLOG[D|Q]` predicate and operations (AVX512+). #include "core.h" @@ -110,7 +85,6 @@ #include "x86/x86builder.h" #include "x86/x86compiler.h" #include "x86/x86emitter.h" -#include "x86/x86features.h" #include "x86/x86globals.h" #include "x86/x86instdb.h" #include "x86/x86operand.h" diff --git a/src/asmjit/x86/x86archtraits_p.h b/src/asmjit/x86/x86archtraits_p.h index 66a6f50..7c43651 100644 --- a/src/asmjit/x86/x86archtraits_p.h +++ b/src/asmjit/x86/x86archtraits_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86ARCHTRAITS_P_H_INCLUDED #define ASMJIT_X86_X86ARCHTRAITS_P_H_INCLUDED @@ -34,10 +16,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::x86ArchTraits -// ============================================================================ - +//! X86 architecture traits (internal). static const constexpr ArchTraits x86ArchTraits = { // SP/FP/LR/PC. Gp::kIdSp, Gp::kIdBp, 0xFF, 0xFF, @@ -52,51 +31,53 @@ static const constexpr ArchTraits x86ArchTraits = { 0x7FFFFFFFu, 0x7FFFFFFFu, // ISA features [Gp, Vec, Other0, Other1]. - { ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop, 0, 0, 0 }, - - // RegInfo. - #define V(index) { x86::RegTraits<index>::kSignature } - { ASMJIT_LOOKUP_TABLE_32(V, 0) }, + {{ + InstHints::kRegSwap | InstHints::kPushPop, + InstHints::kNoHints, + InstHints::kNoHints, + InstHints::kNoHints + }}, + + // Register signatures. + #define V(index) OperandSignature(x86::RegTraits<RegType(index)>::kSignature) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // RegTypeToTypeId. - #define V(index) x86::RegTraits<index>::kTypeId - { ASMJIT_LOOKUP_TABLE_32(V, 0) }, + #define V(index) TypeId(x86::RegTraits<RegType(index)>::kTypeId) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // TypeIdToRegType. - #define V(index) (index + Type::_kIdBaseStart == Type::kIdI8 ? Reg::kTypeGpbLo : \ - index + Type::_kIdBaseStart == Type::kIdU8 ? Reg::kTypeGpbLo : \ - index + Type::_kIdBaseStart == Type::kIdI16 ? Reg::kTypeGpw : \ - index + Type::_kIdBaseStart == Type::kIdU16 ? Reg::kTypeGpw : \ - index + Type::_kIdBaseStart == Type::kIdI32 ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdU32 ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdIntPtr ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdUIntPtr ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdF32 ? Reg::kTypeXmm : \ - index + Type::_kIdBaseStart == Type::kIdF64 ? Reg::kTypeXmm : \ - index + Type::_kIdBaseStart == Type::kIdMask8 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMask16 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMask32 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMask64 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMmx32 ? Reg::kTypeMm : \ - index + Type::_kIdBaseStart == Type::kIdMmx64 ? Reg::kTypeMm : Reg::kTypeNone) - { ASMJIT_LOOKUP_TABLE_32(V, 0) }, + #define V(index) (index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt8) ? RegType::kX86_GpbLo : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt8) ? RegType::kX86_GpbLo : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt16) ? RegType::kX86_Gpw : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt16) ? RegType::kX86_Gpw : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt32) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt32) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kIntPtr) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUIntPtr) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat32) ? RegType::kX86_Xmm : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat64) ? RegType::kX86_Xmm : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask8) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask16) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask32) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask64) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMmx32) ? RegType::kX86_Mm : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMmx64) ? RegType::kX86_Mm : RegType::kNone) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities. { - ISAWordNameId::kDB, - ISAWordNameId::kDW, - ISAWordNameId::kDD, - ISAWordNameId::kDQ + ArchTypeNameId::kDB, + ArchTypeNameId::kDW, + ArchTypeNameId::kDD, + ArchTypeNameId::kDQ } }; -// ============================================================================ -// [asmjit::x86::x64ArchTraits -// ============================================================================ - +//! X64 architecture traits (internal). static const constexpr ArchTraits x64ArchTraits = { // SP/FP/LR/PC. Gp::kIdSp, Gp::kIdBp, 0xFF, 0xFF, @@ -111,46 +92,51 @@ static const constexpr ArchTraits x64ArchTraits = { 0x7FFFFFFFu, 0x7FFFFFFFu, // ISA features [Gp, Vec, Other0, Other1]. - { ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop, 0, 0, 0 }, - - // RegInfo. - #define V(index) { x86::RegTraits<index>::kSignature } - { ASMJIT_LOOKUP_TABLE_32(V, 0) }, + {{ + InstHints::kRegSwap | InstHints::kPushPop, + InstHints::kNoHints, + InstHints::kNoHints, + InstHints::kNoHints + }}, + + // Register signatures. + #define V(index) OperandSignature(x86::RegTraits<RegType(index)>::kSignature) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // RegTypeToTypeId. - #define V(index) x86::RegTraits<index>::kTypeId - { ASMJIT_LOOKUP_TABLE_32(V, 0) }, + #define V(index) TypeId(x86::RegTraits<RegType(index)>::kTypeId) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // TypeIdToRegType. - #define V(index) (index + Type::_kIdBaseStart == Type::kIdI8 ? Reg::kTypeGpbLo : \ - index + Type::_kIdBaseStart == Type::kIdU8 ? Reg::kTypeGpbLo : \ - index + Type::_kIdBaseStart == Type::kIdI16 ? Reg::kTypeGpw : \ - index + Type::_kIdBaseStart == Type::kIdU16 ? Reg::kTypeGpw : \ - index + Type::_kIdBaseStart == Type::kIdI32 ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdU32 ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdI64 ? Reg::kTypeGpq : \ - index + Type::_kIdBaseStart == Type::kIdU64 ? Reg::kTypeGpq : \ - index + Type::_kIdBaseStart == Type::kIdIntPtr ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdUIntPtr ? Reg::kTypeGpd : \ - index + Type::_kIdBaseStart == Type::kIdF32 ? Reg::kTypeXmm : \ - index + Type::_kIdBaseStart == Type::kIdF64 ? Reg::kTypeXmm : \ - index + Type::_kIdBaseStart == Type::kIdMask8 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMask16 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMask32 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMask64 ? Reg::kTypeKReg : \ - index + Type::_kIdBaseStart == Type::kIdMmx32 ? Reg::kTypeMm : \ - index + Type::_kIdBaseStart == Type::kIdMmx64 ? Reg::kTypeMm : Reg::kTypeNone) - { ASMJIT_LOOKUP_TABLE_32(V, 0) }, + #define V(index) (index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt8) ? RegType::kX86_GpbLo : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt8) ? RegType::kX86_GpbLo : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt16) ? RegType::kX86_Gpw : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt16) ? RegType::kX86_Gpw : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt32) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt32) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt64) ? RegType::kX86_Gpq : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt64) ? RegType::kX86_Gpq : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kIntPtr) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUIntPtr) ? RegType::kX86_Gpd : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat32) ? RegType::kX86_Xmm : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat64) ? RegType::kX86_Xmm : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask8) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask16) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask32) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMask64) ? RegType::kX86_KReg : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMmx32) ? RegType::kX86_Mm : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kMmx64) ? RegType::kX86_Mm : RegType::kNone) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, #undef V // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities. { - ISAWordNameId::kDB, - ISAWordNameId::kDW, - ISAWordNameId::kDD, - ISAWordNameId::kDQ + ArchTypeNameId::kDB, + ArchTypeNameId::kDW, + ArchTypeNameId::kDD, + ArchTypeNameId::kDQ } }; diff --git a/src/asmjit/x86/x86assembler.cpp b/src/asmjit/x86/x86assembler.cpp index a568dab..4da28f1 100644 --- a/src/asmjit/x86/x86assembler.cpp +++ b/src/asmjit/x86/x86assembler.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) @@ -39,15 +21,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [TypeDefs] -// ============================================================================ - typedef Support::FastUInt8 FastUInt8; -// ============================================================================ -// [Constants] -// ============================================================================ +// x86::Assembler - Constants +// ========================== //! X86 bytes used to encode important prefixes. enum X86Byte : uint32_t { @@ -78,13 +55,13 @@ enum X86Byte : uint32_t { //! 4-byte EVEX prefix: //! - `[0]` - `0x62`. - //! - `[1]` - Payload0 or `P[ 7: 0]` - `[R X B R' 0 0 m m]`. + //! - `[1]` - Payload0 or `P[ 7: 0]` - `[R X B R' 0 m m m]`. //! - `[2]` - Payload1 or `P[15: 8]` - `[W v v v v 1 p p]`. //! - `[3]` - Payload2 or `P[23:16]` - `[z L' L b V' a a a]`. //! //! Payload: - //! - `P[ 1: 0]` - OPCODE: EVEX.mmmmm, only lowest 2 bits [1:0] used. - //! - `P[ 3: 2]` - ______: Must be 0. + //! - `P[ 2: 0]` - OPCODE: EVEX.mmmmm, only lowest 3 bits [2:0] used. + //! - `P[ 3]` - ______: Must be 0. //! - `P[ 4]` - REG-ID: EVEX.R' - 5th bit of 'RRRRR'. //! - `P[ 5]` - REG-ID: EVEX.B - 4th bit of 'BBBBB'. //! - `P[ 6]` - REG-ID: EVEX.X - 5th bit of 'BBBBB' or 4th bit of 'XXXX' (with SIB). @@ -166,15 +143,13 @@ static const uint32_t x86OpcodePopSReg[8] = { Opcode::k000F00 | 0xA9 // Pop GS. }; -// ============================================================================ -// [asmjit::X86MemInfo | X86VEXPrefix | X86LLByRegType | X86CDisp8Table] +// x86::Assembler - X86MemInfo | X86VEXPrefix | X86LLByRegType | X86CDisp8Table // ============================================================================ //! Memory operand's info bits. //! -//! A lookup table that contains various information based on the BASE and INDEX -//! information of a memory operand. This is much better and safer than playing -//! with IFs in the code and can check for errors must faster and better. +//! A lookup table that contains various information based on the BASE and INDEX information of a memory operand. This +//! is much better and safer than playing with IFs in the code and can check for errors must faster and better. enum X86MemInfo_Enum { kX86MemInfo_0 = 0x00, @@ -191,52 +166,48 @@ enum X86MemInfo_Enum { template<uint32_t X> struct X86MemInfo_T { - enum { + enum : uint32_t { B = (X ) & 0x1F, I = (X >> 5) & 0x1F, - kBase = (B >= Reg::kTypeGpw && B <= Reg::kTypeGpq ) ? kX86MemInfo_BaseGp : - (B == Reg::kTypeRip ) ? kX86MemInfo_BaseRip : - (B == Label::kLabelTag ) ? kX86MemInfo_BaseLabel : 0, - - kIndex = (I >= Reg::kTypeGpw && I <= Reg::kTypeGpq ) ? kX86MemInfo_Index : - (I >= Reg::kTypeXmm && I <= Reg::kTypeZmm ) ? kX86MemInfo_Index : 0, - - k67H = (B == Reg::kTypeGpw && I == Reg::kTypeNone) ? kX86MemInfo_67H_X86 : - (B == Reg::kTypeGpd && I == Reg::kTypeNone) ? kX86MemInfo_67H_X64 : - (B == Reg::kTypeNone && I == Reg::kTypeGpw ) ? kX86MemInfo_67H_X86 : - (B == Reg::kTypeNone && I == Reg::kTypeGpd ) ? kX86MemInfo_67H_X64 : - (B == Reg::kTypeGpw && I == Reg::kTypeGpw ) ? kX86MemInfo_67H_X86 : - (B == Reg::kTypeGpd && I == Reg::kTypeGpd ) ? kX86MemInfo_67H_X64 : - (B == Reg::kTypeGpw && I == Reg::kTypeXmm ) ? kX86MemInfo_67H_X86 : - (B == Reg::kTypeGpd && I == Reg::kTypeXmm ) ? kX86MemInfo_67H_X64 : - (B == Reg::kTypeGpw && I == Reg::kTypeYmm ) ? kX86MemInfo_67H_X86 : - (B == Reg::kTypeGpd && I == Reg::kTypeYmm ) ? kX86MemInfo_67H_X64 : - (B == Reg::kTypeGpw && I == Reg::kTypeZmm ) ? kX86MemInfo_67H_X86 : - (B == Reg::kTypeGpd && I == Reg::kTypeZmm ) ? kX86MemInfo_67H_X64 : - (B == Label::kLabelTag && I == Reg::kTypeGpw ) ? kX86MemInfo_67H_X86 : - (B == Label::kLabelTag && I == Reg::kTypeGpd ) ? kX86MemInfo_67H_X64 : 0, + kBase = (B >= uint32_t(RegType::kX86_Gpw) && B <= uint32_t(RegType::kX86_Gpq)) ? kX86MemInfo_BaseGp : + (B == uint32_t(RegType::kX86_Rip) ) ? kX86MemInfo_BaseRip : + (B == uint32_t(RegType::kLabelTag) ) ? kX86MemInfo_BaseLabel : 0, + + kIndex = (I >= uint32_t(RegType::kX86_Gpw) && I <= uint32_t(RegType::kX86_Gpq)) ? kX86MemInfo_Index : + (I >= uint32_t(RegType::kX86_Xmm) && I <= uint32_t(RegType::kX86_Zmm)) ? kX86MemInfo_Index : 0, + + k67H = (B == uint32_t(RegType::kX86_Gpw) && I == uint32_t(RegType::kNone) ) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kX86_Gpd) && I == uint32_t(RegType::kNone) ) ? kX86MemInfo_67H_X64 : + (B == uint32_t(RegType::kNone) && I == uint32_t(RegType::kX86_Gpw)) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kNone) && I == uint32_t(RegType::kX86_Gpd)) ? kX86MemInfo_67H_X64 : + (B == uint32_t(RegType::kX86_Gpw) && I == uint32_t(RegType::kX86_Gpw)) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kX86_Gpd) && I == uint32_t(RegType::kX86_Gpd)) ? kX86MemInfo_67H_X64 : + (B == uint32_t(RegType::kX86_Gpw) && I == uint32_t(RegType::kX86_Xmm)) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kX86_Gpd) && I == uint32_t(RegType::kX86_Xmm)) ? kX86MemInfo_67H_X64 : + (B == uint32_t(RegType::kX86_Gpw) && I == uint32_t(RegType::kX86_Ymm)) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kX86_Gpd) && I == uint32_t(RegType::kX86_Ymm)) ? kX86MemInfo_67H_X64 : + (B == uint32_t(RegType::kX86_Gpw) && I == uint32_t(RegType::kX86_Zmm)) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kX86_Gpd) && I == uint32_t(RegType::kX86_Zmm)) ? kX86MemInfo_67H_X64 : + (B == uint32_t(RegType::kLabelTag) && I == uint32_t(RegType::kX86_Gpw)) ? kX86MemInfo_67H_X86 : + (B == uint32_t(RegType::kLabelTag) && I == uint32_t(RegType::kX86_Gpd)) ? kX86MemInfo_67H_X64 : 0, kValue = kBase | kIndex | k67H | 0x04 | 0x08 }; }; // The result stored in the LUT is a combination of -// - 67H - Address override prefix - depends on BASE+INDEX register types and -// the target architecture. -// - REX - A possible combination of REX.[B|X|R|W] bits in REX prefix where -// REX.B and REX.X are possibly masked out, but REX.R and REX.W are -// kept as is. +// - 67H - Address override prefix - depends on BASE+INDEX register types and the target architecture. +// - REX - A possible combination of REX.[B|X|R|W] bits in REX prefix where REX.B and REX.X are possibly +// masked out, but REX.R and REX.W are kept as is. #define VALUE(x) X86MemInfo_T<x>::kValue static const uint8_t x86MemInfo[] = { ASMJIT_LOOKUP_TABLE_1024(VALUE, 0) }; #undef VALUE -// VEX3 or XOP xor bits applied to the opcode before emitted. The index to this -// table is 'mmmmm' value, which contains all we need. This is only used by a -// 3 BYTE VEX and XOP prefixes, 2 BYTE VEX prefix is handled differently. The -// idea is to minimize the difference between VEX3 vs XOP when encoding VEX -// or XOP instruction. This should minimize the code required to emit such -// instructions and should also make it faster as we don't need any branch to +// VEX3 or XOP xor bits applied to the opcode before emitted. The index to this table is 'mmmmm' value, which +// contains all we need. This is only used by a 3 BYTE VEX and XOP prefixes, 2 BYTE VEX prefix is handled differently. +// The idea is to minimize the difference between VEX3 vs XOP when encoding VEX or XOP instruction. This should +// minimize the code required to emit such instructions and should also make it faster as we don't need any branch to // decide between VEX3 vs XOP. // ____ ___ // [_OPCODE_|WvvvvLpp|RXBmmmmm|VEX3_XOP] @@ -244,26 +215,23 @@ static const uint8_t x86MemInfo[] = { ASMJIT_LOOKUP_TABLE_1024(VALUE, 0) }; static const uint32_t x86VEXPrefix[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; #undef VALUE -// Table that contains LL opcode field addressed by a register size / 16. It's -// used to propagate L.256 or L.512 when YMM or ZMM registers are used, -// respectively. +// Table that contains LL opcode field addressed by a register size / 16. It's used to propagate L.256 or L.512 when +// YMM or ZMM registers are used, respectively. #define VALUE(x) (x & (64 >> 4)) ? Opcode::kLL_2 : \ (x & (32 >> 4)) ? Opcode::kLL_1 : Opcode::kLL_0 static const uint32_t x86LLBySizeDiv16[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; #undef VALUE -// Table that contains LL opcode field addressed by a register size / 16. It's -// used to propagate L.256 or L.512 when YMM or ZMM registers are used, -// respectively. -#define VALUE(x) x == Reg::kTypeZmm ? Opcode::kLL_2 : \ - x == Reg::kTypeYmm ? Opcode::kLL_1 : Opcode::kLL_0 +// Table that contains LL opcode field addressed by a register size / 16. It's used to propagate L.256 or L.512 when +// YMM or ZMM registers are used, respectively. +#define VALUE(x) x == uint32_t(RegType::kX86_Zmm) ? Opcode::kLL_2 : \ + x == uint32_t(RegType::kX86_Ymm) ? Opcode::kLL_1 : Opcode::kLL_0 static const uint32_t x86LLByRegType[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; #undef VALUE -// Table that contains a scale (shift left) based on 'TTWLL' field and -// the instruction's tuple-type (TT) field. The scale is then applied to -// the BASE-N stored in each opcode to calculate the final compressed -// displacement used by all EVEX encoded instructions. +// Table that contains a scale (shift left) based on 'TTWLL' field and the instruction's tuple-type (TT) field. The +// scale is then applied to the BASE-N stored in each opcode to calculate the final compressed displacement used by +// all EVEX encoded instructions. template<uint32_t X> struct X86CDisp8SHL_T { enum { @@ -314,33 +282,32 @@ struct X86Mod16BaseIndexTable_T { static const uint8_t x86Mod16BaseIndexTable[] = { ASMJIT_LOOKUP_TABLE_64(VALUE, 0) }; #undef VALUE -// ============================================================================ -// [asmjit::x86::Assembler - Helpers] -// ============================================================================ +// x86::Assembler - Helpers +// ======================== -static ASMJIT_INLINE bool x86IsJmpOrCall(uint32_t instId) noexcept { +static ASMJIT_FORCE_INLINE bool x86IsJmpOrCall(InstId instId) noexcept { return instId == Inst::kIdJmp || instId == Inst::kIdCall; } -static ASMJIT_INLINE bool x86IsImplicitMem(const Operand_& op, uint32_t base) noexcept { +static ASMJIT_FORCE_INLINE bool x86IsImplicitMem(const Operand_& op, uint32_t base) noexcept { return op.isMem() && op.as<Mem>().baseId() == base && !op.as<Mem>().hasOffset(); } //! Combine `regId` and `vvvvvId` into a single value (used by AVX and AVX-512). -static ASMJIT_INLINE uint32_t x86PackRegAndVvvvv(uint32_t regId, uint32_t vvvvvId) noexcept { +static ASMJIT_FORCE_INLINE uint32_t x86PackRegAndVvvvv(uint32_t regId, uint32_t vvvvvId) noexcept { return regId + (vvvvvId << kVexVVVVVShift); } -static ASMJIT_INLINE uint32_t x86OpcodeLByVMem(const Operand_& op) noexcept { - return x86LLByRegType[op.as<Mem>().indexType()]; +static ASMJIT_FORCE_INLINE uint32_t x86OpcodeLByVMem(const Operand_& op) noexcept { + return x86LLByRegType[size_t(op.as<Mem>().indexType())]; } -static ASMJIT_INLINE uint32_t x86OpcodeLBySize(uint32_t size) noexcept { +static ASMJIT_FORCE_INLINE uint32_t x86OpcodeLBySize(uint32_t size) noexcept { return x86LLBySizeDiv16[size / 16]; } //! Encode MOD byte. -static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept { +static ASMJIT_FORCE_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept { ASMJIT_ASSERT(m <= 3); ASMJIT_ASSERT(o <= 7); ASMJIT_ASSERT(rm <= 7); @@ -348,14 +315,14 @@ static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) } //! Encode SIB byte. -static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) noexcept { +static ASMJIT_FORCE_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) noexcept { ASMJIT_ASSERT(s <= 3); ASMJIT_ASSERT(i <= 7); ASMJIT_ASSERT(b <= 7); return (s << 6) + (i << 3) + b; } -static ASMJIT_INLINE bool x86IsRexInvalid(uint32_t rex) noexcept { +static ASMJIT_FORCE_INLINE bool x86IsRexInvalid(uint32_t rex) noexcept { // Validates the following possibilities: // REX == 0x00 -> OKAY (X86_32 / X86_64). // REX == 0x40-0x4F -> OKAY (X86_64). @@ -364,29 +331,33 @@ static ASMJIT_INLINE bool x86IsRexInvalid(uint32_t rex) noexcept { return rex > kX86ByteInvalidRex; } +static ASMJIT_FORCE_INLINE uint32_t x86GetForceEvex3MaskInLastBit(InstOptions options) noexcept { + constexpr uint32_t kVex3Bit = Support::ConstCTZ<uint32_t(InstOptions::kX86_Vex3)>::value; + return uint32_t(options & InstOptions::kX86_Vex3) << (31 - kVex3Bit); +} + template<typename T> -static constexpr T x86SignExtendI32(T imm) noexcept { return T(int64_t(int32_t(imm & T(0xFFFFFFFF)))); } +static ASMJIT_FORCE_INLINE constexpr T x86SignExtendI32(T imm) noexcept { return T(int64_t(int32_t(imm & T(0xFFFFFFFF)))); } -static ASMJIT_INLINE uint32_t x86AltOpcodeOf(const InstDB::InstInfo* info) noexcept { +static ASMJIT_FORCE_INLINE uint32_t x86AltOpcodeOf(const InstDB::InstInfo* info) noexcept { return InstDB::_altOpcodeTable[info->_altOpcodeIndex]; } -// ============================================================================ -// [asmjit::X86BufferWriter] -// ============================================================================ +// x86::Assembler - X86BufferWriter +// ================================ class X86BufferWriter : public CodeWriter { public: - ASMJIT_INLINE explicit X86BufferWriter(Assembler* a) noexcept + ASMJIT_FORCE_INLINE explicit X86BufferWriter(Assembler* a) noexcept : CodeWriter(a) {} - ASMJIT_INLINE void emitPP(uint32_t opcode) noexcept { + ASMJIT_FORCE_INLINE void emitPP(uint32_t opcode) noexcept { uint32_t ppIndex = (opcode >> Opcode::kPP_Shift) & (Opcode::kPP_FPUMask >> Opcode::kPP_Shift) ; emit8If(x86OpcodePP[ppIndex], ppIndex != 0); } - ASMJIT_INLINE void emitMMAndOpcode(uint32_t opcode) noexcept { + ASMJIT_FORCE_INLINE void emitMMAndOpcode(uint32_t opcode) noexcept { uint32_t mmIndex = (opcode & Opcode::kMM_Mask) >> Opcode::kMM_Shift; const X86OpcodeMM& mmCode = x86OpcodeMM[mmIndex]; @@ -395,7 +366,7 @@ public: emit8(opcode); } - ASMJIT_INLINE void emitSegmentOverride(uint32_t segmentId) noexcept { + ASMJIT_FORCE_INLINE void emitSegmentOverride(uint32_t segmentId) noexcept { ASMJIT_ASSERT(segmentId < ASMJIT_ARRAY_SIZE(x86SegmentPrefix)); FastUInt8 prefix = x86SegmentPrefix[segmentId]; @@ -403,11 +374,11 @@ public: } template<typename CondT> - ASMJIT_INLINE void emitAddressOverride(CondT condition) noexcept { + ASMJIT_FORCE_INLINE void emitAddressOverride(CondT condition) noexcept { emit8If(0x67, condition); } - ASMJIT_INLINE void emitImmByteOrDWord(uint64_t immValue, FastUInt8 immSize) noexcept { + ASMJIT_FORCE_INLINE void emitImmByteOrDWord(uint64_t immValue, FastUInt8 immSize) noexcept { if (!immSize) return; @@ -431,7 +402,7 @@ public: emit8(imm & 0xFFu); } - ASMJIT_INLINE void emitImmediate(uint64_t immValue, FastUInt8 immSize) noexcept { + ASMJIT_FORCE_INLINE void emitImmediate(uint64_t immValue, FastUInt8 immSize) noexcept { #if ASMJIT_ARCH_BITS >= 64 uint64_t imm = immValue; if (immSize >= 4) { @@ -474,45 +445,57 @@ public: // If the operand is AH|BH|CH|DH // - patch its index from 0..3 to 4..7 as encoded by X86. // - Disallow REX prefix. -#define FIXUP_GPB(REG_OP, REG_ID) \ - do { \ - if (!static_cast<const Gp&>(REG_OP).isGpbHi()) { \ - options |= (REG_ID >= 4) ? uint32_t(Inst::kOptionRex) \ - : uint32_t(0); \ - } \ - else { \ - options |= Inst::_kOptionInvalidRex; \ - REG_ID += 4; \ - } \ +#define FIXUP_GPB(REG_OP, REG_ID) \ + do { \ + if (!static_cast<const Gp&>(REG_OP).isGpbHi()) { \ + options |= (REG_ID) >= 4 ? InstOptions::kX86_Rex \ + : InstOptions::kNone; \ + } \ + else { \ + options |= InstOptions::kX86_InvalidRex; \ + REG_ID += 4; \ + } \ } while (0) -#define ENC_OPS1(OP0) ((Operand::kOp##OP0)) -#define ENC_OPS2(OP0, OP1) ((Operand::kOp##OP0) + ((Operand::kOp##OP1) << 3)) -#define ENC_OPS3(OP0, OP1, OP2) ((Operand::kOp##OP0) + ((Operand::kOp##OP1) << 3) + ((Operand::kOp##OP2) << 6)) -#define ENC_OPS4(OP0, OP1, OP2, OP3) ((Operand::kOp##OP0) + ((Operand::kOp##OP1) << 3) + ((Operand::kOp##OP2) << 6) + ((Operand::kOp##OP3) << 9)) +#define ENC_OPS1(OP0) \ + (uint32_t(OperandType::k##OP0)) -// ============================================================================ -// [asmjit::x86::Assembler - Movabs Heuristics] -// ============================================================================ +#define ENC_OPS2(OP0, OP1) \ + (uint32_t(OperandType::k##OP0) + \ + (uint32_t(OperandType::k##OP1) << 3)) -static ASMJIT_INLINE uint32_t x86GetMovAbsInstSize64Bit(uint32_t regSize, uint32_t options, const Mem& rmRel) noexcept { +#define ENC_OPS3(OP0, OP1, OP2) \ + (uint32_t(OperandType::k##OP0) + \ + (uint32_t(OperandType::k##OP1) << 3) + \ + (uint32_t(OperandType::k##OP2) << 6)) + +#define ENC_OPS4(OP0, OP1, OP2, OP3) \ + (uint32_t(OperandType::k##OP0) + \ + (uint32_t(OperandType::k##OP1) << 3) + \ + (uint32_t(OperandType::k##OP2) << 6) + \ + (uint32_t(OperandType::k##OP3) << 9)) + +// x86::Assembler - Movabs Heuristics +// ================================== + +static ASMJIT_FORCE_INLINE uint32_t x86GetMovAbsInstSize64Bit(uint32_t regSize, InstOptions options, const Mem& rmRel) noexcept { uint32_t segmentPrefixSize = rmRel.segmentId() != 0; uint32_t _66hPrefixSize = regSize == 2; - uint32_t rexPrefixSize = (regSize == 8) || ((options & Inst::kOptionRex) != 0); + uint32_t rexPrefixSize = regSize == 8 || Support::test(options, InstOptions::kX86_Rex); uint32_t opCodeByteSize = 1; uint32_t immediateSize = 8; return segmentPrefixSize + _66hPrefixSize + rexPrefixSize + opCodeByteSize + immediateSize; } -static ASMJIT_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWriter& writer, uint32_t regSize, uint32_t options, const Mem& rmRel) noexcept { +static ASMJIT_FORCE_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWriter& writer, uint32_t regSize, InstOptions options, const Mem& rmRel) noexcept { if (self->is32Bit()) { // There is no relative addressing, just decide whether to use MOV encoded with MOD R/M or absolute. - return !(options & Inst::kOptionModMR); + return !Support::test(options, InstOptions::kX86_ModMR | InstOptions::kX86_ModMR); } else { // If the addressing type is REL or MOD R/M was specified then absolute mov won't be used. - if (rmRel.addrType() == Mem::kAddrTypeRel || (options & Inst::kOptionModMR) != 0) + if (rmRel.addrType() == Mem::AddrType::kRel || Support::test(options, InstOptions::kX86_ModMR)) return false; int64_t addrValue = rmRel.offset(); @@ -520,7 +503,7 @@ static ASMJIT_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWriter& w // If the address type is default, it means to basically check whether relative addressing is possible. However, // this is only possible when the base address is known - relative encoding uses RIP+N it has to be calculated. - if (rmRel.addrType() == Mem::kAddrTypeDefault && baseAddress != Globals::kNoBaseAddress && !rmRel.hasSegment()) { + if (rmRel.addrType() == Mem::AddrType::kDefault && baseAddress != Globals::kNoBaseAddress && !rmRel.hasSegment()) { uint32_t instructionSize = x86GetMovAbsInstSize64Bit(regSize, options, rmRel); uint64_t virtualOffset = uint64_t(writer.offsetFrom(self->_bufferData)); uint64_t rip64 = baseAddress + self->_section->offset() + virtualOffset + instructionSize; @@ -538,9 +521,8 @@ static ASMJIT_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWriter& w } } -// ============================================================================ -// [asmjit::x86::Assembler - Construction / Destruction] -// ============================================================================ +// x86::Assembler - Construction & Destruction +// =========================================== Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { if (code) @@ -548,27 +530,26 @@ Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { } Assembler::~Assembler() noexcept {} -// ============================================================================ -// [asmjit::x86::Assembler - Emit (Low-Level)] -// ============================================================================ +// x86::Assembler - Emit (Low-Level) +// ================================= -ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { +ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { constexpr uint32_t kVSHR_W = Opcode::kW_Shift - 23; constexpr uint32_t kVSHR_PP = Opcode::kPP_Shift - 16; constexpr uint32_t kVSHR_PP_EW = Opcode::kPP_Shift - 16; - constexpr uint32_t kRequiresSpecialHandling = - uint32_t(Inst::kOptionReserved) | // Logging/Validation/Error. - uint32_t(Inst::kOptionRep ) | // REP/REPE prefix. - uint32_t(Inst::kOptionRepne ) | // REPNE prefix. - uint32_t(Inst::kOptionLock ) | // LOCK prefix. - uint32_t(Inst::kOptionXAcquire) | // XACQUIRE prefix. - uint32_t(Inst::kOptionXRelease) ; // XRELEASE prefix. + constexpr InstOptions kRequiresSpecialHandling = + InstOptions::kReserved | // Logging/Validation/Error. + InstOptions::kX86_Rep | // REP/REPE prefix. + InstOptions::kX86_Repne | // REPNE prefix. + InstOptions::kX86_Lock | // LOCK prefix. + InstOptions::kX86_XAcquire | // XACQUIRE prefix. + InstOptions::kX86_XRelease ; // XRELEASE prefix. Error err; Opcode opcode; // Instruction opcode. - uint32_t options; // Instruction options. + InstOptions options; // Instruction options. uint32_t isign3; // A combined signature of first 3 operands. const Operand_* rmRel; // Memory operand or operand that holds Label|Imm. @@ -595,17 +576,16 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c const InstDB::CommonInfo* commonInfo = &instInfo->commonInfo(); // Signature of the first 3 operands. - isign3 = o0.opType() + (o1.opType() << 3) + (o2.opType() << 6); + isign3 = (uint32_t(o0.opType()) ) + + (uint32_t(o1.opType()) << 3) + + (uint32_t(o2.opType()) << 6); - // Combine all instruction options and also check whether the instruction - // is valid. All options that require special handling (including invalid - // instruction) are handled by the next branch. - options = uint32_t(instId == 0); - options |= uint32_t((size_t)(_bufferEnd - writer.cursor()) < 16); - options |= uint32_t(instOptions() | forcedInstOptions()); + // Combine all instruction options and also check whether the instruction is valid. All options + // that require special handling (including invalid instruction) are handled by the next branch. + options = InstOptions((instId == 0) | ((size_t)(_bufferEnd - writer.cursor()) < 16)) | instOptions() | forcedInstOptions(); // Handle failure and rare cases first. - if (ASMJIT_UNLIKELY(options & kRequiresSpecialHandling)) { + if (ASMJIT_UNLIKELY(Support::test(options, kRequiresSpecialHandling))) { if (ASMJIT_UNLIKELY(!_code)) return reportError(DebugUtils::errored(kErrorNotInitialized)); @@ -620,7 +600,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c #ifndef ASMJIT_NO_VALIDATION // Strict validation. - if (hasValidationOption(kValidationOptionAssembler)) { + if (hasDiagnosticOption(DiagnosticOptions::kValidateAssembler)) { Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); @@ -630,37 +610,37 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c } #endif - uint32_t iFlags = instInfo->flags(); + InstDB::InstFlags iFlags = instInfo->flags(); // LOCK, XACQUIRE, and XRELEASE prefixes. - if (options & Inst::kOptionLock) { - bool xAcqRel = (options & (Inst::kOptionXAcquire | Inst::kOptionXRelease)) != 0; + if (Support::test(options, InstOptions::kX86_Lock)) { + bool xAcqRel = Support::test(options, InstOptions::kX86_XAcquire | InstOptions::kX86_XRelease); - if (ASMJIT_UNLIKELY(!(iFlags & (InstDB::kFlagLock)) && !xAcqRel)) + if (ASMJIT_UNLIKELY(!Support::test(iFlags, InstDB::InstFlags::kLock) && !xAcqRel)) goto InvalidLockPrefix; if (xAcqRel) { - if (ASMJIT_UNLIKELY((options & Inst::kOptionXAcquire) && !(iFlags & InstDB::kFlagXAcquire))) + if (ASMJIT_UNLIKELY(Support::test(options, InstOptions::kX86_XAcquire) && !Support::test(iFlags, InstDB::InstFlags::kXAcquire))) goto InvalidXAcquirePrefix; - if (ASMJIT_UNLIKELY((options & Inst::kOptionXRelease) && !(iFlags & InstDB::kFlagXRelease))) + if (ASMJIT_UNLIKELY(Support::test(options, InstOptions::kX86_XRelease) && !Support::test(iFlags, InstDB::InstFlags::kXRelease))) goto InvalidXReleasePrefix; - writer.emit8((options & Inst::kOptionXAcquire) ? 0xF2 : 0xF3); + writer.emit8(Support::test(options, InstOptions::kX86_XAcquire) ? 0xF2 : 0xF3); } writer.emit8(0xF0); } // REP and REPNE prefixes. - if (options & (Inst::kOptionRep | Inst::kOptionRepne)) { - if (ASMJIT_UNLIKELY(!(iFlags & InstDB::kFlagRep))) + if (Support::test(options, InstOptions::kX86_Rep | InstOptions::kX86_Repne)) { + if (ASMJIT_UNLIKELY(!Support::test(iFlags, InstDB::InstFlags::kRep))) goto InvalidRepPrefix; - if (_extraReg.isReg() && ASMJIT_UNLIKELY(_extraReg.group() != Reg::kGroupGp || _extraReg.id() != Gp::kIdCx)) + if (ASMJIT_UNLIKELY(_extraReg.isReg() && (_extraReg.group() != RegGroup::kGp || _extraReg.id() != Gp::kIdCx))) goto InvalidRepPrefix; - writer.emit8((options & Inst::kOptionRepne) ? 0xF2 : 0xF3); + writer.emit8(Support::test(options, InstOptions::kX86_Repne) ? 0xF2 : 0xF3); } } @@ -670,24 +650,20 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c rbReg = 0; opcode |= instInfo->_mainOpcodeValue; - // -------------------------------------------------------------------------- - // [Encoding Scope] - // -------------------------------------------------------------------------- + // Encoding Scope + // -------------- - // How it works? Each case here represents a unique encoding of a group of - // instructions, which is handled separately. The handlers check instruction - // signature, possibly register types, etc, and process this information by - // writing some bits to opcode, opReg/rbReg, immValue/immSize, etc, and then - // at the end of the sequence it uses goto to jump into a lower level handler, - // that actually encodes the instruction. + // How it works? Each case here represents a unique encoding of a group of instructions, which is handled + // separately. The handlers check instruction signature, possibly register types, etc, and process this + // information by writing some bits to opcode, opReg/rbReg, immValue/immSize, etc, and then at the end of + // the sequence it uses goto to jump into a lower level handler, that actually encodes the instruction. switch (instInfo->_encoding) { case InstDB::kEncodingNone: goto EmitDone; - // ------------------------------------------------------------------------ - // [X86] - // ------------------------------------------------------------------------ + // Base Instructions + // ----------------- case InstDB::kEncodingX86Op: goto EmitX86Op; @@ -710,7 +686,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c if (ASMJIT_UNLIKELY(!o0.isReg())) goto InvalidInstruction; - rmInfo = x86MemInfo[o0.as<Reg>().type()]; + rmInfo = x86MemInfo[size_t(o0.as<Reg>().type())]; writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0); goto EmitX86Op; @@ -1005,7 +981,7 @@ CaseX86M_GPB_MulDiv: } // MOD/MR: The default encoding used if not instructed otherwise.. - if (!(options & Inst::kOptionModRM)) + if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; // MOD/RM: Alternative encoding selected via instruction options. @@ -1073,7 +1049,7 @@ CaseX86M_GPB_MulDiv: else goto InvalidImmediate; } - else if (canTransformTo32Bit && hasEncodingOption(kEncodingOptionOptimizeForSize)) { + else if (canTransformTo32Bit && hasEncodingOption(EncodingOptions::kOptimizeForSize)) { size = 4; } @@ -1081,12 +1057,12 @@ CaseX86M_GPB_MulDiv: } immSize = FastUInt8(Support::min<uint32_t>(size, 4)); - if (Support::isInt8(immValue) && !(options & Inst::kOptionLongForm)) + if (Support::isInt8(immValue) && !Support::test(options, InstOptions::kLongForm)) immSize = 1; } // Short form - AL, AX, EAX, RAX. - if (rbReg == 0 && (size == 1 || immSize != 1) && !(options & Inst::kOptionLongForm)) { + if (rbReg == 0 && (size == 1 || immSize != 1) && !Support::test(options, InstOptions::kLongForm)) { opcode &= Opcode::kPP_66 | Opcode::kW; opcode |= ((opReg << 3) | (0x04 + (size != 1))); immSize = FastUInt8(Support::min<uint32_t>(size, 4)); @@ -1110,7 +1086,7 @@ CaseX86M_GPB_MulDiv: if (memSize == 4) immValue = x86SignExtendI32<int64_t>(immValue); - if (Support::isInt8(immValue) && !(options & Inst::kOptionLongForm)) + if (Support::isInt8(immValue) && !Support::test(options, InstOptions::kLongForm)) immSize = 1; opcode += memSize != 1 ? (immSize != 1 ? 1 : 3) : 0; @@ -1179,9 +1155,8 @@ CaseX86M_GPB_MulDiv: if (isign3 == ENC_OPS1(Mem)) goto EmitX86M; - // Call with 32-bit displacement use 0xE8 opcode. Call with 8-bit - // displacement is not encodable so the alternative opcode field - // in X86DB must be zero. + // Call with 32-bit displacement use 0xE8 opcode. Call with 8-bit displacement is not encodable so the + // alternative opcode field in X86DB must be zero. opcode = 0xE8; opReg = 0; goto EmitJmpCall; @@ -1295,7 +1270,7 @@ CaseX86M_GPB_MulDiv: immValue = o2.as<Imm>().value(); immSize = 1; - if (!Support::isInt8(immValue) || (options & Inst::kOptionLongForm)) { + if (!Support::isInt8(immValue) || Support::test(options, InstOptions::kLongForm)) { opcode -= 2; immSize = o0.size() == 2 ? 2 : 4; } @@ -1317,7 +1292,7 @@ CaseX86M_GPB_MulDiv: if (o0.size() == 4) immValue = x86SignExtendI32<int64_t>(immValue); - if (!Support::isInt8(immValue) || (options & Inst::kOptionLongForm)) { + if (!Support::isInt8(immValue) || Support::test(options, InstOptions::kLongForm)) { opcode -= 2; immSize = o0.size() == 2 ? 2 : 4; } @@ -1369,7 +1344,7 @@ CaseX86M_GPB_MulDiv: if (o0.size() == 4) immValue = x86SignExtendI32<int64_t>(immValue); - if (!Support::isInt8(immValue) || (options & Inst::kOptionLongForm)) { + if (!Support::isInt8(immValue) || Support::test(options, InstOptions::kLongForm)) { opcode -= 2; immSize = o0.size() == 2 ? 2 : 4; } @@ -1460,8 +1435,8 @@ CaseX86M_GPB_MulDiv: break; case InstDB::kEncodingX86Jcc: - if ((options & (Inst::kOptionTaken | Inst::kOptionNotTaken)) && hasEncodingOption(kEncodingOptionPredictedJumps)) { - uint8_t prefix = (options & Inst::kOptionTaken) ? uint8_t(0x3E) : uint8_t(0x2E); + if (Support::test(options, InstOptions::kTaken | InstOptions::kNotTaken) && hasEncodingOption(EncodingOptions::kPredictedJumps)) { + uint8_t prefix = Support::test(options, InstOptions::kTaken) ? uint8_t(0x3E) : uint8_t(0x2E); writer.emit8(prefix); } @@ -1493,8 +1468,8 @@ CaseX86M_GPB_MulDiv: if (isign3 == ENC_OPS1(Mem)) goto EmitX86M; - // Jump encoded with 32-bit displacement use 0xE9 opcode. Jump encoded - // with 8-bit displacement's opcode is stored as an alternative opcode. + // Jump encoded with 32-bit displacement use 0xE9 opcode. Jump encoded with 8-bit displacement's opcode is + // stored as an alternative opcode. opcode = 0xE9; opReg = 0; goto EmitJmpCall; @@ -1548,11 +1523,9 @@ CaseX86M_GPB_MulDiv: case InstDB::kEncodingX86Mov: // Reg <- Reg if (isign3 == ENC_OPS2(Reg, Reg)) { - // Asmjit uses segment registers indexed from 1 to 6, leaving zero as - // "no segment register used". We have to fix this (decrement the index - // of the register) when emitting MOV instructions which move to/from - // a segment register. The segment register is always `opReg`, because - // the MOV instruction uses either RM or MR encoding. + // Asmjit uses segment registers indexed from 1 to 6, leaving zero as "no segment register used". We have to + // fix this (decrement the index of the register) when emitting MOV instructions which move to/from a segment + // register. The segment register is always `opReg`, because the MOV instruction uses either RM or MR encoding. // GP <- ?? if (Reg::isGp(o0)) { @@ -1562,21 +1535,15 @@ CaseX86M_GPB_MulDiv: // GP <- GP if (Reg::isGp(o1)) { uint32_t opSize = o0.size(); - if (opSize != o1.size()) { - // TODO: [X86 Assembler] This is a non-standard extension, which should be removed. - // We allow 'mov r64, r32' as it's basically zero-extend. - if (opSize == 8 && o1.size() == 4) - opSize = 4; // Zero extend, don't promote to 64-bit. - else - goto InvalidInstruction; - } + if (opSize != o1.size()) + goto InvalidInstruction; if (opSize == 1) { FIXUP_GPB(o0, rbReg); FIXUP_GPB(o1, opReg); opcode = 0x88; - if (!(options & Inst::kOptionModRM)) + if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; opcode += 2; @@ -1587,7 +1554,7 @@ CaseX86M_GPB_MulDiv: opcode = 0x89; opcode.addPrefixBySize(opSize); - if (!(options & Inst::kOptionModRM)) + if (!Support::test(options, InstOptions::kX86_ModRM)) goto EmitX86R; opcode += 2; @@ -1742,8 +1709,8 @@ CaseX86M_GPB_MulDiv: immValue = o1.as<Imm>().value(); // Optimize the instruction size by using a 32-bit immediate if possible. - if (immSize == 8 && !(options & Inst::kOptionLongForm)) { - if (Support::isUInt32(immValue) && hasEncodingOption(kEncodingOptionOptimizeForSize)) { + if (immSize == 8 && !Support::test(options, InstOptions::kLongForm)) { + if (Support::isUInt32(immValue) && hasEncodingOption(EncodingOptions::kOptimizeForSize)) { // Zero-extend by using a 32-bit GPD destination instead of a 64-bit GPQ. immSize = 4; } @@ -1796,7 +1763,7 @@ CaseX86M_GPB_MulDiv: if (ASMJIT_UNLIKELY(rmRel->as<Mem>().hasBaseOrIndex())) goto InvalidAddress; - if (ASMJIT_UNLIKELY(rmRel->as<Mem>().addrType() == Mem::kAddrTypeRel)) + if (ASMJIT_UNLIKELY(rmRel->as<Mem>().addrType() == Mem::AddrType::kRel)) goto InvalidAddress; immValue = rmRel->as<Mem>().offset(); @@ -1944,7 +1911,7 @@ CaseX86M_GPB_MulDiv: immValue = o0.as<Imm>().value(); immSize = 4; - if (Support::isInt8(immValue) && !(options & Inst::kOptionLongForm)) + if (Support::isInt8(immValue) && !Support::test(options, InstOptions::kLongForm)) immSize = 1; opcode = immSize == 1 ? 0x6A : 0x68; @@ -1964,9 +1931,8 @@ CaseX86M_GPB_MulDiv: } else { CaseX86PushPop_Gp: - // We allow 2 byte, 4 byte, and 8 byte register sizes, although PUSH - // and POP only allow 2 bytes or native size. On 64-bit we simply - // PUSH/POP 64-bit register even if 32-bit register was given. + // We allow 2 byte, 4 byte, and 8 byte register sizes, although PUSH and POP only allow 2 bytes or + // native size. On 64-bit we simply PUSH/POP 64-bit register even if 32-bit register was given. if (ASMJIT_UNLIKELY(o0.size() < 2)) goto InvalidInstruction; @@ -1999,7 +1965,7 @@ CaseX86PushPop_Gp: if (isign3 == ENC_OPS1(Imm)) { immValue = o0.as<Imm>().value(); - if (immValue == 0 && !(options & Inst::kOptionLongForm)) { + if (immValue == 0 && !Support::test(options, InstOptions::kLongForm)) { // 'ret' without immediate, change C2 to C3. opcode.add(1); goto EmitX86Op; @@ -2031,7 +1997,7 @@ CaseX86PushPop_Gp: immValue = o1.as<Imm>().value() & 0xFF; immSize = 0; - if (immValue == 1 && !(options & Inst::kOptionLongForm)) + if (immValue == 1 && !Support::test(options, InstOptions::kLongForm)) goto EmitX86R; opcode -= 0x10; @@ -2058,7 +2024,7 @@ CaseX86PushPop_Gp: immValue = o1.as<Imm>().value() & 0xFF; immSize = 0; - if (immValue == 1 && !(options & Inst::kOptionLongForm)) + if (immValue == 1 && !Support::test(options, InstOptions::kLongForm)) goto EmitX86M; opcode -= 0x10; @@ -2226,7 +2192,7 @@ CaseX86PushPop_Gp: } // Short form - AL, AX, EAX, RAX. - if (rbReg == 0 && !(options & Inst::kOptionLongForm)) { + if (rbReg == 0 && !Support::test(options, InstOptions::kLongForm)) { opcode &= Opcode::kPP_66 | Opcode::kW; opcode |= 0xA8 + (o0.size() != 1); goto EmitX86Op; @@ -2290,7 +2256,7 @@ CaseX86PushPop_Gp: // Encode 'xchg eax, eax' by by using a generic path. } } - else if (!(options & Inst::kOptionLongForm)) { + else if (!Support::test(options, InstOptions::kLongForm)) { // The special encoding encodes only one register, which is non-zero. opReg += rbReg; @@ -2328,7 +2294,7 @@ CaseX86PushPop_Gp: rbReg = o1.id(); // ModRM encoding: - if (!(options & Inst::kOptionModMR)) + if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitX86R; // ModMR encoding: @@ -2352,9 +2318,8 @@ CaseX86PushPop_Gp: } break; - // ------------------------------------------------------------------------ - // [FPU] - // ------------------------------------------------------------------------ + // FPU Instructions + // ---------------- case InstDB::kEncodingFpuOp: goto EmitFpuOp; @@ -2414,16 +2379,16 @@ CaseFpuArith_Mem: if (isign3 == ENC_OPS1(Mem)) { rmRel = &o0; - if (o0.size() == 4 && commonInfo->hasFlag(InstDB::kFlagFpuM32)) { + if (o0.size() == 4 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM32)) { goto EmitX86M; } - if (o0.size() == 8 && commonInfo->hasFlag(InstDB::kFlagFpuM64)) { + if (o0.size() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { opcode += 4; goto EmitX86M; } - if (o0.size() == 10 && commonInfo->hasFlag(InstDB::kFlagFpuM80)) { + if (o0.size() == 10 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM80)) { opcode = x86AltOpcodeOf(instInfo); opReg = opcode.extractModO(); goto EmitX86M; @@ -2443,16 +2408,16 @@ CaseFpuArith_Mem: opcode &= ~uint32_t(Opcode::kCDSHL_Mask); rmRel = &o0; - if (o0.size() == 2 && commonInfo->hasFlag(InstDB::kFlagFpuM16)) { + if (o0.size() == 2 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM16)) { opcode += 4; goto EmitX86M; } - if (o0.size() == 4 && commonInfo->hasFlag(InstDB::kFlagFpuM32)) { + if (o0.size() == 4 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM32)) { goto EmitX86M; } - if (o0.size() == 8 && commonInfo->hasFlag(InstDB::kFlagFpuM64)) { + if (o0.size() == 8 && commonInfo->hasFlag(InstDB::InstFlags::kFpuM64)) { opcode = x86AltOpcodeOf(instInfo) & ~uint32_t(Opcode::kCDSHL_Mask); opReg = opcode.extractModO(); goto EmitX86M; @@ -2492,9 +2457,8 @@ CaseFpuArith_Mem: } break; - // ------------------------------------------------------------------------ - // [Ext] - // ------------------------------------------------------------------------ + // Ext Instructions (Legacy Extensions) + // ------------------------------------ case InstDB::kEncodingExtPextrw: if (isign3 == ENC_OPS3(Reg, Reg, Imm)) { @@ -2552,7 +2516,7 @@ CaseFpuArith_Mem: opReg = o0.id(); rbReg = o1.id(); - if (!(options & Inst::kOptionModMR) || !instInfo->_altOpcodeIndex) + if (!Support::test(options, InstOptions::kX86_ModMR) || !instInfo->_altOpcodeIndex) goto EmitX86R; opcode = x86AltOpcodeOf(instInfo); @@ -2648,7 +2612,7 @@ CaseExtMovd: if (Reg::isMm(o0) && Reg::isMm(o1)) { opcode = Opcode::k000F00 | 0x6F; - if (!(options & Inst::kOptionModMR)) + if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitX86R; opcode += 0x10; @@ -2660,7 +2624,7 @@ CaseExtMovd: if (Reg::isXmm(o0) && Reg::isXmm(o1)) { opcode = Opcode::kF30F00 | 0x7E; - if (!(options & Inst::kOptionModMR)) + if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitX86R; opcode = Opcode::k660F00 | 0xD6; @@ -2858,9 +2822,8 @@ CaseExtRm: } break; - // ------------------------------------------------------------------------ - // [Extrq / Insertq (SSE4A)] - // ------------------------------------------------------------------------ + // Extrq & Insertq (SSE4A) + // ----------------------- case InstDB::kEncodingExtExtrq: opReg = o0.id(); @@ -2884,7 +2847,7 @@ CaseExtRm: case InstDB::kEncodingExtInsertq: { const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); opReg = o0.id(); rbReg = o1.id(); @@ -2904,9 +2867,8 @@ CaseExtRm: break; } - // ------------------------------------------------------------------------ - // [3dNow] - // ------------------------------------------------------------------------ + // 3DNOW Instructions + // ------------------ case InstDB::kEncodingExt3dNow: // Every 3dNow instruction starts with 0x0F0F and the actual opcode is @@ -2928,12 +2890,11 @@ CaseExtRm: } break; - // ------------------------------------------------------------------------ - // [VEX/EVEX] - // ------------------------------------------------------------------------ + // VEX/EVEX Instructions + // --------------------- case InstDB::kEncodingVexOp: - goto EmitVexEvexOp; + goto EmitVexOp; case InstDB::kEncodingVexOpMod: rbReg = 0; @@ -2957,7 +2918,7 @@ CaseExtRm: } // Form 'k, k'. - if (!(options & Inst::kOptionModMR)) + if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitVexEvexR; opcode.add(1); @@ -3239,7 +3200,7 @@ CaseVexRvm_R: case InstDB::kEncodingVexRvmr: { const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); immValue = o3.id() << 4; immSize = 1; @@ -3274,7 +3235,7 @@ CaseVexRvm_R: VexRvmi: { const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); immValue = o3.as<Imm>().value(); immSize = 1; @@ -3335,7 +3296,7 @@ VexRvmi: case InstDB::kEncodingVexRmvi: { const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); immValue = o3.as<Imm>().value(); immSize = 1; @@ -3441,7 +3402,7 @@ VexRvmi: opReg = x86PackRegAndVvvvv(o0.id(), o2.id()); rbReg = o1.id(); - if (!(options & Inst::kOptionModMR)) + if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitVexEvexR; opcode.addW(); @@ -3506,7 +3467,7 @@ VexRvmi: opReg = x86PackRegAndVvvvv(o0.id(), o2.id()); rbReg = o1.id(); - if (!(options & Inst::kOptionModMR)) + if (!Support::test(options, InstOptions::kX86_ModMR)) goto EmitVexEvexR; opcode.addW(); @@ -3703,7 +3664,7 @@ CaseVexVmi_AfterImm: case InstDB::kEncodingVexRvrmRvmr: { const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { opReg = x86PackRegAndVvvvv(o0.id(), o1.id()); @@ -3742,7 +3703,7 @@ CaseVexVmi_AfterImm: if (ASMJIT_UNLIKELY(!o4.isImm())) goto InvalidInstruction; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); opcode |= x86OpcodeLBySize(o0.size() | o1.size() | o2.size() | o3.size()); immValue = o4.as<Imm>().valueAs<uint8_t>() & 0x0F; @@ -3794,9 +3755,8 @@ CaseVexVmi_AfterImm: } break; - // ------------------------------------------------------------------------ - // [FMA4] - // ------------------------------------------------------------------------ + // FMA4 Instructions + // ----------------- case InstDB::kEncodingFma4_Lx: // It's fine to just check the first operand, second is just for sanity. @@ -3805,12 +3765,12 @@ CaseVexVmi_AfterImm: case InstDB::kEncodingFma4: { const Operand_& o3 = opExt[EmitterUtils::kOp3]; - const uint32_t isign4 = isign3 + (o3.opType() << 9); + const uint32_t isign4 = isign3 + (uint32_t(o3.opType()) << 9); if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { opReg = x86PackRegAndVvvvv(o0.id(), o1.id()); - if (!(options & Inst::kOptionModMR)) { + if (!Support::test(options, InstOptions::kX86_ModMR)) { // MOD/RM - Encoding preferred by LLVM. opcode.addW(); rbReg = o3.id(); @@ -3850,9 +3810,8 @@ CaseVexVmi_AfterImm: break; } - // ------------------------------------------------------------------------ - // [AMX] - // ------------------------------------------------------------------------ + // AMX Instructions + // ---------------- case InstDB::kEncodingAmxCfg: if (isign3 == ENC_OPS1(Mem)) { @@ -3896,9 +3855,8 @@ CaseVexVmi_AfterImm: goto InvalidInstruction; - // -------------------------------------------------------------------------- - // [Emit - X86] - // -------------------------------------------------------------------------- + // Emit - X86 Opcode + // ----------------- EmitX86OpMovAbs: immSize = FastUInt8(registerSize()); @@ -3922,9 +3880,8 @@ EmitX86Op: writer.emitImmediate(uint64_t(immValue), immSize); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - X86 - Opcode + Reg] - // -------------------------------------------------------------------------- + // Emit - X86 - Opcode + Reg + // ------------------------- EmitX86OpReg: // Emit mandatory instruction prefix. @@ -3947,9 +3904,8 @@ EmitX86OpReg: writer.emitImmediate(uint64_t(immValue), immSize); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - X86 - Opcode with implicit <mem> operand] - // -------------------------------------------------------------------------- + // Emit - X86 - Opcode with Implicit <mem> Operand + // ----------------------------------------------- EmitX86OpImplicitMem: rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()]; @@ -3979,9 +3935,8 @@ EmitX86OpImplicitMem: writer.emitImmediate(uint64_t(immValue), immSize); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - X86 - Opcode /r - register] - // -------------------------------------------------------------------------- + // Emit - X86 - Opcode /r - Register + // --------------------------------- EmitX86R: // Mandatory instruction prefix. @@ -4012,9 +3967,8 @@ EmitX86R: writer.emitImmediate(uint64_t(immValue), immSize); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - X86 - Opcode /r - memory base] - // -------------------------------------------------------------------------- + // Emit - X86 - Opcode /r - Memory Base + // ------------------------------------ EmitX86RFromM: rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()]; @@ -4053,14 +4007,13 @@ EmitX86RFromM: writer.emitImmediate(uint64_t(immValue), immSize); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - X86 - Opcode /r - memory operand] - // -------------------------------------------------------------------------- + // Emit - X86 - Opcode /r - memory Operand + // --------------------------------------- EmitX86M: // `rmRel` operand must be memory. ASMJIT_ASSERT(rmRel != nullptr); - ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem); + ASMJIT_ASSERT(rmRel->opType() == OperandType::kMem); ASMJIT_ASSERT((opcode & Opcode::kCDSHL_Mask) == 0); // Emit override prefixes. @@ -4099,9 +4052,8 @@ EmitX86M: // ... Fall through ... - // -------------------------------------------------------------------------- - // [Emit - MOD/SIB] - // -------------------------------------------------------------------------- + // Emit - MOD/SIB + // -------------- EmitModSib: if (!(rmInfo & (kX86MemInfo_Index | kX86MemInfo_67H_X86))) { @@ -4158,12 +4110,12 @@ EmitModSib: } // ==========|> [ABSOLUTE | DISP32]. else if (!(rmInfo & (kX86MemInfo_BaseLabel | kX86MemInfo_BaseRip))) { - uint32_t addrType = rmRel->as<Mem>().addrType(); + Mem::AddrType addrType = rmRel->as<Mem>().addrType(); relOffset = rmRel->as<Mem>().offsetLo32(); if (is32Bit()) { // Explicit relative addressing doesn't work in 32-bit mode. - if (ASMJIT_UNLIKELY(addrType == Mem::kAddrTypeRel)) + if (ASMJIT_UNLIKELY(addrType == Mem::AddrType::kRel)) goto InvalidAddress; writer.emit8(x86EncodeMod(0, opReg, 5)); @@ -4174,14 +4126,13 @@ EmitModSib: bool isOffsetU32 = rmRel->as<Mem>().offsetHi32() == 0; uint64_t baseAddress = code()->baseAddress(); - // If relative addressing was not explicitly set then we can try to guess. - // By guessing we check some properties of the memory operand and try to - // base the decision on the segment prefix and the address type. - if (addrType == Mem::kAddrTypeDefault) { + // If relative addressing was not explicitly set then we can try to guess. By guessing we check some + // properties of the memory operand and try to base the decision on the segment prefix and the address type. + if (addrType == Mem::AddrType::kDefault) { if (baseAddress == Globals::kNoBaseAddress) { // Prefer absolute addressing mode if the offset is 32-bit. - addrType = isOffsetI32 || isOffsetU32 ? Mem::kAddrTypeAbs - : Mem::kAddrTypeRel; + addrType = isOffsetI32 || isOffsetU32 ? Mem::AddrType::kAbs + : Mem::AddrType::kRel; } else { // Prefer absolute addressing mode if FS|GS segment override is present. @@ -4189,18 +4140,18 @@ EmitModSib: // Prefer absolute addressing mode if this is LEA with 32-bit immediate. bool isLea32 = (instId == Inst::kIdLea) && (isOffsetI32 || isOffsetU32); - addrType = hasFsGs || isLea32 ? Mem::kAddrTypeAbs - : Mem::kAddrTypeRel; + addrType = hasFsGs || isLea32 ? Mem::AddrType::kAbs + : Mem::AddrType::kRel; } } - if (addrType == Mem::kAddrTypeRel) { + if (addrType == Mem::AddrType::kRel) { uint32_t kModRel32Size = 5; uint64_t virtualOffset = uint64_t(writer.offsetFrom(_bufferData)) + immSize + kModRel32Size; if (baseAddress == Globals::kNoBaseAddress || _section->id() != 0) { // Create a new RelocEntry as we cannot calculate the offset right now. - err = _code->newRelocEntry(&re, RelocEntry::kTypeAbsToRel); + err = _code->newRelocEntry(&re, RelocType::kAbsToRel); if (ASMJIT_UNLIKELY(err)) goto Failed; @@ -4235,22 +4186,19 @@ EmitModSib: } } - // Handle unsigned 32-bit address that doesn't work with sign extension. - // Consider the following instructions: + // Handle unsigned 32-bit address that doesn't work with sign extension. Consider the following instructions: // // 1. lea rax, [-1] - Sign extended to 0xFFFFFFFFFFFFFFFF // 2. lea rax, [0xFFFFFFFF] - Zero extended to 0x00000000FFFFFFFF // 3. add rax, [-1] - Sign extended to 0xFFFFFFFFFFFFFFFF // 4. add rax, [0xFFFFFFFF] - Zero extended to 0x00000000FFFFFFFF // - // Sign extension is naturally performed by the CPU so we don't have to - // bother, however, zero extension requires address-size override prefix, - // which we probably don't have at this moment. So to make the address + // Sign extension is naturally performed by the CPU so we don't have to bother, however, zero extension + // requires address-size override prefix, which we probably don't have at this moment. So to make the address // valid we need to insert it at `memOpAOMark` if it's not already there. // - // If this is 'lea' instruction then it's possible to remove REX.W part - // from REX prefix (if it's there), which would be one-byte shorter than - // inserting address-size override. + // If this is 'lea' instruction then it's possible to remove REX.W part from REX prefix (if it's there), which + // would be one-byte shorter than inserting address-size override. // // NOTE: If we don't do this then these instructions are unencodable. if (!isOffsetI32) { @@ -4261,16 +4209,15 @@ EmitModSib: // We only patch the existing code if we don't have address-size override. if (*memOpAOMark != 0x67) { if (instId == Inst::kIdLea) { - // LEA: Remove REX.W, if present. This is easy as we know that 'lea' - // doesn't use any PP prefix so if REX prefix was emitted it would be - // at `memOpAOMark`. + // LEA: Remove REX.W, if present. This is easy as we know that 'lea' doesn't use any PP prefix so if REX + // prefix was emitted it would be at `memOpAOMark`. uint32_t rex = *memOpAOMark; if (rex & kX86ByteRex) { rex &= (~kX86ByteRexW) & 0xFF; *memOpAOMark = uint8_t(rex); // We can remove the REX prefix completely if it was not forced. - if (rex == kX86ByteRex && !(options & Inst::kOptionRex)) + if (rex == kX86ByteRex && !Support::test(options, InstOptions::kX86_Rex)) writer.remove8(memOpAOMark); } } @@ -4303,7 +4250,7 @@ EmitModSib_LabelRip_X86: if (ASMJIT_UNLIKELY(!label)) goto InvalidLabel; - err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs); + err = _code->newRelocEntry(&re, RelocType::kRelToAbs); if (ASMJIT_UNLIKELY(err)) goto Failed; @@ -4328,7 +4275,7 @@ EmitModSib_LabelRip_X86: } else { // [RIP->ABS]. - err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs); + err = _code->newRelocEntry(&re, RelocType::kRelToAbs); if (ASMJIT_UNLIKELY(err)) goto Failed; @@ -4370,8 +4317,8 @@ EmitModSib_LabelRip_X86: } } else if (!(rmInfo & kX86MemInfo_67H_X86)) { - // ESP|RSP can't be used as INDEX in pure SIB mode, however, VSIB mode - // allows XMM4|YMM4|ZMM4 (that's why the check is before the label). + // ESP|RSP can't be used as INDEX in pure SIB mode, however, VSIB mode allows XMM4|YMM4|ZMM4 (that's why the + // check is before the label). if (ASMJIT_UNLIKELY(rxReg == Gp::kIdSp)) goto InvalidAddressIndex; @@ -4435,10 +4382,9 @@ EmitModVSib: // 16-bit address mode (32-bit mode with 67 override prefix). relOffset = (int32_t(rmRel->as<Mem>().offsetLo32()) << 16) >> 16; - // NOTE: 16-bit addresses don't use SIB byte and their encoding differs. We - // use a table-based approach to calculate the proper MOD byte as it's easier. - // Also, not all BASE [+ INDEX] combinations are supported in 16-bit mode, so - // this may fail. + // NOTE: 16-bit addresses don't use SIB byte and their encoding differs. We use a table-based approach to + // calculate the proper MOD byte as it's easier. Also, not all BASE [+ INDEX] combinations are supported + // in 16-bit mode, so this may fail. const uint32_t kBaseGpIdx = (kX86MemInfo_BaseGp | kX86MemInfo_Index); if (rmInfo & kBaseGpIdx) { @@ -4490,9 +4436,8 @@ EmitModVSib: writer.emitImmediate(uint64_t(immValue), immSize); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - FPU] - // -------------------------------------------------------------------------- + // Emit - FPU + // ---------- EmitFpuOp: // Mandatory instruction prefix. @@ -4503,31 +4448,29 @@ EmitFpuOp: writer.emit8(opcode.v); goto EmitDone; - // -------------------------------------------------------------------------- - // [Emit - VEX|EVEX] - // -------------------------------------------------------------------------- + // Emit - VEX Opcode + // ----------------- -EmitVexEvexOp: +EmitVexOp: { // These don't use immediate. ASMJIT_ASSERT(immSize == 0); - // Only 'vzeroall' and 'vzeroupper' instructions use this encoding, they - // don't define 'W' to be '1' so we can just check the 'mmmmm' field. Both - // functions can encode by using VEX2 prefix so VEX3 is basically only used + // Only 'vzeroall' and 'vzeroupper' instructions use this encoding, they don't define 'W' to be '1' so we can + // just check the 'mmmmm' field. Both functions can encode by using VEX2 prefix so VEX3 is basically only used // when specified as instruction option. ASMJIT_ASSERT((opcode & Opcode::kW) == 0); - uint32_t x = ((opcode & Opcode::kMM_Mask ) >> (Opcode::kMM_Shift )) | - ((opcode & Opcode::kLL_Mask ) >> (Opcode::kLL_Shift - 10)) | - ((opcode & Opcode::kPP_VEXMask ) >> (Opcode::kPP_Shift - 8)) | - ((options & Inst::kOptionVex3 ) >> (Opcode::kMM_Shift )) ; - if (x & 0x04u) { - x = (x & (0x4 ^ 0xFFFF)) << 8; // [00000000|00000Lpp|0000m0mm|00000000]. - x ^= (kX86ByteVex3) | // [........|00000Lpp|0000m0mm|__VEX3__]. - (0x07u << 13) | // [........|00000Lpp|1110m0mm|__VEX3__]. - (0x0Fu << 19) | // [........|01111Lpp|1110m0mm|__VEX3__]. - (opcode << 24) ; // [_OPCODE_|01111Lpp|1110m0mm|__VEX3__]. + uint32_t x = (uint32_t(opcode & Opcode::kMM_Mask ) >> (Opcode::kMM_Shift )) | + (uint32_t(opcode & Opcode::kLL_Mask ) >> (Opcode::kLL_Shift - 10)) | + (uint32_t(opcode & Opcode::kPP_VEXMask ) >> (Opcode::kPP_Shift - 8)) ; + + if (Support::test(options, InstOptions::kX86_Vex3)) { + x = (x & 0xFFFF) << 8; // [00000000|00000Lpp|000mmmmm|00000000]. + x ^= (kX86ByteVex3) | // [........|00000Lpp|000mmmmm|__VEX3__]. + (0x07u << 13) | // [........|00000Lpp|111mmmmm|__VEX3__]. + (0x0Fu << 19) | // [........|01111Lpp|111mmmmm|__VEX3__]. + (opcode << 24) ; // [_OPCODE_|01111Lpp|111mmmmm|__VEX3__]. writer.emit32uLE(x); goto EmitDone; @@ -4541,83 +4484,83 @@ EmitVexEvexOp: } } - // -------------------------------------------------------------------------- - // [Emit - VEX|EVEX - /r (Register)] - // -------------------------------------------------------------------------- + // Emit - VEX|EVEX - /r - Register + // ------------------------------- EmitVexEvexR: { // Construct `x` - a complete EVEX|VEX prefix. - uint32_t x = ((opReg << 4) & 0xF980u) | // [........|........|Vvvvv..R|R.......]. - ((rbReg << 2) & 0x0060u) | // [........|........|........|.BB.....]. - (opcode.extractLLMM(options)) | // [........|.LL.....|Vvvvv..R|RBBmmmmm]. - (_extraReg.id() << 16); // [........|.LL..aaa|Vvvvv..R|RBBmmmmm]. + uint32_t x = ((opReg << 4) & 0xF980u) | // [........|........|Vvvvv..R|R.......]. + ((rbReg << 2) & 0x0060u) | // [........|........|........|.BB.....]. + (opcode.extractLLMMMMM(options)) | // [........|.LL.....|Vvvvv..R|RBBmmmmm]. + (_extraReg.id() << 16); // [........|.LL..aaa|Vvvvv..R|RBBmmmmm]. opReg &= 0x7; // Handle AVX512 options by a single branch. - const uint32_t kAvx512Options = Inst::kOptionZMask | Inst::kOptionER | Inst::kOptionSAE; - if (options & kAvx512Options) { - uint32_t kBcstMask = 0x1 << 20; - uint32_t kLLMask10 = 0x2 << 21; - uint32_t kLLMask11 = 0x3 << 21; + const InstOptions kAvx512Options = InstOptions::kX86_ZMask | InstOptions::kX86_ER | InstOptions::kX86_SAE; + if (Support::test(options, kAvx512Options)) { + static constexpr uint32_t kBcstMask = 0x1 << 20; + static constexpr uint32_t kLLMask10 = 0x2 << 21; + static constexpr uint32_t kLLMask11 = 0x3 << 21; - // Designed to be easily encodable so the position must be exact. - // The {rz-sae} is encoded as {11}, so it should match the mask. - ASMJIT_ASSERT(Inst::kOptionRZ_SAE == kLLMask11); + // Designed to be easily encodable so the position must be exact. The {rz-sae} is encoded as {11}, + // so it should match the mask. + static_assert(uint32_t(InstOptions::kX86_RZ_SAE) == kLLMask11, + "This code requires InstOptions::X86_RZ_SAE to match kLLMask11 to work properly"); - x |= options & Inst::kOptionZMask; // [........|zLLb.aaa|Vvvvv..R|RBBmmmmm]. + x |= uint32_t(options & InstOptions::kX86_ZMask); // [........|zLLb.aaa|Vvvvv..R|RBBmmmmm]. // Support embedded-rounding {er} and suppress-all-exceptions {sae}. - if (options & (Inst::kOptionER | Inst::kOptionSAE)) { - // Embedded rounding is only encodable if the instruction is either - // scalar or it's a 512-bit operation as the {er} rounding predicate - // collides with LL part of the instruction. + if (Support::test(options, InstOptions::kX86_ER | InstOptions::kX86_SAE)) { + // Embedded rounding is only encodable if the instruction is either scalar or it's a 512-bit + // operation as the {er} rounding predicate collides with LL part of the instruction. if ((x & kLLMask11) != kLLMask10) { - // Ok, so LL is not 10, thus the instruction must be scalar. - // Scalar instructions don't support broadcast so if this - // instruction supports it {er} nor {sae} would be encodable. + // Ok, so LL is not 10, thus the instruction must be scalar. Scalar instructions don't + // support broadcast so if this instruction supports it {er} nor {sae} would be encodable. if (ASMJIT_UNLIKELY(commonInfo->hasAvx512B())) goto InvalidEROrSAE; } - if (options & Inst::kOptionER) { + if (Support::test(options, InstOptions::kX86_ER)) { if (ASMJIT_UNLIKELY(!commonInfo->hasAvx512ER())) goto InvalidEROrSAE; - x &=~kLLMask11; // [........|.00..aaa|Vvvvv..R|RBBmmmmm]. - x |= kBcstMask | (options & kLLMask11); // [........|.LLb.aaa|Vvvvv..R|RBBmmmmm]. + x &=~kLLMask11; // [........|.00..aaa|Vvvvv..R|RBBmmmmm]. + x |= kBcstMask | (uint32_t(options) & kLLMask11); // [........|.LLb.aaa|Vvvvv..R|RBBmmmmm]. } else { if (ASMJIT_UNLIKELY(!commonInfo->hasAvx512SAE())) goto InvalidEROrSAE; - x |= kBcstMask; // [........|.LLb.aaa|Vvvvv..R|RBBmmmmm]. + x &=~kLLMask11; // [........|.00..aaa|Vvvvv..R|RBBmmmmm]. + x |= kBcstMask; // [........|.00b.aaa|Vvvvv..R|RBBmmmmm]. } } } - // If these bits are used then EVEX prefix is required. - constexpr uint32_t kEvexBits = 0x00D78150u; // [........|xx.x.xxx|x......x|.x.x....]. + // These bits would force EVEX prefix. + constexpr uint32_t kEvexForce = 0x00000010u; // [........|........|........|...x....]. + constexpr uint32_t kEvexBits = 0x00D78150u; // [........|xx.x.xxx|x......x|.x.x....]. // Force EVEX prefix even in case the instruction has VEX encoding, because EVEX encoding is preferred. At the - // moment this is only required for AVX_VNNI instructions, which were added after AVX512_VNNI instructions. If - // such instruction doesn't specify prefix, EVEX (AVX512_VNNI) would be used by default, + // moment this is only required by AVX_VNNI instructions, which were added after AVX512_VNNI instructions. If + // such instruction doesn't specify prefix, EVEX (AVX512_VNNI) is selected by default. if (commonInfo->preferEvex()) { - if ((x & kEvexBits) == 0 && (options & (Inst::kOptionVex | Inst::kOptionVex3)) == 0) { - x |= (Opcode::kMM_ForceEvex) >> Opcode::kMM_Shift; + if ((x & kEvexBits) == 0 && !Support::test(options, InstOptions::kX86_Vex | InstOptions::kX86_Vex3)) { + x |= kEvexForce; } } - // Check if EVEX is required by checking bits in `x` : [........|xx.x.xxx|x......x|.x.x....]. + // Check if EVEX is required by checking bits in `x` : [........|xx.x.xxx|x......x|.x.x....]. if (x & kEvexBits) { - uint32_t y = ((x << 4) & 0x00080000u) | // [........|...bV...|........|........]. - ((x >> 4) & 0x00000010u) ; // [........|...bV...|........|...R....]. - x = (x & 0x00FF78E3u) | y; // [........|zLLbVaaa|0vvvv000|RBBR00mm]. - x = x << 8; // [zLLbVaaa|0vvvv000|RBBR00mm|00000000]. - x |= (opcode >> kVSHR_W ) & 0x00800000u; // [zLLbVaaa|Wvvvv000|RBBR00mm|00000000]. - x |= (opcode >> kVSHR_PP_EW) & 0x00830000u; // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000] (added PP and EVEX.W). - // _ ____ ____ - x ^= 0x087CF000u | kX86ByteEvex; // [zLLbVaaa|Wvvvv1pp|RBBR00mm|01100010]. + uint32_t y = ((x << 4) & 0x00080000u) | // [........|...bV...|........|........]. + ((x >> 4) & 0x00000010u) ; // [........|...bV...|........|...R....]. + x = (x & 0x00FF78EFu) | y; // [........|zLLbVaaa|0vvvv000|RBBRmmmm]. + x = x << 8; // [zLLbVaaa|0vvvv000|RBBRmmmm|00000000]. + x |= (opcode >> kVSHR_W ) & 0x00800000u; // [zLLbVaaa|Wvvvv000|RBBRmmmm|00000000]. + x |= (opcode >> kVSHR_PP_EW) & 0x00830000u; // [zLLbVaaa|Wvvvv0pp|RBBRmmmm|00000000] (added PP and EVEX.W). + // _ ____ ____ + x ^= 0x087CF000u | kX86ByteEvex; // [zLLbVaaa|Wvvvv1pp|RBBRmmmm|01100010]. writer.emit32uLE(x); writer.emit8(opcode.v); @@ -4628,19 +4571,20 @@ EmitVexEvexR: goto EmitDone; } - // Not EVEX, prepare `x` for VEX2 or VEX3: x = [........|00L00000|0vvvv000|R0B0mmmm]. - x |= ((opcode >> (kVSHR_W + 8)) & 0x8000u) | // [00000000|00L00000|Wvvvv000|R0B0mmmm]. - ((opcode >> (kVSHR_PP + 8)) & 0x0300u) | // [00000000|00L00000|0vvvv0pp|R0B0mmmm]. - ((x >> 11 ) & 0x0400u) ; // [00000000|00L00000|WvvvvLpp|R0B0mmmm]. + // Not EVEX, prepare `x` for VEX2 or VEX3: x = [........|00L00000|0vvvv000|R0Bmmmmm]. + x |= ((opcode >> (kVSHR_W + 8)) & 0x8000u) | // [00000000|00L00000|Wvvvv000|R0Bmmmmm]. + ((opcode >> (kVSHR_PP + 8)) & 0x0300u) | // [00000000|00L00000|0vvvv0pp|R0Bmmmmm]. + ((x >> 11 ) & 0x0400u) ; // [00000000|00L00000|WvvvvLpp|R0Bmmmmm]. + x |= x86GetForceEvex3MaskInLastBit(options); // [x0000000|00L00000|WvvvvLpp|R0Bmmmmm]. - // Check if VEX3 is required / forced: [........|........|x.......|..x..x..]. - if (x & 0x0008024u) { + // Check if VEX3 is required / forced: [x.......|........|x.......|..xxxxx.]. + if (x & 0x8000803Eu) { uint32_t xorMsk = x86VEXPrefix[x & 0xF] | (opcode << 24); - // Clear 'FORCE-VEX3' bit and all high bits. - x = (x & (0x4 ^ 0xFFFF)) << 8; // [00000000|WvvvvLpp|R0B0m0mm|00000000]. - // ____ _ _ - x ^= xorMsk; // [_OPCODE_|WvvvvLpp|R1Bmmmmm|VEX3|XOP]. + // Clear all high bits. + x = (x & 0xFFFF) << 8; // [00000000|WvvvvLpp|R0Bmmmmm|00000000]. + // ____ _ _ + x ^= xorMsk; // [_OPCODE_|WvvvvLpp|R1Bmmmmm|VEX3|XOP]. writer.emit32uLE(x); rbReg &= 0x7; @@ -4664,13 +4608,12 @@ EmitVexEvexR: } } - // -------------------------------------------------------------------------- - // [Emit - VEX|EVEX - /r (Memory)] - // -------------------------------------------------------------------------- + // Emit - VEX|EVEX - /r - Memory + // ----------------------------- EmitVexEvexM: ASMJIT_ASSERT(rmRel != nullptr); - ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem); + ASMJIT_ASSERT(rmRel->opType() == OperandType::kMem); rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()]; writer.emitSegmentOverride(rmRel->as<Mem>().segmentId()); @@ -4685,61 +4628,83 @@ EmitVexEvexM: uint32_t broadcastBit = uint32_t(rmRel->as<Mem>().hasBroadcast()); // Construct `x` - a complete EVEX|VEX prefix. - uint32_t x = ((opReg << 4) & 0x0000F980u) | // [........|........|Vvvvv..R|R.......]. - ((rxReg << 3) & 0x00000040u) | // [........|........|........|.X......]. - ((rxReg << 15) & 0x00080000u) | // [........|....X...|........|........]. - ((rbReg << 2) & 0x00000020u) | // [........|........|........|..B.....]. - opcode.extractLLMM(options) | // [........|.LL.X...|Vvvvv..R|RXBmmmmm]. - (_extraReg.id() << 16) | // [........|.LL.Xaaa|Vvvvv..R|RXBmmmmm]. - (broadcastBit << 20) ; // [........|.LLbXaaa|Vvvvv..R|RXBmmmmm]. + uint32_t x = ((opReg << 4) & 0x0000F980u) | // [........|........|Vvvvv..R|R.......]. + ((rxReg << 3) & 0x00000040u) | // [........|........|........|.X......]. + ((rxReg << 15) & 0x00080000u) | // [........|....X...|........|........]. + ((rbReg << 2) & 0x00000020u) | // [........|........|........|..B.....]. + opcode.extractLLMMMMM(options) | // [........|.LL.X...|Vvvvv..R|RXBmmmmm]. + (_extraReg.id() << 16) | // [........|.LL.Xaaa|Vvvvv..R|RXBmmmmm]. + (broadcastBit << 20) ; // [........|.LLbXaaa|Vvvvv..R|RXBmmmmm]. opReg &= 0x07u; - // Mark invalid VEX (force EVEX) case: // [@.......|.LLbXaaa|Vvvvv..R|RXBmmmmm]. - x |= (~commonInfo->flags() & InstDB::kFlagVex) << (31 - Support::constCtz(InstDB::kFlagVex)); + // Mark invalid VEX (force EVEX) case: // [@.......|.LLbXaaa|Vvvvv..R|RXBmmmmm]. + x |= uint32_t(~commonInfo->flags() & InstDB::InstFlags::kVex) << (31 - Support::ConstCTZ<uint32_t(InstDB::InstFlags::kVex)>::value); // Handle AVX512 options by a single branch. - const uint32_t kAvx512Options = Inst::kOptionZMask | - Inst::kOptionER | - Inst::kOptionSAE ; - if (options & kAvx512Options) { + const InstOptions kAvx512Options = InstOptions::kX86_ZMask | + InstOptions::kX86_ER | + InstOptions::kX86_SAE ; + if (Support::test(options, kAvx512Options)) { // {er} and {sae} are both invalid if memory operand is used. - if (ASMJIT_UNLIKELY(options & (Inst::kOptionER | Inst::kOptionSAE))) + if (ASMJIT_UNLIKELY(Support::test(options, InstOptions::kX86_ER | InstOptions::kX86_SAE))) goto InvalidEROrSAE; - x |= options & (Inst::kOptionZMask); // [@.......|zLLbXaaa|Vvvvv..R|RXBmmmmm]. + x |= uint32_t(options & InstOptions::kX86_ZMask); // [@.......|zLLbXaaa|Vvvvv..R|RXBmmmmm]. } // If these bits are used then EVEX prefix is required. - constexpr uint32_t kEvexBits = 0x80DF8110u; // [@.......|xx.xxxxx|x......x|...x....]. + constexpr uint32_t kEvexForce = 0x00000010u; // [........|........|........|...x....]. + constexpr uint32_t kEvexBits = 0x80DF8110u; // [@.......|xx.xxxxx|x......x|...x....]. // Force EVEX prefix even in case the instruction has VEX encoding, because EVEX encoding is preferred. At the // moment this is only required for AVX_VNNI instructions, which were added after AVX512_VNNI instructions. If // such instruction doesn't specify prefix, EVEX (AVX512_VNNI) would be used by default, if (commonInfo->preferEvex()) { - if ((x & kEvexBits) == 0 && (options & (Inst::kOptionVex | Inst::kOptionVex3)) == 0) { - x |= (Opcode::kMM_ForceEvex) >> Opcode::kMM_Shift; + if ((x & kEvexBits) == 0 && !Support::test(options, InstOptions::kX86_Vex | InstOptions::kX86_Vex3)) { + x |= kEvexForce; } } - // Check if EVEX is required by checking bits in `x` : [@.......|xx.xxxxx|x......x|...x....]. + // Check if EVEX is required by checking bits in `x` : [@.......|xx.xxxxx|x......x|...x....]. if (x & kEvexBits) { - uint32_t y = ((x << 4) & 0x00080000u) | // [@.......|....V...|........|........]. - ((x >> 4) & 0x00000010u) ; // [@.......|....V...|........|...R....]. - x = (x & 0x00FF78E3u) | y; // [........|zLLbVaaa|0vvvv000|RXBR00mm]. - x = x << 8; // [zLLbVaaa|0vvvv000|RBBR00mm|00000000]. - x |= (opcode >> kVSHR_W ) & 0x00800000u; // [zLLbVaaa|Wvvvv000|RBBR00mm|00000000]. - x |= (opcode >> kVSHR_PP_EW) & 0x00830000u; // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000] (added PP and EVEX.W). - // _ ____ ____ - x ^= 0x087CF000u | kX86ByteEvex; // [zLLbVaaa|Wvvvv1pp|RBBR00mm|01100010]. - - writer.emit32uLE(x); - writer.emit8(opcode.v); + uint32_t y = ((x << 4) & 0x00080000u) | // [@.......|....V...|........|........]. + ((x >> 4) & 0x00000010u) ; // [@.......|....V...|........|...R....]. + x = (x & 0x00FF78EFu) | y; // [........|zLLbVaaa|0vvvv000|RXBRmmmm]. + x = x << 8; // [zLLbVaaa|0vvvv000|RBBRmmmm|00000000]. + x |= (opcode >> kVSHR_W ) & 0x00800000u; // [zLLbVaaa|Wvvvv000|RBBRmmmm|00000000]. + x |= (opcode >> kVSHR_PP_EW) & 0x00830000u; // [zLLbVaaa|Wvvvv0pp|RBBRmmmm|00000000] (added PP and EVEX.W). + // _ ____ ____ + x ^= 0x087CF000u | kX86ByteEvex; // [zLLbVaaa|Wvvvv1pp|RBBRmmmm|01100010]. if (x & 0x10000000u) { - // Broadcast, change the compressed displacement scale to either x4 (SHL 2) or x8 (SHL 3) - // depending on instruction's W. If 'W' is 1 'SHL' must be 3, otherwise it must be 2. + // Broadcast support. + // + // 1. Verify our LL field is correct as broadcast changes the "size" of the source operand. For example if + // a broadcasted operand is qword_ptr[X] {1to8} the source size becomes 64 and not 8 as the memory operand + // would report. + // + // 2. Change the compressed displacement scale to either x2 (SHL1), x4 (SHL 2), or x8 (SHL 3) depending on + // the broadcast unit/element size. + uint32_t broadcastUnitSize = commonInfo->broadcastSize(); + uint32_t broadcastVectorSize = broadcastUnitSize << uint32_t(rmRel->as<Mem>().getBroadcast()); + + if (ASMJIT_UNLIKELY(broadcastUnitSize == 0)) + goto InvalidBroadcast; + + // LL was already shifted 8 bits right. + constexpr uint32_t kLLShift = 21 + 8; + + uint32_t currentLL = x & (0x3u << kLLShift); + uint32_t broadcastLL = (Support::max<uint32_t>(Support::ctz(broadcastVectorSize), 4) - 4) << kLLShift; + + if (broadcastLL > (2u << kLLShift)) + goto InvalidBroadcast; + + uint32_t newLL = Support::max(currentLL, broadcastLL); + x = (x & ~(uint32_t(0x3) << kLLShift)) | newLL; + opcode &=~uint32_t(Opcode::kCDSHL_Mask); - opcode |= ((x & 0x00800000u) ? 3u : 2u) << Opcode::kCDSHL_Shift; + opcode |= Support::ctz(broadcastUnitSize) << Opcode::kCDSHL_Shift; } else { // Add the compressed displacement 'SHF' to the opcode based on 'TTWLL'. @@ -4749,24 +4714,28 @@ EmitVexEvexM: ((x >> 29) & 0x3); opcode += x86CDisp8SHL[TTWLL]; } + + writer.emit32uLE(x); + writer.emit8(opcode.v); } else { - // Not EVEX, prepare `x` for VEX2 or VEX3: x = [........|00L00000|0vvvv000|RXB0mmmm]. - x |= ((opcode >> (kVSHR_W + 8)) & 0x8000u) | // [00000000|00L00000|Wvvvv000|RXB0mmmm]. - ((opcode >> (kVSHR_PP + 8)) & 0x0300u) | // [00000000|00L00000|Wvvvv0pp|RXB0mmmm]. - ((x >> 11 ) & 0x0400u) ; // [00000000|00L00000|WvvvvLpp|RXB0mmmm]. + // Not EVEX, prepare `x` for VEX2 or VEX3: x = [........|00L00000|0vvvv000|RXBmmmmm]. + x |= ((opcode >> (kVSHR_W + 8)) & 0x8000u) | // [00000000|00L00000|Wvvvv000|RXBmmmmm]. + ((opcode >> (kVSHR_PP + 8)) & 0x0300u) | // [00000000|00L00000|Wvvvv0pp|RXBmmmmm]. + ((x >> 11 ) & 0x0400u) ; // [00000000|00L00000|WvvvvLpp|RXBmmmmm]. + x |= x86GetForceEvex3MaskInLastBit(options); // [x0000000|00L00000|WvvvvLpp|RXBmmmmm]. // Clear a possible CDisp specified by EVEX. opcode &= ~Opcode::kCDSHL_Mask; - // Check if VEX3 is required / forced: [........|........|x.......|.xx..x..]. - if (x & 0x0008064u) { + // Check if VEX3 is required / forced: [x.......|........|x.......|.xxxxxx.]. + if (x & 0x8000807Eu) { uint32_t xorMsk = x86VEXPrefix[x & 0xF] | (opcode << 24); - // Clear 'FORCE-VEX3' bit and all high bits. - x = (x & (0x4 ^ 0xFFFF)) << 8; // [00000000|WvvvvLpp|RXB0m0mm|00000000]. - // ____ ___ - x ^= xorMsk; // [_OPCODE_|WvvvvLpp|RXBmmmmm|VEX3_XOP]. + // Clear all high bits. + x = (x & 0xFFFF) << 8; // [00000000|WvvvvLpp|RXBmmmmm|00000000]. + // ____ ___ + x ^= xorMsk; // [_OPCODE_|WvvvvLpp|RXBmmmmm|VEX3_XOP]. writer.emit32uLE(x); } else { @@ -4782,7 +4751,7 @@ EmitVexEvexM: } // MOD|SIB address. - if (!commonInfo->hasFlag(InstDB::kFlagVsib)) + if (!commonInfo->hasFlag(InstDB::InstFlags::kVsib)) goto EmitModSib; // MOD|VSIB address without INDEX is invalid. @@ -4790,9 +4759,8 @@ EmitVexEvexM: goto EmitModVSib; goto InvalidInstruction; - // -------------------------------------------------------------------------- - // [Emit - Jmp/Jcc/Call] - // -------------------------------------------------------------------------- + // Emit - Jmp/Jcc/Call + // ------------------- EmitJmpCall: { @@ -4832,7 +4800,7 @@ EmitJmpCall: } else { // Non-bound label or label bound to a different section. - if (opCode8 && (!opcode.v || (options & Inst::kOptionShortForm))) { + if (opCode8 && (!opcode.v || Support::test(options, InstOptions::kShortForm))) { writer.emit8(opCode8); // Record DISP8 (non-bound label). @@ -4842,7 +4810,7 @@ EmitJmpCall: } else { // Refuse also 'short' prefix, if specified. - if (ASMJIT_UNLIKELY(!opcode.v || (options & Inst::kOptionShortForm) != 0)) + if (ASMJIT_UNLIKELY(!opcode.v || Support::test(options, InstOptions::kShortForm))) goto InvalidDisplacement; writer.emit8If(0x0F, (opcode & Opcode::kMM_Mask) != 0);// Emit 0F prefix. @@ -4861,9 +4829,8 @@ EmitJmpCall: uint64_t baseAddress = code()->baseAddress(); uint64_t jumpAddress = rmRel->as<Imm>().valueAs<uint64_t>(); - // If the base-address is known calculate a relative displacement and - // check if it fits in 32 bits (which is always true in 32-bit mode). - // Emit relative displacement as it was a bound label if all checks are ok. + // If the base-address is known calculate a relative displacement and check if it fits in 32 bits (which is + // always true in 32-bit mode). Emit relative displacement as it was a bound label if all checks are ok. if (baseAddress != Globals::kNoBaseAddress) { uint64_t rel64 = jumpAddress - (ip + baseAddress) - inst32Size; if (Environment::is32Bit(arch()) || Support::isInt32(int64_t(rel64))) { @@ -4871,14 +4838,14 @@ EmitJmpCall: goto EmitJmpCallRel; } else { - // Relative displacement exceeds 32-bits - relocator can only - // insert trampoline for jmp/call, but not for jcc/jecxz. + // Relative displacement exceeds 32-bits - relocator can only insert trampoline for jmp/call, but not + // for jcc/jecxz. if (ASMJIT_UNLIKELY(!x86IsJmpOrCall(instId))) goto InvalidDisplacement; } } - err = _code->newRelocEntry(&re, RelocEntry::kTypeAbsToRel); + err = _code->newRelocEntry(&re, RelocType::kAbsToRel); if (ASMJIT_UNLIKELY(err)) goto Failed; @@ -4887,10 +4854,9 @@ EmitJmpCall: re->_payload = jumpAddress; if (ASMJIT_LIKELY(opcode.v)) { - // 64-bit: Emit REX prefix so the instruction can be patched later. - // REX prefix does nothing if not patched, but allows to patch the - // instruction to use MOD/M and to point to a memory where the final - // 64-bit address is stored. + // 64-bit: Emit REX prefix so the instruction can be patched later. REX prefix does nothing if not patched, + // but allows to patch the instruction to use MOD/M and to point to a memory where the final 64-bit address + // is stored. if (Environment::is64Bit(arch()) && x86IsJmpOrCall(instId)) { if (!rex) writer.emit8(kX86ByteRex); @@ -4899,7 +4865,7 @@ EmitJmpCall: if (ASMJIT_UNLIKELY(err)) goto Failed; - re->_relocType = RelocEntry::kTypeX64AddressEntry; + re->_relocType = RelocType::kX64AddressEntry; } writer.emit8If(0x0F, (opcode & Opcode::kMM_Mask) != 0); // Emit 0F prefix. @@ -4921,21 +4887,20 @@ EmitJmpCall: // Not Label|Imm -> Invalid. goto InvalidInstruction; - // Emit jmp/call with relative displacement known at assembly-time. Decide - // between 8-bit and 32-bit displacement encoding. Some instructions only - // allow either 8-bit or 32-bit encoding, others allow both encodings. + // Emit jmp/call with relative displacement known at assembly-time. Decide between 8-bit and 32-bit displacement + // encoding. Some instructions only allow either 8-bit or 32-bit encoding, others allow both encodings. EmitJmpCallRel: - if (Support::isInt8(int32_t(rel32 + inst32Size - inst8Size)) && opCode8 && !(options & Inst::kOptionLongForm)) { - options |= Inst::kOptionShortForm; + if (Support::isInt8(int32_t(rel32 + inst32Size - inst8Size)) && opCode8 && !Support::test(options, InstOptions::kLongForm)) { + options |= InstOptions::kShortForm; writer.emit8(opCode8); // Emit opcode writer.emit8(rel32 + inst32Size - inst8Size); // Emit DISP8. goto EmitDone; } else { - if (ASMJIT_UNLIKELY(!opcode.v || (options & Inst::kOptionShortForm) != 0)) + if (ASMJIT_UNLIKELY(!opcode.v || Support::test(options, InstOptions::kShortForm))) goto InvalidDisplacement; - options &= ~Inst::kOptionShortForm; + options &= ~InstOptions::kShortForm; writer.emit8If(0x0F, (opcode & Opcode::kMM_Mask) != 0); // Emit 0x0F prefix. writer.emit8(opcode.v); // Emit Opcode. writer.emit8If(x86EncodeMod(3, opReg, 0), opReg != 0); // Emit MOD. @@ -4944,9 +4909,8 @@ EmitJmpCallRel: } } - // -------------------------------------------------------------------------- - // [Emit - Relative] - // -------------------------------------------------------------------------- + // Emit - Relative + // --------------- EmitRel: { @@ -4969,12 +4933,11 @@ EmitRel: } writer.emitImmediate(uint64_t(immValue), immSize); - // -------------------------------------------------------------------------- - // [Done] - // -------------------------------------------------------------------------- + // Emit - Done + // ----------- EmitDone: - if (ASMJIT_UNLIKELY(options & Inst::kOptionReserved)) { + if (Support::test(options, InstOptions::kReserved)) { #ifndef ASMJIT_NO_LOGGING if (_logger) EmitterUtils::logInstructionEmitted(this, instId, options, o0, o1, o2, opExt, relSize, immSize, writer.cursor()); @@ -4988,9 +4951,8 @@ EmitDone: writer.done(this); return kErrorOk; - // -------------------------------------------------------------------------- - // [Error Handler] - // -------------------------------------------------------------------------- + // Error Handler + // ------------- #define ERROR_HANDLER(ERR) ERR: err = DebugUtils::errored(kError##ERR); goto Failed; ERROR_HANDLER(OutOfMemory) @@ -5009,6 +4971,7 @@ EmitDone: ERROR_HANDLER(InvalidPhysId) ERROR_HANDLER(InvalidSegment) ERROR_HANDLER(InvalidImmediate) + ERROR_HANDLER(InvalidBroadcast) ERROR_HANDLER(OperandSizeMismatch) ERROR_HANDLER(AmbiguousOperandSize) ERROR_HANDLER(NotConsecutiveRegs) @@ -5025,15 +4988,14 @@ Failed: #endif } -// ============================================================================ -// [asmjit::x86::Assembler - Align] -// ============================================================================ +//x86::Assembler - Align +// ===================== -Error Assembler::align(uint32_t alignMode, uint32_t alignment) { +Error Assembler::align(AlignMode alignMode, uint32_t alignment) { if (ASMJIT_UNLIKELY(!_code)) return reportError(DebugUtils::errored(kErrorNotInitialized)); - if (ASMJIT_UNLIKELY(alignMode >= kAlignCount)) + if (ASMJIT_UNLIKELY(uint32_t(alignMode) > uint32_t(AlignMode::kMaxValue))) return reportError(DebugUtils::errored(kErrorInvalidArgument)); if (alignment <= 1) @@ -5049,8 +5011,8 @@ Error Assembler::align(uint32_t alignMode, uint32_t alignment) { uint8_t pattern = 0x00; switch (alignMode) { - case kAlignCode: { - if (hasEncodingOption(kEncodingOptionOptimizedAlign)) { + case AlignMode::kCode: { + if (hasEncodingOption(EncodingOptions::kOptimizedAlign)) { // Intel 64 and IA-32 Architectures Software Developer's Manual - Volume 2B (NOP). enum { kMaxNopSize = 9 }; @@ -5081,11 +5043,11 @@ Error Assembler::align(uint32_t alignMode, uint32_t alignment) { break; } - case kAlignData: + case AlignMode::kData: pattern = 0xCC; break; - case kAlignZero: + case AlignMode::kZero: // Pattern already set to zero. break; } @@ -5101,7 +5063,7 @@ Error Assembler::align(uint32_t alignMode, uint32_t alignment) { #ifndef ASMJIT_NO_LOGGING if (_logger) { StringTmp<128> sb; - sb.appendChars(' ', _logger->indentation(FormatOptions::kIndentationCode)); + sb.appendChars(' ', _logger->indentation(FormatIndentationGroup::kCode)); sb.appendFormat("align %u\n", alignment); _logger->log(sb); } @@ -5110,12 +5072,11 @@ Error Assembler::align(uint32_t alignMode, uint32_t alignment) { return kErrorOk; } -// ============================================================================ -// [asmjit::x86::Assembler - Events] -// ============================================================================ +// x86::Assembler - Events +// ======================= Error Assembler::onAttach(CodeHolder* code) noexcept { - uint32_t arch = code->arch(); + Arch arch = code->arch(); if (!Environment::isFamilyX86(arch)) return DebugUtils::errored(kErrorInvalidArch); @@ -5123,12 +5084,12 @@ Error Assembler::onAttach(CodeHolder* code) noexcept { if (Environment::is32Bit(arch)) { // 32 bit architecture - X86. - _forcedInstOptions |= Inst::_kOptionInvalidRex; + _forcedInstOptions |= InstOptions::kX86_InvalidRex; _setAddressOverrideMask(kX86MemInfo_67H_X86); } else { // 64 bit architecture - X64. - _forcedInstOptions &= ~Inst::_kOptionInvalidRex; + _forcedInstOptions &= ~InstOptions::kX86_InvalidRex; _setAddressOverrideMask(kX86MemInfo_67H_X64); } @@ -5136,7 +5097,7 @@ Error Assembler::onAttach(CodeHolder* code) noexcept { } Error Assembler::onDetach(CodeHolder* code) noexcept { - _forcedInstOptions &= ~Inst::_kOptionInvalidRex; + _forcedInstOptions &= ~InstOptions::kX86_InvalidRex; _setAddressOverrideMask(0); return Base::onDetach(code); diff --git a/src/asmjit/x86/x86assembler.h b/src/asmjit/x86/x86assembler.h index 8cd1014..dbffae6 100644 --- a/src/asmjit/x86/x86assembler.h +++ b/src/asmjit/x86/x86assembler.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86ASSEMBLER_H_INCLUDED #define ASMJIT_X86_X86ASSEMBLER_H_INCLUDED @@ -33,21 +15,15 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::Assembler] -// ============================================================================ - //! X86/X64 assembler implementation. //! -//! x86::Assembler is a code emitter that emits machine code directly into the -//! \ref CodeBuffer. The assembler is capable of targeting both 32-bit and 64-bit -//! instruction sets, the instruction set can be configured through \ref CodeHolder. +//! x86::Assembler is a code emitter that emits machine code directly into the \ref CodeBuffer. The assembler is capable +//! of targeting both 32-bit and 64-bit instruction sets, the instruction set can be configured through \ref CodeHolder. //! //! ### Basics //! -//! The following example shows a basic use of `x86::Assembler`, how to generate -//! a function that works in both 32-bit and 64-bit modes, and how to connect -//! \ref JitRuntime, \ref CodeHolder, and `x86::Assembler`. +//! The following example shows a basic use of `x86::Assembler`, how to generate a function that works in both 32-bit +//! and 64-bit modes, and how to connect \ref JitRuntime, \ref CodeHolder, and `x86::Assembler`. //! //! ``` //! #include <asmjit/x86.h> @@ -122,32 +98,26 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! The example should be self-explanatory. It shows how to work with labels, -//! how to use operands, and how to emit instructions that can use different -//! registers based on runtime selection. It implements 32-bit CDECL, WIN64, +//! The example should be self-explanatory. It shows how to work with labels, how to use operands, and how to emit +//! instructions that can use different registers based on runtime selection. It implements 32-bit CDECL, WIN64, //! and SysV64 caling conventions and will work on most X86/X64 environments. //! -//! Although functions prologs / epilogs can be implemented manually, AsmJit -//! provides utilities that can be used to create function prologs and epilogs -//! automatically, see \ref asmjit_function for more details. +//! Although functions prologs / epilogs can be implemented manually, AsmJit provides utilities that can be used +//! to create function prologs and epilogs automatically, see \ref asmjit_function for more details. //! //! ### Instruction Validation //! -//! Assembler prefers speed over strictness by default. The implementation checks -//! the type of operands and fails if the signature of types is invalid, however, -//! it does only basic checks regarding registers and their groups used in -//! instructions. It's possible to pass operands that don't form any valid -//! signature to the implementation and succeed. This is usually not a problem -//! as Assembler provides typed API so operand types are normally checked by C++ -//! compiler at compile time, however, Assembler is fully dynamic and its \ref -//! emit() function can be called with any instruction id, options, and operands. -//! Moreover, it's also possible to form instructions that will be accepted by -//! the typed API, for example by calling `mov(x86::eax, x86::al)` - the C++ -//! compiler won't see a problem as both EAX and AL are \ref Gp registers. -//! -//! To help with common mistakes AsmJit allows to activate instruction validation. -//! This feature instruments the Assembler to call \ref InstAPI::validate() before -//! it attempts to encode any instruction. +//! Assembler prefers speed over strictness by default. The implementation checks the type of operands and fails +//! if the signature of types is invalid, however, it does only basic checks regarding registers and their groups +//! used in instructions. It's possible to pass operands that don't form any valid signature to the implementation +//! and succeed. This is usually not a problem as Assembler provides typed API so operand types are normally checked +//! by C++ compiler at compile time, however, Assembler is fully dynamic and its \ref emit() function can be called +//! with any instruction id, options, and operands. Moreover, it's also possible to form instructions that will be +//! accepted by the typed API, for example by calling `mov(x86::eax, x86::al)` - the C++ compiler won't see a problem +//! as both EAX and AL are \ref Gp registers. +//! +//! To help with common mistakes AsmJit allows to activate instruction validation. This feature instruments +//! the Assembler to call \ref InstAPI::validate() before it attempts to encode any instruction. //! //! The example below illustrates how validation can be turned on: //! @@ -165,7 +135,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! x86::Assembler a(&code); // Create and attach x86::Assembler to code. //! //! // Enable strict validation. -//! a.addValidationOptions(BaseEmitter::kValidationOptionAssembler); +//! a.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); //! //! // Try to encode invalid or ill-formed instructions. //! Error err; @@ -188,11 +158,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Native Registers //! -//! All emitters provide functions to construct machine-size registers depending -//! on the target. This feature is for users that want to write code targeting -//! both 32-bit and 64-bit architectures at the same time. In AsmJit terminology -//! such registers have prefix `z`, so for example on X86 architecture the -//! following native registers are provided: +//! All emitters provide functions to construct machine-size registers depending on the target. This feature is +//! for users that want to write code targeting both 32-bit and 64-bit architectures at the same time. In AsmJit +//! terminology such registers have prefix `z`, so for example on X86 architecture the following native registers +//! are provided: //! //! - `zax` - mapped to either `eax` or `rax` //! - `zbx` - mapped to either `ebx` or `rbx` @@ -203,8 +172,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! - `zsi` - mapped to either `esi` or `rsi` //! - `zdi` - mapped to either `edi` or `rdi` //! -//! They are accessible through \ref x86::Assembler, \ref x86::Builder, and -//! \ref x86::Compiler. The example below illustrates how to use this feature: +//! They are accessible through \ref x86::Assembler, \ref x86::Builder, and \ref x86::Compiler. The example below +//! illustrates how to use this feature: //! //! ``` //! #include <asmjit/x86.h> @@ -253,11 +222,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! The example just returns `0`, but the function generated contains a standard -//! prolog and epilog sequence and the function itself reserves 32 bytes of local -//! stack. The advantage is clear - a single code-base can handle multiple targets -//! easily. If you want to create a register of native size dynamically by -//! specifying its id it's also possible: +//! The example just returns `0`, but the function generated contains a standard prolog and epilog sequence and the +//! function itself reserves 32 bytes of local stack. The advantage is clear - a single code-base can handle multiple +//! targets easily. If you want to create a register of native size dynamically by specifying its id it's also possible: //! //! ``` //! void example(x86::Assembler& a) { @@ -274,14 +241,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Data Embedding //! -//! x86::Assembler extends the standard \ref BaseAssembler with X86/X64 specific -//! conventions that are often used by assemblers to embed data next to the code. -//! The following functions can be used to embed data: -//! -//! - \ref x86::Assembler::db() - embeds byte (8 bits) (x86 naming). -//! - \ref x86::Assembler::dw() - embeds word (16 bits) (x86 naming). -//! - \ref x86::Assembler::dd() - embeds dword (32 bits) (x86 naming). -//! - \ref x86::Assembler::dq() - embeds qword (64 bits) (x86 naming). +//! x86::Assembler extends the standard \ref BaseAssembler with X86/X64 specific conventions that are often used by +//! assemblers to embed data next to the code. The following functions can be used to embed data: //! //! - \ref BaseAssembler::embedInt8() - embeds int8_t (portable naming). //! - \ref BaseAssembler::embedUInt8() - embeds uint8_t (portable naming). @@ -294,6 +255,11 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! - \ref BaseAssembler::embedFloat() - embeds float (portable naming). //! - \ref BaseAssembler::embedDouble() - embeds double (portable naming). //! +//! - \ref x86::Assembler::db() - embeds byte (8 bits) (x86 naming). +//! - \ref x86::Assembler::dw() - embeds word (16 bits) (x86 naming). +//! - \ref x86::Assembler::dd() - embeds dword (32 bits) (x86 naming). +//! - \ref x86::Assembler::dq() - embeds qword (64 bits) (x86 naming). +//! //! The following example illustrates how embed works: //! //! ``` @@ -308,8 +274,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! Sometimes it's required to read the data that is embedded after code, for -//! example. This can be done through \ref Label as shown below: +//! Sometimes it's required to read the data that is embedded after code, for example. This can be done through +//! \ref Label as shown below: //! //! ``` //! #include <asmjit/x86.h> @@ -335,17 +301,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Label Embedding //! -//! It's also possible to embed labels. In general AsmJit provides the following -//! options: +//! It's also possible to embed labels. In general AsmJit provides the following options: //! -//! - \ref BaseEmitter::embedLabel() - Embeds absolute address of a label. -//! This is target dependent and would embed either 32-bit or 64-bit data -//! that embeds absolute label address. This kind of embedding cannot be +//! - \ref BaseEmitter::embedLabel() - Embeds absolute address of a label. This is target dependent and would +//! embed either 32-bit or 64-bit data that embeds absolute label address. This kind of embedding cannot be //! used in a position independent code. //! -//! - \ref BaseEmitter::embedLabelDelta() - Embeds a difference between two -//! labels. The size of the difference can be specified so it's possible to -//! embed 8-bit, 16-bit, 32-bit, and 64-bit difference, which is sufficient +//! - \ref BaseEmitter::embedLabelDelta() - Embeds a difference between two labels. The size of the difference +//! can be specified so it's possible to embed 8-bit, 16-bit, 32-bit, and 64-bit difference, which is sufficient //! for most purposes. //! //! The following example demonstrates how to embed labels and their differences: @@ -368,9 +331,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Using FuncFrame and FuncDetail with x86::Assembler //! -//! The example below demonstrates how \ref FuncFrame and \ref FuncDetail can be -//! used together with \ref x86::Assembler to generate a function that will use -//! platform dependent calling conventions automatically depending on the target: +//! The example below demonstrates how \ref FuncFrame and \ref FuncDetail can be used together with \ref x86::Assembler +//! to generate a function that will use platform dependent calling conventions automatically depending on the target: //! //! ``` //! #include <asmjit/x86.h> @@ -399,13 +361,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! // Create/initialize FuncDetail and FuncFrame. //! FuncDetail func; -//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost)); +//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost)); //! //! FuncFrame frame; //! frame.init(func); //! -//! // Make XMM0 and XMM1 dirty - kGroupVec describes XMM|YMM|ZMM registers. -//! frame.setDirtyRegs(x86::Reg::kGroupVec, IntUtils::mask(0, 1)); +//! // Make XMM0 and XMM1 dirty - RegGroup::kVec describes XMM|YMM|ZMM registers. +//! frame.setDirtyRegs(RegGroup::kVec, IntUtils::mask(0, 1)); //! //! // Alternatively, if you don't want to use register masks you can pass BaseReg //! // to addDirtyRegs(). The following code would add both xmm0 and xmm1. @@ -444,50 +406,40 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Using x86::Assembler as Code-Patcher //! -//! This is an advanced topic that is sometimes unavoidable. AsmJit by default -//! appends machine code it generates into a \ref CodeBuffer, however, it also -//! allows to set the offset in \ref CodeBuffer explicitly and to overwrite its -//! content. This technique is extremely dangerous as X86 instructions have -//! variable length (see below), so you should in general only patch code to -//! change instruction's immediate values or some other details not known the -//! at a time the instruction was emitted. A typical scenario that requires -//! code-patching is when you start emitting function and you don't know how -//! much stack you want to reserve for it. -//! -//! Before we go further it's important to introduce instruction options, because -//! they can help with code-patching (and not only patching, but that will be -//! explained in AVX-512 section): -//! -//! - Many general-purpose instructions (especially arithmetic ones) on X86 -//! have multiple encodings - in AsmJit this is usually called 'short form' -//! and 'long form'. -//! - AsmJit always tries to use 'short form' as it makes the resulting -//! machine-code smaller, which is always good - this decision is used -//! by majority of assemblers out there. -//! - AsmJit allows to override the default decision by using `short_()` -//! and `long_()` instruction options to force short or long form, -//! respectively. The most useful is `long_()` as it basically forces -//! AsmJit to always emit the longest form. The `short_()` is not that -//! useful as it's automatic (except jumps to non-bound labels). Note that -//! the underscore after each function name avoids collision with built-in -//! C++ types. -//! -//! To illustrate what short form and long form means in binary let's assume -//! we want to emit "add esp, 16" instruction, which has two possible binary -//! encodings: -//! -//! - `83C410` - This is a short form aka `short add esp, 16` - You can see -//! opcode byte (0x8C), MOD/RM byte (0xC4) and an 8-bit immediate value -//! representing `16`. -//! - `81C410000000` - This is a long form aka `long add esp, 16` - You can -//! see a different opcode byte (0x81), the same Mod/RM byte (0xC4) and a -//! 32-bit immediate in little-endian representing `16`. -//! -//! It should be obvious that patching an existing instruction into an instruction -//! having a different size may create various problems. So it's recommended to be -//! careful and to only patch instructions into instructions having the same size. -//! The example below demonstrates how instruction options can be used to guarantee -//! the size of an instruction by forcing the assembler to use long-form encoding: +//! This is an advanced topic that is sometimes unavoidable. AsmJit by default appends machine code it generates +//! into a \ref CodeBuffer, however, it also allows to set the offset in \ref CodeBuffer explicitly and to overwrite +//! its content. This technique is extremely dangerous as X86 instructions have variable length (see below), so you +//! should in general only patch code to change instruction's immediate values or some other details not known the +//! at a time the instruction was emitted. A typical scenario that requires code-patching is when you start emitting +//! function and you don't know how much stack you want to reserve for it. +//! +//! Before we go further it's important to introduce instruction options, because they can help with code-patching +//! (and not only patching, but that will be explained in AVX-512 section): +//! +//! - Many general-purpose instructions (especially arithmetic ones) on X86 have multiple encodings - in AsmJit +//! this is usually called 'short form' and 'long form'. +//! +//! - AsmJit always tries to use 'short form' as it makes the resulting machine-code smaller, which is always +//! good - this decision is used by majority of assemblers out there. +//! +//! - AsmJit allows to override the default decision by using `short_()` and `long_()` instruction options to force +//! short or long form, respectively. The most useful is `long_()` as it basically forces AsmJit to always emit +//! the longest form. The `short_()` is not that useful as it's automatic (except jumps to non-bound labels). Note +//! that the underscore after each function name avoids collision with built-in C++ types. +//! +//! To illustrate what short form and long form means in binary let's assume we want to emit "add esp, 16" instruction, +//! which has two possible binary encodings: +//! +//! - `83C410` - This is a short form aka `short add esp, 16` - You can see opcode byte (0x8C), MOD/RM byte (0xC4) +//! and an 8-bit immediate value representing `16`. +//! +//! - `81C410000000` - This is a long form aka `long add esp, 16` - You can see a different opcode byte (0x81), the +//! same Mod/RM byte (0xC4) and a 32-bit immediate in little-endian representing `16`. +//! +//! It should be obvious that patching an existing instruction into an instruction having a different size may create +//! various problems. So it's recommended to be careful and to only patch instructions into instructions having the +//! same size. The example below demonstrates how instruction options can be used to guarantee the size of an +//! instruction by forcing the assembler to use long-form encoding: //! //! ``` //! #include <asmjit/x86.h> @@ -546,27 +498,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! If you run the example it will just work, because both instructions have -//! the same size. As an experiment you can try removing `long_()` form to -//! see what happens when wrong code is generated. +//! If you run the example it will just work, because both instructions have the same size. As an experiment you can +//! try removing `long_()` form to see what happens when wrong code is generated. //! //! ### Code Patching and REX Prefix //! -//! In 64-bit mode there is one more thing to worry about when patching code: -//! REX prefix. It's a single byte prefix designed to address registers with -//! ids from 9 to 15 and to override the default width of operation from 32 -//! to 64 bits. AsmJit, like other assemblers, only emits REX prefix when it's -//! necessary. If the patched code only changes the immediate value as shown -//! in the previous example then there is nothing to worry about as it doesn't -//! change the logic behind emitting REX prefix, however, if the patched code -//! changes register id or overrides the operation width then it's important -//! to take care of REX prefix as well. -//! -//! AsmJit contains another instruction option that controls (forces) REX -//! prefix - `rex()`. If you use it the instruction emitted will always use -//! REX prefix even when it's encodable without it. The following list contains -//! some instructions and their binary representations to illustrate when it's -//! emitted: +//! In 64-bit mode there is one more thing to worry about when patching code: REX prefix. It's a single byte prefix +//! designed to address registers with ids from 9 to 15 and to override the default width of operation from 32 to 64 +//! bits. AsmJit, like other assemblers, only emits REX prefix when it's necessary. If the patched code only changes +//! the immediate value as shown in the previous example then there is nothing to worry about as it doesn't change +//! the logic behind emitting REX prefix, however, if the patched code changes register id or overrides the operation +//! width then it's important to take care of REX prefix as well. +//! +//! AsmJit contains another instruction option that controls (forces) REX prefix - `rex()`. If you use it the +//! instruction emitted will always use REX prefix even when it's encodable without it. The following list contains +//! some instructions and their binary representations to illustrate when it's emitted: //! //! - `__83C410` - `add esp, 16` - 32-bit operation in 64-bit mode doesn't require REX prefix. //! - `4083C410` - `rex add esp, 16` - 32-bit operation in 64-bit mode with forced REX prefix (0x40). @@ -619,18 +565,15 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! It's important to understand that prefixes are part of instruction options. -//! When a member function that involves adding a prefix is called the prefix -//! is combined with existing instruction options, which will affect the next +//! It's important to understand that prefixes are part of instruction options. When a member function that involves +//! adding a prefix is called the prefix is combined with existing instruction options, which will affect the next //! instruction generated. //! //! ### Generating AVX512 code. //! -//! x86::Assembler can generate AVX512+ code including the use of opmask -//! registers. Opmask can be specified through \ref x86::Assembler::k() -//! function, which stores it as an extra register, which will be used -//! by the next instruction. AsmJit uses such concept for manipulating -//! instruction options as well. +//! x86::Assembler can generate AVX512+ code including the use of opmask registers. Opmask can be specified through +//! \ref x86::Assembler::k() function, which stores it as an extra register, which will be used by the next +//! instruction. AsmJit uses such concept for manipulating instruction options as well. //! //! The following AVX512 features are supported: //! @@ -702,9 +645,8 @@ public: //! \name Internal //! \{ - // NOTE: x86::Assembler uses _privateData to store 'address-override' bit that - // is used to decide whether to emit address-override (67H) prefix based on - // the memory BASE+INDEX registers. It's either `kX86MemInfo_67H_X86` or + // NOTE: x86::Assembler uses _privateData to store 'address-override' bit that is used to decide whether to emit + // address-override (67H) prefix based on the memory BASE+INDEX registers. It's either `kX86MemInfo_67H_X86` or // `kX86MemInfo_67H_X64`. inline uint32_t _addressOverrideMask() const noexcept { return _privateData; } inline void _setAddressOverrideMask(uint32_t m) noexcept { _privateData = m; } @@ -715,7 +657,7 @@ public: //! \name Emit //! \{ - ASMJIT_API Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; + ASMJIT_API Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; //! \} //! \endcond @@ -723,7 +665,7 @@ public: //! \name Align //! \{ - ASMJIT_API Error align(uint32_t alignMode, uint32_t alignment) override; + ASMJIT_API Error align(AlignMode alignMode, uint32_t alignment) override; //! \} diff --git a/src/asmjit/x86/x86builder.cpp b/src/asmjit/x86/x86builder.cpp index b6b4ea3..a1b848d 100644 --- a/src/asmjit/x86/x86builder.cpp +++ b/src/asmjit/x86/x86builder.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_BUILDER) @@ -29,34 +11,22 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::Builder - Construction / Destruction] -// ============================================================================ - Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { if (code) code->attach(this); } Builder::~Builder() noexcept {} -// ============================================================================ -// [asmjit::x86::Builder - Finalize] -// ============================================================================ - Error Builder::finalize() { ASMJIT_PROPAGATE(runPasses()); Assembler a(_code); a.addEncodingOptions(encodingOptions()); - a.addValidationOptions(validationOptions()); + a.addDiagnosticOptions(diagnosticOptions()); return serializeTo(&a); } -// ============================================================================ -// [asmjit::x86::Builder - Events] -// ============================================================================ - Error Builder::onAttach(CodeHolder* code) noexcept { - uint32_t arch = code->arch(); + Arch arch = code->arch(); if (!Environment::isFamilyX86(arch)) return DebugUtils::errored(kErrorInvalidArch); diff --git a/src/asmjit/x86/x86builder.h b/src/asmjit/x86/x86builder.h index 256bc9e..31c9783 100644 --- a/src/asmjit/x86/x86builder.h +++ b/src/asmjit/x86/x86builder.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86BUILDER_H_INCLUDED #define ASMJIT_X86_X86BUILDER_H_INCLUDED @@ -28,7 +10,6 @@ #ifndef ASMJIT_NO_BUILDER #include "../core/builder.h" -#include "../core/datatypes.h" #include "../x86/x86emitter.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) @@ -36,19 +17,13 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::Builder] -// ============================================================================ - //! X86/X64 builder implementation. //! -//! The code representation used by \ref BaseBuilder is compatible with everything -//! AsmJit provides. Each instruction is stored as \ref InstNode, which contains -//! instruction id, options, and operands. Each instruction emitted will create -//! a new \ref InstNode instance and add it to the current cursor in the double-linked -//! list of nodes. Since the instruction stream used by \ref BaseBuilder can be -//! manipulated, we can rewrite the SumInts example from \ref asmjit_assembler -//! into the following: +//! The code representation used by \ref BaseBuilder is compatible with everything AsmJit provides. Each instruction +//! is stored as \ref InstNode, which contains instruction id, options, and operands. Each instruction emitted will +//! create a new \ref InstNode instance and add it to the current cursor in the double-linked list of nodes. Since +//! the instruction stream used by \ref BaseBuilder can be manipulated, we can rewrite the SumInts example from +//! \ref asmjit_assembler into the following: //! //! ``` //! #include <asmjit/x86.h> @@ -72,9 +47,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! code.init(rt.environment()); // Initialize code to match the JIT environment. //! x86::Builder cb(&code); // Create and attach x86::Builder to `code`. //! -//! // Decide which registers will be mapped to function arguments. Try changing -//! // registers of `dst`, `srcA`, and `srcB` and see what happens in function's -//! // prolog and epilog. +//! // Decide which registers will be mapped to function arguments. Try changing registers +//! // of `dst`, `srcA`, and `srcB` and see what happens in function's prolog and epilog. //! x86::Gp dst = cb.zax(); //! x86::Gp srcA = cb.zcx(); //! x86::Gp srcB = cb.zdx(); @@ -84,7 +58,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! // Create and initialize `FuncDetail`. //! FuncDetail func; -//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost)); +//! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost)); //! //! // Remember prolog insertion point. //! BaseNode* prologInsertionPoint = cb.cursor(); @@ -106,8 +80,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! FuncFrame frame; //! frame.init(func); //! -//! // Make XMM0 and XMM1 dirty; `kGroupVec` describes XMM|YMM|ZMM registers. -//! frame.setDirtyRegs(x86::Reg::kGroupVec, IntUtils::mask(0, 1)); +//! // Make XMM0 and XMM1 dirty; RegGroup::kVec describes XMM|YMM|ZMM registers. +//! frame.setDirtyRegs(RegGroup::kVec, IntUtils::mask(0, 1)); //! //! FuncArgsAssignment args(&func); // Create arguments assignment context. //! args.assignAll(dst, srcA, srcB); // Assign our registers to arguments. @@ -148,8 +122,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! When the example is executed it should output the following (this one using -//! AMD64-SystemV ABI): +//! When the example is executed it should output the following (this one using AMD64-SystemV ABI): //! //! ``` //! Raw Function: @@ -170,23 +143,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! {5 8 4 9} //! ``` //! -//! The number of use-cases of \ref BaseBuilder is not limited and highly depends -//! on your creativity and experience. The previous example can be easily improved -//! to collect all dirty registers inside the function programmatically and to pass -//! them to \ref FuncFrame::setDirtyRegs(). +//! The number of use-cases of \ref BaseBuilder is not limited and highly depends on your creativity and experience. +//! The previous example can be easily improved to collect all dirty registers inside the function programmatically +//! and to pass them to \ref FuncFrame::setDirtyRegs(). //! //! ``` //! #include <asmjit/x86.h> //! //! using namespace asmjit; //! -//! // NOTE: This function doesn't cover all possible constructs. It ignores -//! // instructions that write to implicit registers that are not part of the -//! // operand list. It also counts read-only registers. Real implementation -//! // would be a bit more complicated, but still relatively easy to implement. +//! // NOTE: This function doesn't cover all possible constructs. It ignores instructions that write +//! // to implicit registers that are not part of the operand list. It also counts read-only registers. +//! // Real implementation would be a bit more complicated, but still relatively easy to implement. //! static void collectDirtyRegs(const BaseNode* first, //! const BaseNode* last, -//! uint32_t regMask[BaseReg::kGroupVirt]) { +//! Support::Array<RegMask, Globals::kNumVirtGroups>& regMask) { //! const BaseNode* node = first; //! while (node) { //! if (node->actsAsInst()) { @@ -197,7 +168,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! const Operand& op = opArray[i]; //! if (op.isReg()) { //! const x86::Reg& reg = op.as<x86::Reg>(); -//! if (reg.group() < BaseReg::kGroupVirt) { +//! if (reg.group() <= RegGroup::kMaxVirt) { //! regMask[reg.group()] |= 1u << reg.id(); //! } //! } @@ -211,23 +182,21 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! //! static void setDirtyRegsOfFuncFrame(const x86::Builder& builder, FuncFrame& frame) { -//! uint32_t regMask[BaseReg::kGroupVirt] {}; +//! Support::Array<RegMask, Globals::kNumVirtGroups> regMask {}; //! collectDirtyRegs(builder.firstNode(), builder.lastNode(), regMask); //! //! // X86/X64 ABIs only require to save GP/XMM registers: -//! frame.setDirtyRegs(x86::Reg::kGroupGp , regMask[x86::Reg::kGroupGp ]); -//! frame.setDirtyRegs(x86::Reg::kGroupVec, regMask[x86::Reg::kGroupVec]); +//! frame.setDirtyRegs(RegGroup::kGp, regMask[RegGroup::kGp]); +//! frame.setDirtyRegs(RegGroup::kVec, regMask[RegGroup::kVec]); //! } //! ``` //! //! ### Casting Between Various Emitters //! -//! Even when \ref BaseAssembler and \ref BaseBuilder provide the same interface -//! as defined by \ref BaseEmitter their platform dependent variants like \ref -//! x86::Assembler and \ref x86::Builder cannot be interchanged or casted -//! to each other by using a C++ `static_cast<>`. The main reason is the -//! inheritance graph of these classes is different and cast-incompatible, as -//! illustrated below: +//! Even when \ref BaseAssembler and \ref BaseBuilder provide the same interface as defined by \ref BaseEmitter their +//! platform dependent variants like \ref x86::Assembler and \ref x86::Builder cannot be interchanged or casted to each +//! other by using a C++ `static_cast<>`. The main reason is the inheritance graph of these classes is different and +//! cast-incompatible, as illustrated below: //! //! ``` //! +--------------+ +=========================+ @@ -250,15 +219,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! (abstract) (final) (mixin) //! ``` //! -//! The graph basically shows that it's not possible to cast between \ref -//! x86::Assembler and \ref x86::Builder. However, since both share the -//! base interface (\ref BaseEmitter) it's possible to cast them to a class -//! that cannot be instantiated, but defines the same interface - the class -//! is called \ref x86::Emitter and was introduced to make it possible to -//! write a function that can emit to both \ref x86::Assembler and \ref -//! x86::Builder. Note that \ref x86::Emitter cannot be created, it's abstract -//! and has private constructors and destructors; it was only designed to be -//! casted to and used as an interface. +//! The graph basically shows that it's not possible to cast between \ref x86::Assembler and \ref x86::Builder. +//! However, since both share the base interface (\ref BaseEmitter) it's possible to cast them to a class that +//! cannot be instantiated, but defines the same interface - the class is called \ref x86::Emitter and was +//! introduced to make it possible to write a function that can emit to both \ref x86::Assembler and \ref +//! x86::Builder. Note that \ref x86::Emitter cannot be created, it's abstract and has private constructors and +//! destructors; it was only designed to be casted to and used as an interface. //! //! Each architecture-specific emitter implements a member function called //! `as<arch::Emitter>()`, which casts the instance to the architecture @@ -289,19 +255,16 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! The example above shows how to create a function that can emit code to -//! either \ref x86::Assembler or \ref x86::Builder through \ref x86::Emitter, -//! which provides emitter-neutral functionality. \ref x86::Emitter, however, -//! doesn't provide any emitter-specific functionality like `setCursor()`. +//! The example above shows how to create a function that can emit code to either \ref x86::Assembler or \ref +//! x86::Builder through \ref x86::Emitter, which provides emitter-neutral functionality. \ref x86::Emitter, +//! however, doesn't provide any emitter-specific functionality like `setCursor()`. //! //! ### Code Injection and Manipulation //! -//! \ref BaseBuilder emitter stores its nodes in a double-linked list, which -//! makes it easy to manipulate that list during the code generation or -//! afterwards. Each node is always emitted next to the current cursor and the -//! cursor is advanced to that newly emitted node. The cursor can be retrieved -//! and changed by \ref BaseBuilder::cursor() and \ref BaseBuilder::setCursor(), -//! respectively. +//! \ref BaseBuilder emitter stores its nodes in a double-linked list, which makes it easy to manipulate that +//! list during the code generation or afterwards. Each node is always emitted next to the current cursor and +//! the cursor is advanced to that newly emitted node. The cursor can be retrieved and changed by \ref +//! BaseBuilder::cursor() and \ref BaseBuilder::setCursor(), respectively. //! //! The example below demonstrates how to remember a node and inject something //! next to it. diff --git a/src/asmjit/x86/x86compiler.cpp b/src/asmjit/x86/x86compiler.cpp index 92ed645..014ba19 100644 --- a/src/asmjit/x86/x86compiler.cpp +++ b/src/asmjit/x86/x86compiler.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_COMPILER) @@ -30,34 +12,22 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::Compiler - Construction / Destruction] -// ============================================================================ - Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { if (code) code->attach(this); } Compiler::~Compiler() noexcept {} -// ============================================================================ -// [asmjit::x86::Compiler - Finalize] -// ============================================================================ - Error Compiler::finalize() { ASMJIT_PROPAGATE(runPasses()); Assembler a(_code); a.addEncodingOptions(encodingOptions()); - a.addValidationOptions(validationOptions()); + a.addDiagnosticOptions(diagnosticOptions()); return serializeTo(&a); } -// ============================================================================ -// [asmjit::x86::Compiler - Events] -// ============================================================================ - Error Compiler::onAttach(CodeHolder* code) noexcept { - uint32_t arch = code->arch(); + Arch arch = code->arch(); if (!Environment::isFamilyX86(arch)) return DebugUtils::errored(kErrorInvalidArch); diff --git a/src/asmjit/x86/x86compiler.h b/src/asmjit/x86/x86compiler.h index 7ca506a..466ffa2 100644 --- a/src/asmjit/x86/x86compiler.h +++ b/src/asmjit/x86/x86compiler.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86COMPILER_H_INCLUDED #define ASMJIT_X86_X86COMPILER_H_INCLUDED @@ -28,7 +10,6 @@ #ifndef ASMJIT_NO_COMPILER #include "../core/compiler.h" -#include "../core/datatypes.h" #include "../core/type.h" #include "../x86/x86emitter.h" @@ -37,16 +18,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::Compiler] -// ============================================================================ - //! X86/X64 compiler implementation. //! //! ### Compiler Basics //! -//! The first \ref x86::Compiler example shows how to generate a function that -//! simply returns an integer value. It's an analogy to the first Assembler example: +//! The first \ref x86::Compiler example shows how to generate a function that simply returns an integer value. It's +//! an analogy to the first Assembler example: //! //! ``` //! #include <asmjit/x86.h> @@ -87,12 +64,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! } //! ``` //! -//! The \ref BaseCompiler::addFunc() and \ref BaseCompiler::endFunc() functions -//! are used to define the function and its end. Both must be called per function, -//! but the body doesn't have to be generated in sequence. An example of generating -//! two functions will be shown later. The next example shows more complicated code -//! that contain a loop and generates a simple memory copy function that uses -//! `uint32_t` items: +//! The \ref BaseCompiler::addFunc() and \ref BaseCompiler::endFunc() functions are used to define the function and +//! its end. Both must be called per function, but the body doesn't have to be generated in sequence. An example of +//! generating two functions will be shown later. The next example shows more complicated code that contain a loop +//! and generates a simple memory copy function that uses `uint32_t` items: //! //! ``` //! #include <asmjit/x86.h> @@ -110,7 +85,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! code.init(rt.environment()); // Initialize code to match the JIT environment. //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! cc.addFunc( // Begin the function of the following signature: +//! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature: //! FuncSignatureT<void, // Return value - void (no return value). //! uint32_t*, // 1st argument - uint32_t* (machine reg-size). //! const uint32_t*, // 2nd argument - uint32_t* (machine reg-size). @@ -123,9 +98,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! x86::Gp src = cc.newIntPtr("src");// Create `src` register (source pointer). //! x86::Gp i = cc.newUIntPtr("i"); // Create `i` register (loop counter). //! -//! cc.setArg(0, dst); // Assign `dst` argument. -//! cc.setArg(1, src); // Assign `src` argument. -//! cc.setArg(2, i); // Assign `i` argument. +//! funcNode->setArg(0, dst); // Assign `dst` argument. +//! funcNode->setArg(1, src); // Assign `src` argument. +//! funcNode->setArg(2, i); // Assign `i` argument. //! //! cc.test(i, i); // Early exit if length is zero. //! cc.jz(L_Exit); @@ -172,11 +147,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### AVX and AVX-512 //! -//! AVX and AVX-512 code generation must be explicitly enabled via \ref FuncFrame -//! to work properly. If it's not setup correctly then Prolog & Epilog would use -//! SSE instead of AVX instructions to work with SIMD registers. In addition, Compiler -//! requires explicitly enable AVX-512 via \ref FuncFrame in order to use all 32 SIMD -//! registers. +//! AVX and AVX-512 code generation must be explicitly enabled via \ref FuncFrame to work properly. If it's not setup +//! correctly then Prolog & Epilog would use SSE instead of AVX instructions to work with SIMD registers. In addition, +//! Compiler requires explicitly enable AVX-512 via \ref FuncFrame in order to use all 32 SIMD registers. //! //! ``` //! #include <asmjit/x86.h> @@ -194,17 +167,17 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! code.init(rt.environment()); // Initialize code to match the JIT environment. //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! cc.addFunc(FuncSignatureT<void, void*>()); +//! FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*>()); //! //! // Use the following to enable AVX and/or AVX-512. -//! cc.func()->frame().setAvxEnabled(); -//! cc.func()->frame().setAvx512Enabled(); +//! funcNode->frame().setAvxEnabled(); +//! funcNode->frame().setAvx512Enabled(); //! //! // Do something with the input pointer. //! x86::Gp addr = cc.newIntPtr("addr"); //! x86::Zmm vreg = cc.newZmm("vreg"); //! -//! cc.setArg(0, addr); +//! funcNode->setArg(0, addr); //! //! cc.vmovdqu32(vreg, x86::ptr(addr)); //! cc.vpaddq(vreg, vreg, vreg); @@ -231,9 +204,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Recursive Functions //! -//! It's possible to create more functions by using the same \ref x86::Compiler -//! instance and make links between them. In such case it's important to keep -//! the pointer to \ref FuncNode. +//! It's possible to create more functions by using the same \ref x86::Compiler instance and make links between them. +//! In such case it's important to keep the pointer to \ref FuncNode. //! //! The example below creates a simple Fibonacci function that calls itself recursively: //! @@ -253,14 +225,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! code.init(rt.environment()); // Initialize code to match the JIT environment. //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code. //! -//! FuncNode* func = cc.addFunc( // Begin of the Fibonacci function, addFunc() +//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc() //! FuncSignatureT<int, int>()); // Returns a pointer to the FuncNode node. //! //! Label L_Exit = cc.newLabel() // Exit label. -//! x86::Gp x = cc.newU32(); // Function x argument. -//! x86::Gp y = cc.newU32(); // Temporary. +//! x86::Gp x = cc.newUInt32(); // Function x argument. +//! x86::Gp y = cc.newUInt32(); // Temporary. //! -//! cc.setArg(0, x); +//! funcNode->setArg(0, x); //! //! cc.cmp(x, 3); // Return x if less than 3. //! cc.jb(L_Exit); @@ -270,7 +242,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! InvokeNode* invokeNode; // Function invocation: //! cc.invoke(&invokeNode, // - InvokeNode (output). -//! func->label(), // - Function address or Label. +//! funcNode->label(), // - Function address or Label. //! FuncSignatureT<int, int>()); // - Function signature. //! //! invokeNode->setArg(0, x); // Assign x as the first argument. @@ -300,7 +272,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Stack Management //! -//! Function's stack-frame is managed automatically, which is used by the register allocator to spill virtual registers. It also provides an interface to allocate user-defined block of the stack, which can be used as a temporary storage by the generated function. In the following example a stack of 256 bytes size is allocated, filled by bytes starting from 0 to 255 and then iterated again to sum all the values. +//! Function's stack-frame is managed automatically, which is used by the register allocator to spill virtual +//! registers. It also provides an interface to allocate user-defined block of the stack, which can be used as +//! a temporary storage by the generated function. In the following example a stack of 256 bytes size is allocated, +//! filled by bytes starting from 0 to 255 and then iterated again to sum all the values. //! //! ``` //! #include <asmjit/x86.h> @@ -349,8 +324,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! cc.jb(L1); // goto L1; //! //! // Second loop, sum all bytes stored in `stack`. -//! x86::Gp sum = cc.newI32("sum"); -//! x86::Gp val = cc.newI32("val"); +//! x86::Gp sum = cc.newInt32("sum"); +//! x86::Gp val = cc.newInt32("val"); //! //! cc.xor_(i, i); //! cc.xor_(sum, sum); @@ -386,12 +361,11 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! Compiler provides two constant pools for a general purpose code generation: //! -//! - Local constant pool - Part of \ref FuncNode, can be only used by a -//! single function and added after the function epilog sequence (after -//! `ret` instruction). +//! - Local constant pool - Part of \ref FuncNode, can be only used by a single function and added after the +//! function epilog sequence (after `ret` instruction). //! -//! - Global constant pool - Part of \ref BaseCompiler, flushed at the end -//! of the generated code by \ref BaseEmitter::finalize(). +//! - Global constant pool - Part of \ref BaseCompiler, flushed at the end of the generated code by \ref +//! BaseEmitter::finalize(). //! //! The example below illustrates how a built-in constant pool can be used: //! @@ -406,8 +380,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! x86::Gp v0 = cc.newGpd("v0"); //! x86::Gp v1 = cc.newGpd("v1"); //! -//! x86::Mem c0 = cc.newInt32Const(ConstPool::kScopeLocal, 200); -//! x86::Mem c1 = cc.newInt32Const(ConstPool::kScopeLocal, 33); +//! x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kLocal, 200); +//! x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kLocal, 33); //! //! cc.mov(v0, c0); //! cc.mov(v1, c1); @@ -420,16 +394,14 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! //! ### Jump Tables //! -//! x86::Compiler supports `jmp` instruction with reg/mem operand, which is a -//! commonly used pattern to implement indirect jumps within a function, for -//! example to implement `switch()` statement in a programming languages. By -//! default AsmJit assumes that every basic block can be a possible jump -//! target as it's unable to deduce targets from instruction's operands. This -//! is a very pessimistic default that should be avoided if possible as it's -//! costly and very unfriendly to liveness analysis and register allocation. +//! x86::Compiler supports `jmp` instruction with reg/mem operand, which is a commonly used pattern to implement +//! indirect jumps within a function, for example to implement `switch()` statement in a programming languages. +//! By default AsmJit assumes that every basic block can be a possible jump target as it's unable to deduce targets +//! from instruction's operands. This is a very pessimistic default that should be avoided if possible as it's costly +//! and very unfriendly to liveness analysis and register allocation. //! -//! Instead of relying on such pessimistic default behavior, let's use \ref -//! JumpAnnotation to annotate a jump where all targets are known: +//! Instead of relying on such pessimistic default behavior, let's use \ref JumpAnnotation to annotate a jump where +//! all targets are known: //! //! ``` //! #include <asmjit/x86.h> @@ -437,7 +409,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! using namespace asmjit; //! //! static void exampleUseOfIndirectJump(x86::Compiler& cc) { -//! cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConv::kIdHost)); +//! FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConvId::kHost)); //! //! // Function arguments //! x86::Xmm a = cc.newXmmSs("a"); @@ -454,13 +426,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! Label L_Div = cc.newLabel(); //! Label L_End = cc.newLabel(); //! -//! cc.setArg(0, a); -//! cc.setArg(1, b); -//! cc.setArg(2, op); +//! funcNode->setArg(0, a); +//! funcNode->setArg(1, b); +//! funcNode->setArg(2, op); //! -//! // Jump annotation is a building block that allows to annotate all -//! // possible targets where `jmp()` can jump. It then drives the CFG -//! // construction and liveness analysis, which impacts register allocation. +//! // Jump annotation is a building block that allows to annotate all possible targets where `jmp()` can +//! // jump. It then drives the CFG construction and liveness analysis, which impacts register allocation. //! JumpAnnotation* annotation = cc.newJumpAnnotation(); //! annotation->addLabel(L_Add); //! annotation->addLabel(L_Sub); @@ -536,14 +507,14 @@ public: #endif #define ASMJIT_NEW_REG_CUSTOM(FUNC, REG) \ - inline REG FUNC(uint32_t typeId) { \ + inline REG FUNC(TypeId typeId) { \ REG reg(Globals::NoInit); \ _newReg(®, typeId); \ return reg; \ } \ \ template<typename... Args> \ - inline REG FUNC(uint32_t typeId, const char* fmt, Args&&... args) { \ + inline REG FUNC(TypeId typeId, const char* fmt, Args&&... args) { \ REG reg(Globals::NoInit); \ ASMJIT_NEW_REG_FMT(reg, typeId, fmt, std::forward<Args>(args)...); \ return reg; \ @@ -582,46 +553,38 @@ public: ASMJIT_NEW_REG_CUSTOM(newVec , Vec ) ASMJIT_NEW_REG_CUSTOM(newK , KReg) - ASMJIT_NEW_REG_TYPED(newI8 , Gp , Type::kIdI8 ) - ASMJIT_NEW_REG_TYPED(newU8 , Gp , Type::kIdU8 ) - ASMJIT_NEW_REG_TYPED(newI16 , Gp , Type::kIdI16 ) - ASMJIT_NEW_REG_TYPED(newU16 , Gp , Type::kIdU16 ) - ASMJIT_NEW_REG_TYPED(newI32 , Gp , Type::kIdI32 ) - ASMJIT_NEW_REG_TYPED(newU32 , Gp , Type::kIdU32 ) - ASMJIT_NEW_REG_TYPED(newI64 , Gp , Type::kIdI64 ) - ASMJIT_NEW_REG_TYPED(newU64 , Gp , Type::kIdU64 ) - ASMJIT_NEW_REG_TYPED(newInt8 , Gp , Type::kIdI8 ) - ASMJIT_NEW_REG_TYPED(newUInt8 , Gp , Type::kIdU8 ) - ASMJIT_NEW_REG_TYPED(newInt16 , Gp , Type::kIdI16 ) - ASMJIT_NEW_REG_TYPED(newUInt16 , Gp , Type::kIdU16 ) - ASMJIT_NEW_REG_TYPED(newInt32 , Gp , Type::kIdI32 ) - ASMJIT_NEW_REG_TYPED(newUInt32 , Gp , Type::kIdU32 ) - ASMJIT_NEW_REG_TYPED(newInt64 , Gp , Type::kIdI64 ) - ASMJIT_NEW_REG_TYPED(newUInt64 , Gp , Type::kIdU64 ) - ASMJIT_NEW_REG_TYPED(newIntPtr , Gp , Type::kIdIntPtr ) - ASMJIT_NEW_REG_TYPED(newUIntPtr, Gp , Type::kIdUIntPtr) - - ASMJIT_NEW_REG_TYPED(newGpb , Gp , Type::kIdU8 ) - ASMJIT_NEW_REG_TYPED(newGpw , Gp , Type::kIdU16 ) - ASMJIT_NEW_REG_TYPED(newGpd , Gp , Type::kIdU32 ) - ASMJIT_NEW_REG_TYPED(newGpq , Gp , Type::kIdU64 ) - ASMJIT_NEW_REG_TYPED(newGpz , Gp , Type::kIdUIntPtr) - ASMJIT_NEW_REG_TYPED(newXmm , Xmm , Type::kIdI32x4 ) - ASMJIT_NEW_REG_TYPED(newXmmSs , Xmm , Type::kIdF32x1 ) - ASMJIT_NEW_REG_TYPED(newXmmSd , Xmm , Type::kIdF64x1 ) - ASMJIT_NEW_REG_TYPED(newXmmPs , Xmm , Type::kIdF32x4 ) - ASMJIT_NEW_REG_TYPED(newXmmPd , Xmm , Type::kIdF64x2 ) - ASMJIT_NEW_REG_TYPED(newYmm , Ymm , Type::kIdI32x8 ) - ASMJIT_NEW_REG_TYPED(newYmmPs , Ymm , Type::kIdF32x8 ) - ASMJIT_NEW_REG_TYPED(newYmmPd , Ymm , Type::kIdF64x4 ) - ASMJIT_NEW_REG_TYPED(newZmm , Zmm , Type::kIdI32x16 ) - ASMJIT_NEW_REG_TYPED(newZmmPs , Zmm , Type::kIdF32x16 ) - ASMJIT_NEW_REG_TYPED(newZmmPd , Zmm , Type::kIdF64x8 ) - ASMJIT_NEW_REG_TYPED(newMm , Mm , Type::kIdMmx64 ) - ASMJIT_NEW_REG_TYPED(newKb , KReg, Type::kIdMask8 ) - ASMJIT_NEW_REG_TYPED(newKw , KReg, Type::kIdMask16 ) - ASMJIT_NEW_REG_TYPED(newKd , KReg, Type::kIdMask32 ) - ASMJIT_NEW_REG_TYPED(newKq , KReg, Type::kIdMask64 ) + ASMJIT_NEW_REG_TYPED(newInt8 , Gp , TypeId::kInt8) + ASMJIT_NEW_REG_TYPED(newUInt8 , Gp , TypeId::kUInt8) + ASMJIT_NEW_REG_TYPED(newInt16 , Gp , TypeId::kInt16) + ASMJIT_NEW_REG_TYPED(newUInt16 , Gp , TypeId::kUInt16) + ASMJIT_NEW_REG_TYPED(newInt32 , Gp , TypeId::kInt32) + ASMJIT_NEW_REG_TYPED(newUInt32 , Gp , TypeId::kUInt32) + ASMJIT_NEW_REG_TYPED(newInt64 , Gp , TypeId::kInt64) + ASMJIT_NEW_REG_TYPED(newUInt64 , Gp , TypeId::kUInt64) + ASMJIT_NEW_REG_TYPED(newIntPtr , Gp , TypeId::kIntPtr) + ASMJIT_NEW_REG_TYPED(newUIntPtr, Gp , TypeId::kUIntPtr) + + ASMJIT_NEW_REG_TYPED(newGpb , Gp , TypeId::kUInt8) + ASMJIT_NEW_REG_TYPED(newGpw , Gp , TypeId::kUInt16) + ASMJIT_NEW_REG_TYPED(newGpd , Gp , TypeId::kUInt32) + ASMJIT_NEW_REG_TYPED(newGpq , Gp , TypeId::kUInt64) + ASMJIT_NEW_REG_TYPED(newGpz , Gp , TypeId::kUIntPtr) + ASMJIT_NEW_REG_TYPED(newXmm , Xmm , TypeId::kInt32x4) + ASMJIT_NEW_REG_TYPED(newXmmSs , Xmm , TypeId::kFloat32x1) + ASMJIT_NEW_REG_TYPED(newXmmSd , Xmm , TypeId::kFloat64x1) + ASMJIT_NEW_REG_TYPED(newXmmPs , Xmm , TypeId::kFloat32x4) + ASMJIT_NEW_REG_TYPED(newXmmPd , Xmm , TypeId::kFloat64x2) + ASMJIT_NEW_REG_TYPED(newYmm , Ymm , TypeId::kInt32x8) + ASMJIT_NEW_REG_TYPED(newYmmPs , Ymm , TypeId::kFloat32x8) + ASMJIT_NEW_REG_TYPED(newYmmPd , Ymm , TypeId::kFloat64x4) + ASMJIT_NEW_REG_TYPED(newZmm , Zmm , TypeId::kInt32x16) + ASMJIT_NEW_REG_TYPED(newZmmPs , Zmm , TypeId::kFloat32x16) + ASMJIT_NEW_REG_TYPED(newZmmPd , Zmm , TypeId::kFloat64x8) + ASMJIT_NEW_REG_TYPED(newMm , Mm , TypeId::kMmx64) + ASMJIT_NEW_REG_TYPED(newKb , KReg, TypeId::kMask8) + ASMJIT_NEW_REG_TYPED(newKw , KReg, TypeId::kMask16) + ASMJIT_NEW_REG_TYPED(newKd , KReg, TypeId::kMask32) + ASMJIT_NEW_REG_TYPED(newKq , KReg, TypeId::kMask64) #undef ASMJIT_NEW_REG_TYPED #undef ASMJIT_NEW_REG_CUSTOM @@ -645,49 +608,38 @@ public: //! \{ //! Put data to a constant-pool and get a memory reference to it. - inline Mem newConst(uint32_t scope, const void* data, size_t size) { + inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) { Mem m(Globals::NoInit); _newConst(&m, scope, data, size); return m; } //! Put a BYTE `val` to a constant-pool. - inline Mem newByteConst(uint32_t scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } + inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } //! Put a WORD `val` to a constant-pool. - inline Mem newWordConst(uint32_t scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + inline Mem newWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a DWORD `val` to a constant-pool. - inline Mem newDWordConst(uint32_t scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + inline Mem newDWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a QWORD `val` to a constant-pool. - inline Mem newQWordConst(uint32_t scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + inline Mem newQWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a WORD `val` to a constant-pool. - inline Mem newInt16Const(uint32_t scope, int16_t val) noexcept { return newConst(scope, &val, 2); } + inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a WORD `val` to a constant-pool. - inline Mem newUInt16Const(uint32_t scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } //! Put a DWORD `val` to a constant-pool. - inline Mem newInt32Const(uint32_t scope, int32_t val) noexcept { return newConst(scope, &val, 4); } + inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a DWORD `val` to a constant-pool. - inline Mem newUInt32Const(uint32_t scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } //! Put a QWORD `val` to a constant-pool. - inline Mem newInt64Const(uint32_t scope, int64_t val) noexcept { return newConst(scope, &val, 8); } + inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a QWORD `val` to a constant-pool. - inline Mem newUInt64Const(uint32_t scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } //! Put a SP-FP `val` to a constant-pool. - inline Mem newFloatConst(uint32_t scope, float val) noexcept { return newConst(scope, &val, 4); } + inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); } //! Put a DP-FP `val` to a constant-pool. - inline Mem newDoubleConst(uint32_t scope, double val) noexcept { return newConst(scope, &val, 8); } - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("newMmConst() uses a deprecated Data64, use newConst() with your own data instead") - inline Mem newMmConst(uint32_t scope, const Data64& val) noexcept { return newConst(scope, &val, 8); } - - ASMJIT_DEPRECATED("newXmmConst() uses a deprecated Data128, use newConst() with your own data instead") - inline Mem newXmmConst(uint32_t scope, const Data128& val) noexcept { return newConst(scope, &val, 16); } - - ASMJIT_DEPRECATED("newYmmConst() uses a deprecated Data256, use newConst() with your own data instead") - inline Mem newYmmConst(uint32_t scope, const Data256& val) noexcept { return newConst(scope, &val, 32); } -#endif // !ASMJIT_NO_DEPRECATED + inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); } //! \} @@ -695,9 +647,9 @@ public: //! \{ //! Force the compiler to not follow the conditional or unconditional jump. - inline Compiler& unfollow() noexcept { _instOptions |= Inst::kOptionUnfollow; return *this; } + inline Compiler& unfollow() noexcept { addInstOptions(InstOptions::kUnfollow); return *this; } //! Tell the compiler that the destination variable will be overwritten. - inline Compiler& overwrite() noexcept { _instOptions |= Inst::kOptionOverwrite; return *this; } + inline Compiler& overwrite() noexcept { addInstOptions(InstOptions::kOverwrite); return *this; } //! \} @@ -706,15 +658,13 @@ public: //! Invoke a function call without `target` type enforcement. inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) { - return _addInvokeNode(out, Inst::kIdCall, target, signature); + return addInvokeNode(out, Inst::kIdCall, target, signature); } - //! Invoke a function call of the given `target` and `signature` and store - //! the added node to `out`. + //! Invoke a function call of the given `target` and `signature` and store the added node to `out`. //! - //! Creates a new \ref InvokeNode, initializes all the necessary members to - //! match the given function `signature`, adds the node to the compiler, and - //! stores its pointer to `out`. The operation is atomic, if anything fails + //! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`, + //! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails //! nullptr is stored in `out` and error code is returned. inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); } //! \overload @@ -726,22 +676,12 @@ public: //! \overload inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); } -#ifndef _DOXYGEN - template<typename Target> - ASMJIT_DEPRECATED("Use invoke() instead of call()") - inline InvokeNode* call(const Target& target, const FuncSignature& signature) { - InvokeNode* invokeNode; - invoke(&invokeNode, target, signature); - return invokeNode; - } -#endif - - //! Return. - inline FuncRetNode* ret() { return addRet(Operand(), Operand()); } + //! Return from function. + inline Error ret() { return addRet(Operand(), Operand()); } //! \overload - inline FuncRetNode* ret(const BaseReg& o0) { return addRet(o0, Operand()); } + inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); } //! \overload - inline FuncRetNode* ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } + inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } //! \} diff --git a/src/asmjit/x86/x86emithelper.cpp b/src/asmjit/x86/x86emithelper.cpp index e6290ea..4a85a16 100644 --- a/src/asmjit/x86/x86emithelper.cpp +++ b/src/asmjit/x86/x86emithelper.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) @@ -35,11 +17,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::Internal - Helpers] -// ============================================================================ +// x86::EmitHelper - Utilities +// =========================== -static ASMJIT_INLINE uint32_t getXmmMovInst(const FuncFrame& frame) { +static inline uint32_t getXmmMovInst(const FuncFrame& frame) { bool avx = frame.isAvxEnabled(); bool aligned = frame.hasAlignedVecSR(); @@ -58,21 +39,24 @@ static inline uint32_t kmovInstFromSize(uint32_t size) noexcept { } } -// ============================================================================ -// [asmjit::X86Internal - Emit Helpers] -// ============================================================================ +static inline uint32_t makeCastOp(TypeId dst, TypeId src) noexcept { + return (uint32_t(dst) << 8) | uint32_t(src); +} + +// x86::EmitHelper - Emit Reg Move +// =============================== ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove( const Operand_& dst_, - const Operand_& src_, uint32_t typeId, const char* comment) { + const Operand_& src_, TypeId typeId, const char* comment) { // Invalid or abstract TypeIds are not allowed. - ASMJIT_ASSERT(Type::isValid(typeId) && !Type::isAbstract(typeId)); + ASMJIT_ASSERT(TypeUtils::isValid(typeId) && !TypeUtils::isAbstract(typeId)); Operand dst(dst_); Operand src(src_); - uint32_t instId = Inst::kIdNone; + InstId instId = Inst::kIdNone; uint32_t memFlags = 0; uint32_t overrideMemSize = 0; @@ -81,72 +65,70 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove( kSrcMem = 0x2 }; - // Detect memory operands and patch them to have the same size as the register. - // BaseCompiler always sets memory size of allocs and spills, so it shouldn't - // be really necessary, however, after this function was separated from Compiler - // it's better to make sure that the size is always specified, as we can use - // 'movzx' and 'movsx' that rely on it. + // Detect memory operands and patch them to have the same size as the register. BaseCompiler always sets memory size + // of allocs and spills, so it shouldn't be really necessary, however, after this function was separated from Compiler + // it's better to make sure that the size is always specified, as we can use 'movzx' and 'movsx' that rely on it. if (dst.isMem()) { memFlags |= kDstMem; dst.as<Mem>().setSize(src.size()); } if (src.isMem()) { memFlags |= kSrcMem; src.as<Mem>().setSize(dst.size()); } switch (typeId) { - case Type::kIdI8: - case Type::kIdU8: - case Type::kIdI16: - case Type::kIdU16: + case TypeId::kInt8: + case TypeId::kUInt8: + case TypeId::kInt16: + case TypeId::kUInt16: // Special case - 'movzx' load. if (memFlags & kSrcMem) { instId = Inst::kIdMovzx; - dst.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); } else if (!memFlags) { // Change both destination and source registers to GPD (safer, no dependencies). - dst.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); - src.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); + src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); } ASMJIT_FALLTHROUGH; - case Type::kIdI32: - case Type::kIdU32: - case Type::kIdI64: - case Type::kIdU64: + case TypeId::kInt32: + case TypeId::kUInt32: + case TypeId::kInt64: + case TypeId::kUInt64: instId = Inst::kIdMov; break; - case Type::kIdMmx32: + case TypeId::kMmx32: instId = Inst::kIdMovd; if (memFlags) break; ASMJIT_FALLTHROUGH; - case Type::kIdMmx64 : instId = Inst::kIdMovq ; break; - case Type::kIdMask8 : instId = Inst::kIdKmovb; break; - case Type::kIdMask16: instId = Inst::kIdKmovw; break; - case Type::kIdMask32: instId = Inst::kIdKmovd; break; - case Type::kIdMask64: instId = Inst::kIdKmovq; break; + case TypeId::kMmx64 : instId = Inst::kIdMovq ; break; + case TypeId::kMask8 : instId = Inst::kIdKmovb; break; + case TypeId::kMask16: instId = Inst::kIdKmovw; break; + case TypeId::kMask32: instId = Inst::kIdKmovd; break; + case TypeId::kMask64: instId = Inst::kIdKmovq; break; default: { - uint32_t elementTypeId = Type::baseOf(typeId); - if (Type::isVec32(typeId) && memFlags) { + TypeId scalarTypeId = TypeUtils::scalarOf(typeId); + if (TypeUtils::isVec32(typeId) && memFlags) { overrideMemSize = 4; - if (elementTypeId == Type::kIdF32) + if (scalarTypeId == TypeId::kFloat32) instId = _avxEnabled ? Inst::kIdVmovss : Inst::kIdMovss; else instId = _avxEnabled ? Inst::kIdVmovd : Inst::kIdMovd; break; } - if (Type::isVec64(typeId) && memFlags) { + if (TypeUtils::isVec64(typeId) && memFlags) { overrideMemSize = 8; - if (elementTypeId == Type::kIdF64) + if (scalarTypeId == TypeId::kFloat64) instId = _avxEnabled ? Inst::kIdVmovsd : Inst::kIdMovsd; else instId = _avxEnabled ? Inst::kIdVmovq : Inst::kIdMovq; break; } - if (elementTypeId == Type::kIdF32) + if (scalarTypeId == TypeId::kFloat32) instId = _avxEnabled ? Inst::kIdVmovaps : Inst::kIdMovaps; - else if (elementTypeId == Type::kIdF64) + else if (scalarTypeId == TypeId::kFloat64) instId = _avxEnabled ? Inst::kIdVmovapd : Inst::kIdMovapd; else if (!_avx512Enabled) instId = _avxEnabled ? Inst::kIdVmovdqa : Inst::kIdMovdqa; @@ -168,75 +150,77 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove( return _emitter->emit(instId, dst, src); } +// x86::EmitHelper - Emit Arg Move +// =============================== + ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( - const BaseReg& dst_, uint32_t dstTypeId, - const Operand_& src_, uint32_t srcTypeId, const char* comment) { + const BaseReg& dst_, TypeId dstTypeId, + const Operand_& src_, TypeId srcTypeId, const char* comment) { - // Deduce optional `dstTypeId`, which may be `Type::kIdVoid` in some cases. - if (!dstTypeId) { + // Deduce optional `dstTypeId`, which may be `TypeId::kVoid` in some cases. + if (dstTypeId == TypeId::kVoid) { const ArchTraits& archTraits = ArchTraits::byArch(_emitter->arch()); dstTypeId = archTraits.regTypeToTypeId(dst_.type()); } // Invalid or abstract TypeIds are not allowed. - ASMJIT_ASSERT(Type::isValid(dstTypeId) && !Type::isAbstract(dstTypeId)); - ASMJIT_ASSERT(Type::isValid(srcTypeId) && !Type::isAbstract(srcTypeId)); + ASMJIT_ASSERT(TypeUtils::isValid(dstTypeId) && !TypeUtils::isAbstract(dstTypeId)); + ASMJIT_ASSERT(TypeUtils::isValid(srcTypeId) && !TypeUtils::isAbstract(srcTypeId)); Reg dst(dst_.as<Reg>()); Operand src(src_); - uint32_t dstSize = Type::sizeOf(dstTypeId); - uint32_t srcSize = Type::sizeOf(srcTypeId); + uint32_t dstSize = TypeUtils::sizeOf(dstTypeId); + uint32_t srcSize = TypeUtils::sizeOf(srcTypeId); - uint32_t instId = Inst::kIdNone; + InstId instId = Inst::kIdNone; // Not a real loop, just 'break' is nicer than 'goto'. for (;;) { - if (Type::isInt(dstTypeId)) { - if (Type::isInt(srcTypeId)) { + if (TypeUtils::isInt(dstTypeId)) { + if (TypeUtils::isInt(srcTypeId)) { instId = Inst::kIdMovsx; - uint32_t typeOp = (dstTypeId << 8) | srcTypeId; + uint32_t castOp = makeCastOp(dstTypeId, srcTypeId); // Sign extend by using 'movsx'. - if (typeOp == ((Type::kIdI16 << 8) | Type::kIdI8 ) || - typeOp == ((Type::kIdI32 << 8) | Type::kIdI8 ) || - typeOp == ((Type::kIdI32 << 8) | Type::kIdI16) || - typeOp == ((Type::kIdI64 << 8) | Type::kIdI8 ) || - typeOp == ((Type::kIdI64 << 8) | Type::kIdI16)) + if (castOp == makeCastOp(TypeId::kInt16, TypeId::kInt8 ) || + castOp == makeCastOp(TypeId::kInt32, TypeId::kInt8 ) || + castOp == makeCastOp(TypeId::kInt32, TypeId::kInt16) || + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt8 ) || + castOp == makeCastOp(TypeId::kInt64, TypeId::kInt16)) break; // Sign extend by using 'movsxd'. instId = Inst::kIdMovsxd; - if (typeOp == ((Type::kIdI64 << 8) | Type::kIdI32)) + if (castOp == makeCastOp(TypeId::kInt64, TypeId::kInt32)) break; } - if (Type::isInt(srcTypeId) || src_.isMem()) { + if (TypeUtils::isInt(srcTypeId) || src_.isMem()) { // Zero extend by using 'movzx' or 'mov'. if (dstSize <= 4 && srcSize < 4) { instId = Inst::kIdMovzx; - dst.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); } else { - // We should have caught all possibilities where `srcSize` is less - // than 4, so we don't have to worry about 'movzx' anymore. Minimum - // size is enough to determine if we want 32-bit or 64-bit move. + // We should have caught all possibilities where `srcSize` is less than 4, so we don't have to worry + // about 'movzx' anymore. Minimum size is enough to determine if we want 32-bit or 64-bit move. instId = Inst::kIdMov; srcSize = Support::min(srcSize, dstSize); - dst.setSignature(srcSize == 4 ? Reg::signatureOfT<Reg::kTypeGpd>() - : Reg::signatureOfT<Reg::kTypeGpq>()); + dst.setSignature(srcSize == 4 ? Reg::signatureOfT<RegType::kX86_Gpd>() + : Reg::signatureOfT<RegType::kX86_Gpq>()); if (src.isReg()) src.setSignature(dst.signature()); } break; } - // NOTE: The previous branch caught all memory sources, from here it's - // always register to register conversion, so catch the remaining cases. + // NOTE: The previous branch caught all memory sources, from here it's always register to register conversion, + // so catch the remaining cases. srcSize = Support::min(srcSize, dstSize); - if (Type::isMmx(srcTypeId)) { + if (TypeUtils::isMmx(srcTypeId)) { // 64-bit move. instId = Inst::kIdMovq; if (srcSize == 8) @@ -244,18 +228,18 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( // 32-bit move. instId = Inst::kIdMovd; - dst.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); break; } - if (Type::isMask(srcTypeId)) { + if (TypeUtils::isMask(srcTypeId)) { instId = kmovInstFromSize(srcSize); - dst.setSignature(srcSize <= 4 ? Reg::signatureOfT<Reg::kTypeGpd>() - : Reg::signatureOfT<Reg::kTypeGpq>()); + dst.setSignature(srcSize <= 4 ? Reg::signatureOfT<RegType::kX86_Gpd>() + : Reg::signatureOfT<RegType::kX86_Gpq>()); break; } - if (Type::isVec(srcTypeId)) { + if (TypeUtils::isVec(srcTypeId)) { // 64-bit move. instId = _avxEnabled ? Inst::kIdVmovq : Inst::kIdMovq; if (srcSize == 8) @@ -263,16 +247,16 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( // 32-bit move. instId = _avxEnabled ? Inst::kIdVmovd : Inst::kIdMovd; - dst.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); break; } } - if (Type::isMmx(dstTypeId)) { + if (TypeUtils::isMmx(dstTypeId)) { instId = Inst::kIdMovq; srcSize = Support::min(srcSize, dstSize); - if (Type::isInt(srcTypeId) || src.isMem()) { + if (TypeUtils::isInt(srcTypeId) || src.isMem()) { // 64-bit move. if (srcSize == 8) break; @@ -280,33 +264,33 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( // 32-bit move. instId = Inst::kIdMovd; if (src.isReg()) - src.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); break; } - if (Type::isMmx(srcTypeId)) + if (TypeUtils::isMmx(srcTypeId)) break; // This will hurt if AVX is enabled. instId = Inst::kIdMovdq2q; - if (Type::isVec(srcTypeId)) + if (TypeUtils::isVec(srcTypeId)) break; } - if (Type::isMask(dstTypeId)) { + if (TypeUtils::isMask(dstTypeId)) { srcSize = Support::min(srcSize, dstSize); - if (Type::isInt(srcTypeId) || Type::isMask(srcTypeId) || src.isMem()) { + if (TypeUtils::isInt(srcTypeId) || TypeUtils::isMask(srcTypeId) || src.isMem()) { instId = kmovInstFromSize(srcSize); if (Reg::isGp(src) && srcSize <= 4) - src.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); break; } } - if (Type::isVec(dstTypeId)) { + if (TypeUtils::isVec(dstTypeId)) { // By default set destination to XMM, will be set to YMM|ZMM if needed. - dst.setSignature(Reg::signatureOfT<Reg::kTypeXmm>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Xmm>()); // This will hurt if AVX is enabled. if (Reg::isMm(src)) { @@ -316,10 +300,10 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( } // Argument conversion. - uint32_t dstElement = Type::baseOf(dstTypeId); - uint32_t srcElement = Type::baseOf(srcTypeId); + TypeId dstScalarId = TypeUtils::scalarOf(dstTypeId); + TypeId srcScalarId = TypeUtils::scalarOf(srcTypeId); - if (dstElement == Type::kIdF32 && srcElement == Type::kIdF64) { + if (dstScalarId == TypeId::kFloat32 && srcScalarId == TypeId::kFloat64) { srcSize = Support::min(dstSize * 2, srcSize); dstSize = srcSize / 2; @@ -329,13 +313,13 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( instId = _avxEnabled ? Inst::kIdVcvtps2pd : Inst::kIdCvtps2pd; if (dstSize == 32) - dst.setSignature(Reg::signatureOfT<Reg::kTypeYmm>()); + dst.setSignature(Reg::signatureOfT<RegType::kX86_Ymm>()); if (src.isReg()) src.setSignature(Reg::signatureOfVecBySize(srcSize)); break; } - if (dstElement == Type::kIdF64 && srcElement == Type::kIdF32) { + if (dstScalarId == TypeId::kFloat64 && srcScalarId == TypeId::kFloat32) { srcSize = Support::min(dstSize, srcSize * 2) / 2; dstSize = srcSize * 2; @@ -346,7 +330,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( dst.setSignature(Reg::signatureOfVecBySize(dstSize)); if (src.isReg() && srcSize >= 32) - src.setSignature(Reg::signatureOfT<Reg::kTypeYmm>()); + src.setSignature(Reg::signatureOfT<RegType::kX86_Ymm>()); break; } @@ -356,7 +340,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( if (srcSize <= 4) { instId = _avxEnabled ? Inst::kIdVmovd : Inst::kIdMovd; if (src.isReg()) - src.setSignature(Reg::signatureOfT<Reg::kTypeGpd>()); + src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>()); break; } @@ -373,7 +357,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitArgMove( if (src.isMem() && srcSize < _emitter->environment().stackAlignment()) instId = _avxEnabled ? Inst::kIdVmovups : Inst::kIdMovups; - uint32_t signature = Reg::signatureOfVecBySize(srcSize); + OperandSignature signature = Reg::signatureOfVecBySize(srcSize); dst.setSignature(signature); if (src.isReg()) src.setSignature(signature); @@ -403,33 +387,34 @@ Error EmitHelper::emitRegSwap( return DebugUtils::errored(kErrorInvalidState); } -// ============================================================================ -// [asmjit::X86Internal - Emit Prolog & Epilog] -// ============================================================================ +// x86::EmitHelper - Emit Prolog & Epilog +// ====================================== -static ASMJIT_INLINE void X86Internal_setupSaveRestoreInfo(uint32_t group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept { +static inline void X86Internal_setupSaveRestoreInfo(RegGroup group, const FuncFrame& frame, Reg& xReg, uint32_t& xInst, uint32_t& xSize) noexcept { switch (group) { - case Reg::kGroupVec: + case RegGroup::kVec: xReg = xmm(0); xInst = getXmmMovInst(frame); xSize = xReg.size(); break; - case Reg::kGroupMm: + case RegGroup::kX86_K: + xReg = k(0); + xInst = Inst::kIdKmovq; + xSize = xReg.size(); + break; + case RegGroup::kX86_MM: xReg = mm(0); xInst = Inst::kIdMovq; xSize = xReg.size(); break; - case Reg::kGroupKReg: - xReg = k(0); - xInst = Inst::kIdKmovq; - xSize = xReg.size(); + default: break; } } ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { Emitter* emitter = _emitter->as<Emitter>(); - uint32_t gpSaved = frame.savedRegs(Reg::kGroupGp); + uint32_t gpSaved = frame.savedRegs(RegGroup::kGp); Gp zsp = emitter->zsp(); // ESP|RSP register. Gp zbp = emitter->zbp(); // EBP|RBP register. @@ -446,7 +431,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { // Emit: 'push gp' sequence. { - Support::BitWordIterator<uint32_t> it(gpSaved); + Support::BitWordIterator<RegMask> it(gpSaved); while (it.hasNext()) { gpReg.setId(it.next()); ASMJIT_PROPAGATE(emitter->push(gpReg)); @@ -490,8 +475,8 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { uint32_t xInst; uint32_t xSize; - for (uint32_t group = 1; group < BaseReg::kGroupVirt; group++) { - Support::BitWordIterator<uint32_t> it(frame.savedRegs(group)); + for (RegGroup group : Support::EnumValues<RegGroup, RegGroup(1), RegGroup::kMaxVirt>{}) { + Support::BitWordIterator<RegMask> it(frame.savedRegs(group)); if (it.hasNext()) { X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize); do { @@ -513,7 +498,7 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { uint32_t regId; uint32_t registerSize = emitter->registerSize(); - uint32_t gpSaved = frame.savedRegs(Reg::kGroupGp); + uint32_t gpSaved = frame.savedRegs(RegGroup::kGp); Gp zsp = emitter->zsp(); // ESP|RSP register. Gp zbp = emitter->zbp(); // EBP|RBP register. @@ -531,8 +516,8 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { uint32_t xInst; uint32_t xSize; - for (uint32_t group = 1; group < BaseReg::kGroupVirt; group++) { - Support::BitWordIterator<uint32_t> it(frame.savedRegs(group)); + for (RegGroup group : Support::EnumValues<RegGroup, RegGroup(1), RegGroup::kMaxVirt>{}) { + Support::BitWordIterator<RegMask> it(frame.savedRegs(group)); if (it.hasNext()) { X86Internal_setupSaveRestoreInfo(group, frame, xReg, xInst, xSize); do { diff --git a/src/asmjit/x86/x86emithelper_p.h b/src/asmjit/x86/x86emithelper_p.h index dd3b0c9..98d16da 100644 --- a/src/asmjit/x86/x86emithelper_p.h +++ b/src/asmjit/x86/x86emithelper_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86EMITHELPER_P_H_INCLUDED #define ASMJIT_X86_X86EMITHELPER_P_H_INCLUDED @@ -37,13 +19,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::EmitHelper] -// ============================================================================ - -static ASMJIT_INLINE uint32_t vecTypeIdToRegType(uint32_t typeId) noexcept { - return typeId <= Type::_kIdVec128End ? Reg::kTypeXmm : - typeId <= Type::_kIdVec256End ? Reg::kTypeYmm : Reg::kTypeZmm; +static inline RegType vecTypeIdToRegType(TypeId typeId) noexcept { + return uint32_t(typeId) <= uint32_t(TypeId::_kVec128End) ? RegType::kX86_Xmm : + uint32_t(typeId) <= uint32_t(TypeId::_kVec256End) ? RegType::kX86_Ymm : RegType::kX86_Zmm; } class EmitHelper : public BaseEmitHelper { @@ -58,11 +36,11 @@ public: Error emitRegMove( const Operand_& dst_, - const Operand_& src_, uint32_t typeId, const char* comment = nullptr) override; + const Operand_& src_, TypeId typeId, const char* comment = nullptr) override; Error emitArgMove( - const BaseReg& dst_, uint32_t dstTypeId, - const Operand_& src_, uint32_t srcTypeId, const char* comment = nullptr) override; + const BaseReg& dst_, TypeId dstTypeId, + const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) override; Error emitRegSwap( const BaseReg& a, diff --git a/src/asmjit/x86/x86emitter.h b/src/asmjit/x86/x86emitter.h index 24f2fb6..1f85dec 100644 --- a/src/asmjit/x86/x86emitter.h +++ b/src/asmjit/x86/x86emitter.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86EMITTER_H_INCLUDED #define ASMJIT_X86_X86EMITTER_H_INCLUDED @@ -38,7 +20,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) inline Error NAME(const T0& o0) { return _emitter()->_emitI(Inst::kId##ID, o0); } #define ASMJIT_INST_1c(NAME, ID, CONV, T0) \ - inline Error NAME(uint32_t cc, const T0& o0) { return _emitter()->_emitI(CONV(cc), o0); } \ + inline Error NAME(CondCode cc, const T0& o0) { return _emitter()->_emitI(CONV(cc), o0); } \ inline Error NAME##a(const T0& o0) { return _emitter()->_emitI(Inst::kId##ID##a, o0); } \ inline Error NAME##ae(const T0& o0) { return _emitter()->_emitI(Inst::kId##ID##ae, o0); } \ inline Error NAME##b(const T0& o0) { return _emitter()->_emitI(Inst::kId##ID##b, o0); } \ @@ -74,7 +56,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) inline Error NAME(const T0& o0, const T1& o1) { return _emitter()->_emitI(Inst::kId##ID, o0, o1); } #define ASMJIT_INST_2c(NAME, ID, CONV, T0, T1) \ - inline Error NAME(uint32_t cc, const T0& o0, const T1& o1) { return _emitter()->_emitI(CONV(cc), o0, o1); } \ + inline Error NAME(CondCode cc, const T0& o0, const T1& o1) { return _emitter()->_emitI(CONV(cc), o0, o1); } \ inline Error NAME##a(const T0& o0, const T1& o1) { return _emitter()->_emitI(Inst::kId##ID##a, o0, o1); } \ inline Error NAME##ae(const T0& o0, const T1& o1) { return _emitter()->_emitI(Inst::kId##ID##ae, o0, o1); } \ inline Error NAME##b(const T0& o0, const T1& o1) { return _emitter()->_emitI(Inst::kId##ID##b, o0, o1); } \ @@ -121,10 +103,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::EmitterExplicitT] -// ============================================================================ - //! Emitter (X86 - explicit). template<typename This> struct EmitterExplicitT { @@ -159,9 +137,8 @@ struct EmitterExplicitT { typedef Xmm XMM0; - // These two are unfortunately reported by the sanitizer. We know what we do, - // however, the sanitizer doesn't. I have tried to use reinterpret_cast instead, - // but that would generate bad code when compiled by MSC. + // These two are unfortunately reported by the sanitizer. We know what we do, however, the sanitizer doesn't. + // I have tried to use reinterpret_cast instead, but that would generate bad code when compiled by MSC. ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline This* _emitter() noexcept { return static_cast<This*>(this); } ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline const This* _emitter() const noexcept { return static_cast<const This*>(this); } @@ -171,16 +148,16 @@ struct EmitterExplicitT { //! \{ //! Returns either GPD or GPQ register of the given `id` depending on the emitter's architecture. - inline Gp gpz(uint32_t id) const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), id); } + inline Gp gpz(uint32_t id) const noexcept { return Gp(_emitter()->_gpSignature, id); } - inline Gp zax() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdAx); } - inline Gp zcx() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdCx); } - inline Gp zdx() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdDx); } - inline Gp zbx() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdBx); } - inline Gp zsp() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdSp); } - inline Gp zbp() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdBp); } - inline Gp zsi() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdSi); } - inline Gp zdi() const noexcept { return Gp::fromSignatureAndId(_emitter()->_gpRegInfo.signature(), Gp::kIdDi); } + inline Gp zax() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdAx); } + inline Gp zcx() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdCx); } + inline Gp zdx() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdDx); } + inline Gp zbx() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdBx); } + inline Gp zsp() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdSp); } + inline Gp zbp() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdBp); } + inline Gp zsi() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdSi); } + inline Gp zdi() const noexcept { return Gp(_emitter()->_gpSignature, Gp::kIdDi); } //! \} @@ -189,7 +166,10 @@ struct EmitterExplicitT { //! Creates a target dependent pointer of which base register's id is `baseId`. inline Mem ptr_base(uint32_t baseId, int32_t off = 0, uint32_t size = 0) const noexcept { - return Mem(Mem::Decomposed { _emitter()->_gpRegInfo.type(), baseId, 0, 0, off, size, 0 }); + return Mem(OperandSignature::fromOpType(OperandType::kMem) | + OperandSignature::fromMemBaseType(_emitter()->_gpSignature.regType()) | + OperandSignature::fromSize(size), + baseId, 0, off); } inline Mem ptr_zax(int32_t off = 0, uint32_t size = 0) const noexcept { return ptr_base(Gp::kIdAx, off, size); } @@ -249,12 +229,12 @@ struct EmitterExplicitT { //! \overload inline Mem intptr_ptr_abs(uint64_t base) const noexcept { uint32_t nativeGpSize = _emitter()->registerSize(); - return Mem(base, nativeGpSize, Mem::kSignatureMemAbs); + return Mem(base, nativeGpSize, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! \overload inline Mem intptr_ptr_abs(uint64_t base, const Gp& index, uint32_t shift = 0) const noexcept { uint32_t nativeGpSize = _emitter()->registerSize(); - return Mem(base, index, shift, nativeGpSize, Mem::kSignatureMemAbs); + return Mem(base, index, shift, nativeGpSize, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } //! \} @@ -271,47 +251,6 @@ struct EmitterExplicitT { //! Embeds 64-bit integer data. inline Error dq(uint64_t x, size_t repeatCount = 1) { return _emitter()->embedUInt64(x, repeatCount); } -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use embedInt8() instead of dint8()") - inline Error dint8(int8_t x) { return _emitter()->embed(&x, sizeof(int8_t)); } - - ASMJIT_DEPRECATED("Use embedUInt8() instead of duint8()") - inline Error duint8(uint8_t x) { return _emitter()->embed(&x, sizeof(uint8_t)); } - - ASMJIT_DEPRECATED("Use embedInt16() instead of dint16()") - inline Error dint16(int16_t x) { return _emitter()->embed(&x, sizeof(int16_t)); } - - ASMJIT_DEPRECATED("Use embedUInt16() instead of duint16()") - inline Error duint16(uint16_t x) { return _emitter()->embed(&x, sizeof(uint16_t)); } - - ASMJIT_DEPRECATED("Use embedInt32() instead of dint32()") - inline Error dint32(int32_t x) { return _emitter()->embed(&x, sizeof(int32_t)); } - - ASMJIT_DEPRECATED("Use embedUInt32() instead of duint32()") - inline Error duint32(uint32_t x) { return _emitter()->embed(&x, sizeof(uint32_t)); } - - ASMJIT_DEPRECATED("Use embedInt64() instead of dint64()") - inline Error dint64(int64_t x) { return _emitter()->embed(&x, sizeof(int64_t)); } - - ASMJIT_DEPRECATED("Use embedUInt64() instead of duint64()") - inline Error duint64(uint64_t x) { return _emitter()->embed(&x, sizeof(uint64_t)); } - - ASMJIT_DEPRECATED("Use embedFloat() instead of float()") - inline Error dfloat(float x) { return _emitter()->embed(&x, sizeof(float)); } - - ASMJIT_DEPRECATED("Use embedDouble() instead of ddouble()") - inline Error ddouble(double x) { return _emitter()->embed(&x, sizeof(double)); } - - ASMJIT_DEPRECATED("Use embed[U]IntN() or embed[Float|Double]() instead of dmm()") - inline Error dmm(const Data64& x) { return _emitter()->embed(&x, 8); } - - ASMJIT_DEPRECATED("Use embed[U]IntN() or embed[Float|Double]() instead of dxmm()") - inline Error dxmm(const Data128& x) { return _emitter()->embed(&x, 16); } - - ASMJIT_DEPRECATED("Use embed[U]IntN() or embed[Float|Double]() instead of dymm()") - inline Error dymm(const Data256& x) { return _emitter()->embed(&x, 32); } -#endif // !ASMJIT_NO_DEPRECATED - //! Adds data in a given structure instance to the CodeBuffer. template<typename T> inline Error dstruct(const T& x) { return _emitter()->embed(&x, uint32_t(sizeof(T))); } @@ -320,7 +259,7 @@ struct EmitterExplicitT { protected: //! \cond - inline This& _addInstOptions(uint32_t options) noexcept { + inline This& _addInstOptions(InstOptions options) noexcept { _emitter()->addInstOptions(options); return *_emitter(); } @@ -331,9 +270,9 @@ public: //! \{ //! Force short form of jmp/jcc instruction. - inline This& short_() noexcept { return _addInstOptions(Inst::kOptionShortForm); } + inline This& short_() noexcept { return _addInstOptions(InstOptions::kShortForm); } //! Force long form of jmp/jcc instruction. - inline This& long_() noexcept { return _addInstOptions(Inst::kOptionLongForm); } + inline This& long_() noexcept { return _addInstOptions(InstOptions::kLongForm); } //! \} @@ -341,10 +280,10 @@ public: //! \{ //! Prefer MOD/RM encoding when both MOD/RM and MOD/MR forms are applicable. - inline This& mod_rm() noexcept { return _addInstOptions(Inst::kOptionModRM); } + inline This& mod_rm() noexcept { return _addInstOptions(InstOptions::kX86_ModRM); } //! Prefer MOD/MR encoding when both MOD/RM and MOD/MR forms are applicable. - inline This& mod_mr() noexcept { return _addInstOptions(Inst::kOptionModMR); } + inline This& mod_mr() noexcept { return _addInstOptions(InstOptions::kX86_ModMR); } //! \} @@ -352,28 +291,28 @@ public: //! \{ //! Condition is likely to be taken (has only benefit on P4). - inline This& taken() noexcept { return _addInstOptions(Inst::kOptionTaken); } + inline This& taken() noexcept { return _addInstOptions(InstOptions::kTaken); } //! Condition is unlikely to be taken (has only benefit on P4). - inline This& notTaken() noexcept { return _addInstOptions(Inst::kOptionNotTaken); } + inline This& notTaken() noexcept { return _addInstOptions(InstOptions::kNotTaken); } //! Use LOCK prefix. - inline This& lock() noexcept { return _addInstOptions(Inst::kOptionLock); } + inline This& lock() noexcept { return _addInstOptions(InstOptions::kX86_Lock); } //! Use XACQUIRE prefix. - inline This& xacquire() noexcept { return _addInstOptions(Inst::kOptionXAcquire); } + inline This& xacquire() noexcept { return _addInstOptions(InstOptions::kX86_XAcquire); } //! Use XRELEASE prefix. - inline This& xrelease() noexcept { return _addInstOptions(Inst::kOptionXRelease); } + inline This& xrelease() noexcept { return _addInstOptions(InstOptions::kX86_XRelease); } //! Use BND/REPNE prefix. //! //! \note This is the same as using `repne()` or `repnz()` prefix. - inline This& bnd() noexcept { return _addInstOptions(Inst::kOptionRepne); } + inline This& bnd() noexcept { return _addInstOptions(InstOptions::kX86_Repne); } //! Use REP/REPZ prefix. //! //! \note This is the same as using `repe()` or `repz()` prefix. inline This& rep(const Gp& zcx) noexcept { _emitter()->_extraReg.init(zcx); - return _addInstOptions(Inst::kOptionRep); + return _addInstOptions(InstOptions::kX86_Rep); } //! Use REP/REPE prefix. @@ -391,7 +330,7 @@ public: //! \note This is the same as using `bnd()` or `repnz()` prefix. inline This& repne(const Gp& zcx) noexcept { _emitter()->_extraReg.init(zcx); - return _addInstOptions(Inst::kOptionRepne); + return _addInstOptions(InstOptions::kX86_Repne); } //! Use REPNE prefix. @@ -406,18 +345,18 @@ public: //! Force REX prefix to be emitted even when it's not needed (X86_64). //! - //! \note Don't use when using high 8-bit registers as REX prefix makes them - //! inaccessible and `x86::Assembler` would fail to encode such instruction. - inline This& rex() noexcept { return _addInstOptions(Inst::kOptionRex); } + //! \note Don't use when using high 8-bit registers as REX prefix makes them inaccessible and `x86::Assembler` + //! would fail to encode such instruction. + inline This& rex() noexcept { return _addInstOptions(InstOptions::kX86_Rex); } //! Force REX.B prefix (X64) [It exists for special purposes only]. - inline This& rex_b() noexcept { return _addInstOptions(Inst::kOptionOpCodeB); } + inline This& rex_b() noexcept { return _addInstOptions(InstOptions::kX86_OpCodeB); } //! Force REX.X prefix (X64) [It exists for special purposes only]. - inline This& rex_x() noexcept { return _addInstOptions(Inst::kOptionOpCodeX); } + inline This& rex_x() noexcept { return _addInstOptions(InstOptions::kX86_OpCodeX); } //! Force REX.R prefix (X64) [It exists for special purposes only]. - inline This& rex_r() noexcept { return _addInstOptions(Inst::kOptionOpCodeR); } + inline This& rex_r() noexcept { return _addInstOptions(InstOptions::kX86_OpCodeR); } //! Force REX.W prefix (X64) [It exists for special purposes only]. - inline This& rex_w() noexcept { return _addInstOptions(Inst::kOptionOpCodeW); } + inline This& rex_w() noexcept { return _addInstOptions(InstOptions::kX86_OpCodeW); } //! \} @@ -425,11 +364,11 @@ public: //! \{ //! Use VEX prefix instead of EVEX prefix (useful to select AVX_VNNI instruction instead of AVX512_VNNI). - inline This& vex() noexcept { return _addInstOptions(Inst::kOptionVex); } + inline This& vex() noexcept { return _addInstOptions(InstOptions::kX86_Vex); } //! Force 3-byte VEX prefix (AVX+). - inline This& vex3() noexcept { return _addInstOptions(Inst::kOptionVex3); } + inline This& vex3() noexcept { return _addInstOptions(InstOptions::kX86_Vex3); } //! Force 4-byte EVEX prefix (AVX512+). - inline This& evex() noexcept { return _addInstOptions(Inst::kOptionEvex); } + inline This& evex() noexcept { return _addInstOptions(InstOptions::kX86_Evex); } //! \} @@ -443,18 +382,18 @@ public: } //! Use zeroing instead of merging (AVX512+). - inline This& z() noexcept { return _addInstOptions(Inst::kOptionZMask); } + inline This& z() noexcept { return _addInstOptions(InstOptions::kX86_ZMask); } //! Suppress all exceptions (AVX512+). - inline This& sae() noexcept { return _addInstOptions(Inst::kOptionSAE); } + inline This& sae() noexcept { return _addInstOptions(InstOptions::kX86_SAE); } //! Static rounding mode {rn} (round-to-nearest even) and {sae} (AVX512+). - inline This& rn_sae() noexcept { return _addInstOptions(Inst::kOptionER | Inst::kOptionRN_SAE); } + inline This& rn_sae() noexcept { return _addInstOptions(InstOptions::kX86_ER | InstOptions::kX86_RN_SAE); } //! Static rounding mode {rd} (round-down, toward -inf) and {sae} (AVX512+). - inline This& rd_sae() noexcept { return _addInstOptions(Inst::kOptionER | Inst::kOptionRD_SAE); } + inline This& rd_sae() noexcept { return _addInstOptions(InstOptions::kX86_ER | InstOptions::kX86_RD_SAE); } //! Static rounding mode {ru} (round-up, toward +inf) and {sae} (AVX512+). - inline This& ru_sae() noexcept { return _addInstOptions(Inst::kOptionER | Inst::kOptionRU_SAE); } + inline This& ru_sae() noexcept { return _addInstOptions(InstOptions::kX86_ER | InstOptions::kX86_RU_SAE); } //! Static rounding mode {rz} (round-toward-zero, truncate) and {sae} (AVX512+). - inline This& rz_sae() noexcept { return _addInstOptions(Inst::kOptionER | Inst::kOptionRZ_SAE); } + inline This& rz_sae() noexcept { return _addInstOptions(InstOptions::kX86_ER | InstOptions::kX86_RZ_SAE); } //! \} @@ -508,8 +447,8 @@ public: ASMJIT_INST_1x(call, Call, Mem) // ANY ASMJIT_INST_1x(call, Call, Label) // ANY ASMJIT_INST_1x(call, Call, Imm) // ANY - ASMJIT_INST_2c(cmov, Cmov, Condition::toCmovcc, Gp, Gp) // CMOV - ASMJIT_INST_2c(cmov, Cmov, Condition::toCmovcc, Gp, Mem) // CMOV + ASMJIT_INST_2c(cmov, Cmov, Inst::cmovccFromCond, Gp, Gp) // CMOV + ASMJIT_INST_2c(cmov, Cmov, Inst::cmovccFromCond, Gp, Mem) // CMOV ASMJIT_INST_2x(cmp, Cmp, Gp, Gp) // ANY ASMJIT_INST_2x(cmp, Cmp, Gp, Mem) // ANY ASMJIT_INST_2x(cmp, Cmp, Gp, Imm) // ANY @@ -539,8 +478,8 @@ public: ASMJIT_INST_3x(imul, Imul, Gp, Gp, Mem) // ANY [EXPLICIT] xDX:xAX <- xAX * m16|m32|m64 ASMJIT_INST_1x(inc, Inc, Gp) // ANY ASMJIT_INST_1x(inc, Inc, Mem) // ANY - ASMJIT_INST_1c(j, J, Condition::toJcc, Label) // ANY - ASMJIT_INST_1c(j, J, Condition::toJcc, Imm) // ANY + ASMJIT_INST_1c(j, J, Inst::jccFromCond, Label) // ANY + ASMJIT_INST_1c(j, J, Inst::jccFromCond, Imm) // ANY ASMJIT_INST_2x(jecxz, Jecxz, Gp, Label) // ANY [EXPLICIT] Short jump if CX/ECX/RCX is zero. ASMJIT_INST_2x(jecxz, Jecxz, Gp, Imm) // ANY [EXPLICIT] Short jump if CX/ECX/RCX is zero. ASMJIT_INST_1x(jmp, Jmp, Gp) // ANY @@ -648,8 +587,8 @@ public: ASMJIT_INST_2x(sar, Sar, Gp, Imm) // ANY ASMJIT_INST_2x(sar, Sar, Mem, Imm) // ANY ASMJIT_INST_2x(scas, Scas, Gp_ZAX, ES_ZDI) // ANY [EXPLICIT] - ASMJIT_INST_1c(set, Set, Condition::toSetcc, Gp) // ANY - ASMJIT_INST_1c(set, Set, Condition::toSetcc, Mem) // ANY + ASMJIT_INST_1c(set, Set, Inst::setccFromCond, Gp) // ANY + ASMJIT_INST_1c(set, Set, Inst::setccFromCond, Mem) // ANY ASMJIT_INST_2x(shl, Shl, Gp, Gp_CL) // ANY ASMJIT_INST_2x(shl, Shl, Mem, Gp_CL) // ANY ASMJIT_INST_2x(shl, Shl, Gp, Imm) // ANY @@ -3720,6 +3659,227 @@ public: //! \} + //! \name AVX512_FP16 Instructions + //! \{ + + ASMJIT_INST_3x(vaddph, Vaddph, Vec, Vec, Vec) + ASMJIT_INST_3x(vaddph, Vaddph, Vec, Vec, Mem) + ASMJIT_INST_3x(vaddsh, Vaddsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vaddsh, Vaddsh, Vec, Vec, Mem) + ASMJIT_INST_4x(vcmpph, Vcmpph, KReg, Vec, Vec, Imm) + ASMJIT_INST_4x(vcmpph, Vcmpph, KReg, Vec, Mem, Imm) + ASMJIT_INST_4x(vcmpsh, Vcmpsh, KReg, Vec, Vec, Imm) + ASMJIT_INST_4x(vcmpsh, Vcmpsh, KReg, Vec, Mem, Imm) + ASMJIT_INST_2x(vcomish, Vcomish, Vec, Vec) + ASMJIT_INST_2x(vcomish, Vcomish, Vec, Mem) + ASMJIT_INST_2x(vcvtdq2ph, Vcvtdq2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtdq2ph, Vcvtdq2ph, Vec, Mem) + ASMJIT_INST_2x(vcvtpd2ph, Vcvtpd2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtpd2ph, Vcvtpd2ph, Vec, Mem) + ASMJIT_INST_2x(vcvtph2dq, Vcvtph2dq, Vec, Vec) + ASMJIT_INST_2x(vcvtph2dq, Vcvtph2dq, Vec, Mem) + ASMJIT_INST_2x(vcvtph2pd, Vcvtph2pd, Vec, Vec) + ASMJIT_INST_2x(vcvtph2pd, Vcvtph2pd, Vec, Mem) + ASMJIT_INST_2x(vcvtph2psx, Vcvtph2psx, Vec, Vec) + ASMJIT_INST_2x(vcvtph2psx, Vcvtph2psx, Vec, Mem) + ASMJIT_INST_2x(vcvtph2qq, Vcvtph2qq, Vec, Vec) + ASMJIT_INST_2x(vcvtph2qq, Vcvtph2qq, Vec, Mem) + ASMJIT_INST_2x(vcvtph2udq, Vcvtph2udq, Vec, Vec) + ASMJIT_INST_2x(vcvtph2udq, Vcvtph2udq, Vec, Mem) + ASMJIT_INST_2x(vcvtph2uqq, Vcvtph2uqq, Vec, Vec) + ASMJIT_INST_2x(vcvtph2uqq, Vcvtph2uqq, Vec, Mem) + ASMJIT_INST_2x(vcvtph2uw, Vcvtph2uw, Vec, Vec) + ASMJIT_INST_2x(vcvtph2uw, Vcvtph2uw, Vec, Mem) + ASMJIT_INST_2x(vcvtph2w, Vcvtph2w, Vec, Vec) + ASMJIT_INST_2x(vcvtph2w, Vcvtph2w, Vec, Mem) + ASMJIT_INST_2x(vcvtps2phx, Vcvtps2phx, Vec, Vec) + ASMJIT_INST_2x(vcvtps2phx, Vcvtps2phx, Vec, Mem) + ASMJIT_INST_2x(vcvtqq2ph, Vcvtqq2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtqq2ph, Vcvtqq2ph, Vec, Mem) + ASMJIT_INST_3x(vcvtsd2sh, Vcvtsd2sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vcvtsd2sh, Vcvtsd2sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vcvtsh2sd, Vcvtsh2sd, Vec, Vec, Vec) + ASMJIT_INST_3x(vcvtsh2sd, Vcvtsh2sd, Vec, Vec, Mem) + ASMJIT_INST_2x(vcvtsh2si, Vcvtsh2si, Gp, Vec) + ASMJIT_INST_2x(vcvtsh2si, Vcvtsh2si, Gp, Mem) + ASMJIT_INST_3x(vcvtsh2ss, Vcvtsh2ss, Vec, Vec, Vec) + ASMJIT_INST_3x(vcvtsh2ss, Vcvtsh2ss, Vec, Vec, Mem) + ASMJIT_INST_2x(vcvtsh2usi, Vcvtsh2usi, Gp, Vec) + ASMJIT_INST_2x(vcvtsh2usi, Vcvtsh2usi, Gp, Mem) + ASMJIT_INST_3x(vcvtsi2sh, Vcvtsi2sh, Vec, Vec, Gp) + ASMJIT_INST_3x(vcvtsi2sh, Vcvtsi2sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vcvtss2sh, Vcvtss2sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vcvtss2sh, Vcvtss2sh, Vec, Vec, Mem) + ASMJIT_INST_2x(vcvttph2dq, Vcvttph2dq, Vec, Vec) + ASMJIT_INST_2x(vcvttph2dq, Vcvttph2dq, Vec, Mem) + ASMJIT_INST_2x(vcvttph2qq, Vcvttph2qq, Vec, Vec) + ASMJIT_INST_2x(vcvttph2qq, Vcvttph2qq, Vec, Mem) + ASMJIT_INST_2x(vcvttph2udq, Vcvttph2udq, Vec, Vec) + ASMJIT_INST_2x(vcvttph2udq, Vcvttph2udq, Vec, Mem) + ASMJIT_INST_2x(vcvttph2uqq, Vcvttph2uqq, Vec, Vec) + ASMJIT_INST_2x(vcvttph2uqq, Vcvttph2uqq, Vec, Mem) + ASMJIT_INST_2x(vcvttph2uw, Vcvttph2uw, Vec, Vec) + ASMJIT_INST_2x(vcvttph2uw, Vcvttph2uw, Vec, Mem) + ASMJIT_INST_2x(vcvttph2w, Vcvttph2w, Vec, Vec) + ASMJIT_INST_2x(vcvttph2w, Vcvttph2w, Vec, Mem) + ASMJIT_INST_2x(vcvttsh2si, Vcvttsh2si, Gp, Vec) + ASMJIT_INST_2x(vcvttsh2si, Vcvttsh2si, Gp, Mem) + ASMJIT_INST_2x(vcvttsh2usi, Vcvttsh2usi, Gp, Vec) + ASMJIT_INST_2x(vcvttsh2usi, Vcvttsh2usi, Gp, Mem) + ASMJIT_INST_2x(vcvtudq2ph, Vcvtudq2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtudq2ph, Vcvtudq2ph, Vec, Mem) + ASMJIT_INST_2x(vcvtuqq2ph, Vcvtuqq2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtuqq2ph, Vcvtuqq2ph, Vec, Mem) + ASMJIT_INST_3x(vcvtusi2sh, Vcvtusi2sh, Vec, Vec, Gp) + ASMJIT_INST_3x(vcvtusi2sh, Vcvtusi2sh, Vec, Vec, Mem) + ASMJIT_INST_2x(vcvtuw2ph, Vcvtuw2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtuw2ph, Vcvtuw2ph, Vec, Mem) + ASMJIT_INST_2x(vcvtw2ph, Vcvtw2ph, Vec, Vec) + ASMJIT_INST_2x(vcvtw2ph, Vcvtw2ph, Vec, Mem) + ASMJIT_INST_3x(vdivph, Vdivph, Vec, Vec, Vec) + ASMJIT_INST_3x(vdivph, Vdivph, Vec, Vec, Mem) + ASMJIT_INST_3x(vdivsh, Vdivsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vdivsh, Vdivsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfcmaddcph, Vfcmaddcph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfcmaddcph, Vfcmaddcph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfcmaddcsh, Vfcmaddcsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfcmaddcsh, Vfcmaddcsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfcmulcph, Vfcmulcph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfcmulcph, Vfcmulcph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfcmulcsh, Vfcmulcsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfcmulcsh, Vfcmulcsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmadd132ph, Vfmadd132ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmadd132ph, Vfmadd132ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmadd132sh, Vfmadd132sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmadd132sh, Vfmadd132sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmadd213ph, Vfmadd213ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmadd213ph, Vfmadd213ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmadd213sh, Vfmadd213sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmadd213sh, Vfmadd213sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmadd231ph, Vfmadd231ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmadd231ph, Vfmadd231ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmadd231sh, Vfmadd231sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmadd231sh, Vfmadd231sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmaddcph, Vfmaddcph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmaddcph, Vfmaddcph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmaddcsh, Vfmaddcsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmaddcsh, Vfmaddcsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmaddsub132ph, Vfmaddsub132ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmaddsub132ph, Vfmaddsub132ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmaddsub213ph, Vfmaddsub213ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmaddsub213ph, Vfmaddsub213ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmaddsub231ph, Vfmaddsub231ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmaddsub231ph, Vfmaddsub231ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsub132ph, Vfmsub132ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsub132ph, Vfmsub132ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsub132sh, Vfmsub132sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsub132sh, Vfmsub132sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsub213ph, Vfmsub213ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsub213ph, Vfmsub213ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsub213sh, Vfmsub213sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsub213sh, Vfmsub213sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsub231ph, Vfmsub231ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsub231ph, Vfmsub231ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsub231sh, Vfmsub231sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsub231sh, Vfmsub231sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsubadd132ph, Vfmsubadd132ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsubadd132ph, Vfmsubadd132ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsubadd213ph, Vfmsubadd213ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsubadd213ph, Vfmsubadd213ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmsubadd231ph, Vfmsubadd231ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmsubadd231ph, Vfmsubadd231ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmulcph, Vfmulcph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmulcph, Vfmulcph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfmulcsh, Vfmulcsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfmulcsh, Vfmulcsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmadd132ph, Vfnmadd132ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmadd132ph, Vfnmadd132ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmadd132sh, Vfnmadd132sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmadd132sh, Vfnmadd132sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmadd213ph, Vfnmadd213ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmadd213ph, Vfnmadd213ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmadd213sh, Vfnmadd213sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmadd213sh, Vfnmadd213sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmadd231ph, Vfnmadd231ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmadd231ph, Vfnmadd231ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmadd231sh, Vfnmadd231sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmadd231sh, Vfnmadd231sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmsub132ph, Vfnmsub132ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmsub132ph, Vfnmsub132ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmsub132sh, Vfnmsub132sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmsub132sh, Vfnmsub132sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmsub213ph, Vfnmsub213ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmsub213ph, Vfnmsub213ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmsub213sh, Vfnmsub213sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmsub213sh, Vfnmsub213sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmsub231ph, Vfnmsub231ph, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmsub231ph, Vfnmsub231ph, Vec, Vec, Mem) + ASMJIT_INST_3x(vfnmsub231sh, Vfnmsub231sh, Vec, Vec, Vec) + ASMJIT_INST_3x(vfnmsub231sh, Vfnmsub231sh, Vec, Vec, Mem) + ASMJIT_INST_3x(vfpclassph, Vfpclassph, KReg, Vec, Imm) + ASMJIT_INST_3x(vfpclassph, Vfpclassph, KReg, Mem, Imm) + ASMJIT_INST_3x(vfpclasssh, Vfpclasssh, KReg, Vec, Imm) + ASMJIT_INST_3x(vfpclasssh, Vfpclasssh, KReg, Mem, Imm) + ASMJIT_INST_2x(vgetexpph, Vgetexpph, Vec, Vec) + ASMJIT_INST_2x(vgetexpph, Vgetexpph, Vec, Mem) + ASMJIT_INST_3x(vgetexpsh, Vgetexpsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vgetexpsh, Vgetexpsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vgetmantph, Vgetmantph, Vec, Vec, Imm) + ASMJIT_INST_3x(vgetmantph, Vgetmantph, Vec, Mem, Imm) + ASMJIT_INST_4x(vgetmantsh, Vgetmantsh, Vec, Vec, Vec, Imm) + ASMJIT_INST_4x(vgetmantsh, Vgetmantsh, Vec, Vec, Mem, Imm) + ASMJIT_INST_3x(vmaxph, Vmaxph, Vec, Vec, Vec) + ASMJIT_INST_3x(vmaxph, Vmaxph, Vec, Vec, Mem) + ASMJIT_INST_3x(vmaxsh, Vmaxsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vmaxsh, Vmaxsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vminph, Vminph, Vec, Vec, Vec) + ASMJIT_INST_3x(vminph, Vminph, Vec, Vec, Mem) + ASMJIT_INST_3x(vminsh, Vminsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vminsh, Vminsh, Vec, Vec, Mem) + ASMJIT_INST_2x(vmovsh, Vmovsh, Mem, Xmm) + ASMJIT_INST_2x(vmovsh, Vmovsh, Xmm, Mem) + ASMJIT_INST_3x(vmovsh, Vmovsh, Xmm, Xmm, Xmm) + ASMJIT_INST_2x(vmovw, Vmovw, Gp, Xmm) + ASMJIT_INST_2x(vmovw, Vmovw, Mem, Xmm) + ASMJIT_INST_2x(vmovw, Vmovw, Xmm, Gp) + ASMJIT_INST_2x(vmovw, Vmovw, Xmm, Mem) + ASMJIT_INST_3x(vmulph, Vmulph, Vec, Vec, Vec) + ASMJIT_INST_3x(vmulph, Vmulph, Vec, Vec, Mem) + ASMJIT_INST_3x(vmulsh, Vmulsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vmulsh, Vmulsh, Vec, Vec, Mem) + ASMJIT_INST_2x(vrcpph, Vrcpph, Vec, Vec) + ASMJIT_INST_2x(vrcpph, Vrcpph, Vec, Mem) + ASMJIT_INST_3x(vrcpsh, Vrcpsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vrcpsh, Vrcpsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vreduceph, Vreduceph, Vec, Vec, Imm) + ASMJIT_INST_3x(vreduceph, Vreduceph, Vec, Mem, Imm) + ASMJIT_INST_4x(vreducesh, Vreducesh, Vec, Vec, Vec, Imm) + ASMJIT_INST_4x(vreducesh, Vreducesh, Vec, Vec, Mem, Imm) + ASMJIT_INST_3x(vrndscaleph, Vrndscaleph, Vec, Vec, Imm) + ASMJIT_INST_3x(vrndscaleph, Vrndscaleph, Vec, Mem, Imm) + ASMJIT_INST_4x(vrndscalesh, Vrndscalesh, Vec, Vec, Vec, Imm) + ASMJIT_INST_4x(vrndscalesh, Vrndscalesh, Vec, Vec, Mem, Imm) + ASMJIT_INST_2x(vrsqrtph, Vrsqrtph, Vec, Vec) + ASMJIT_INST_2x(vrsqrtph, Vrsqrtph, Vec, Mem) + ASMJIT_INST_3x(vrsqrtsh, Vrsqrtsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vrsqrtsh, Vrsqrtsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vscalefph, Vscalefph, Vec, Vec, Vec) + ASMJIT_INST_3x(vscalefph, Vscalefph, Vec, Vec, Mem) + ASMJIT_INST_3x(vscalefsh, Vscalefsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vscalefsh, Vscalefsh, Vec, Vec, Mem) + ASMJIT_INST_2x(vsqrtph, Vsqrtph, Vec, Vec) + ASMJIT_INST_2x(vsqrtph, Vsqrtph, Vec, Mem) + ASMJIT_INST_3x(vsqrtsh, Vsqrtsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vsqrtsh, Vsqrtsh, Vec, Vec, Mem) + ASMJIT_INST_3x(vsubph, Vsubph, Vec, Vec, Vec) + ASMJIT_INST_3x(vsubph, Vsubph, Vec, Vec, Mem) + ASMJIT_INST_3x(vsubsh, Vsubsh, Vec, Vec, Vec) + ASMJIT_INST_3x(vsubsh, Vsubsh, Vec, Vec, Mem) + ASMJIT_INST_2x(vucomish, Vucomish, Vec, Vec) + ASMJIT_INST_2x(vucomish, Vucomish, Vec, Mem) + + //! \} + //! \name AMX Instructions //! \{ @@ -3740,10 +3900,6 @@ public: //! \} }; -// ============================================================================ -// [asmjit::x86::EmitterImplicitT] -// ============================================================================ - //! Emitter (X86 - implicit). template<typename This> struct EmitterImplicitT : public EmitterExplicitT<This> { @@ -3755,14 +3911,14 @@ struct EmitterImplicitT : public EmitterExplicitT<This> { //! \{ //! Use REP/REPE prefix. - inline This& rep() noexcept { return EmitterExplicitT<This>::_addInstOptions(Inst::kOptionRep); } + inline This& rep() noexcept { return EmitterExplicitT<This>::_addInstOptions(InstOptions::kX86_Rep); } //! Use REP/REPE prefix. inline This& repe() noexcept { return rep(); } //! Use REP/REPE prefix. inline This& repz() noexcept { return rep(); } //! Use REPNE prefix. - inline This& repne() noexcept { return EmitterExplicitT<This>::_addInstOptions(Inst::kOptionRepne); } + inline This& repne() noexcept { return EmitterExplicitT<This>::_addInstOptions(InstOptions::kX86_Repne); } //! Use REPNE prefix. inline This& repnz() noexcept { return repne(); } @@ -4133,16 +4289,11 @@ struct EmitterImplicitT : public EmitterExplicitT<This> { //! \} }; -// ============================================================================ -// [asmjit::x86::Emitter] -// ============================================================================ - //! Emitter (X86). //! -//! \note This class cannot be instantiated, you can only cast to it and use -//! it as emitter that emits to either `x86::Assembler`, `x86::Builder`, or -//! `x86::Compiler` (use with caution with `x86::Compiler` as it requires virtual -//! registers). +//! \note This class cannot be instantiated, you can only cast to it and use it as emitter that emits to either +//! `x86::Assembler`, `x86::Builder`, or `x86::Compiler` (use with caution with `x86::Compiler` as it requires +//! virtual registers). class Emitter : public BaseEmitter, public EmitterImplicitT<Emitter> { ASMJIT_NONCONSTRUCTIBLE(Emitter) }; diff --git a/src/asmjit/x86/x86features.cpp b/src/asmjit/x86/x86features.cpp deleted file mode 100644 index e04aebd..0000000 --- a/src/asmjit/x86/x86features.cpp +++ /dev/null @@ -1,452 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 - -#include "../core/cpuinfo.h" -#include "../core/support.h" -#include "../x86/x86features.h" - -// Required by `__cpuidex()` and `_xgetbv()`. -#if defined(_MSC_VER) - #include <intrin.h> -#endif - -ASMJIT_BEGIN_SUB_NAMESPACE(x86) - -// ============================================================================ -// [asmjit::x86::Features - Detect] -// ============================================================================ - -struct cpuid_t { uint32_t eax, ebx, ecx, edx; }; -struct xgetbv_t { uint32_t eax, edx; }; - -// Executes `cpuid` instruction. -static inline void cpuidQuery(cpuid_t* out, uint32_t inEax, uint32_t inEcx = 0) noexcept { -#if defined(_MSC_VER) - __cpuidex(reinterpret_cast<int*>(out), inEax, inEcx); -#elif defined(__GNUC__) && ASMJIT_ARCH_X86 == 32 - __asm__ __volatile__( - "mov %%ebx, %%edi\n" - "cpuid\n" - "xchg %%edi, %%ebx\n" : "=a"(out->eax), "=D"(out->ebx), "=c"(out->ecx), "=d"(out->edx) : "a"(inEax), "c"(inEcx)); -#elif defined(__GNUC__) && ASMJIT_ARCH_X86 == 64 - __asm__ __volatile__( - "mov %%rbx, %%rdi\n" - "cpuid\n" - "xchg %%rdi, %%rbx\n" : "=a"(out->eax), "=D"(out->ebx), "=c"(out->ecx), "=d"(out->edx) : "a"(inEax), "c"(inEcx)); -#else - #error "[asmjit] x86::cpuidQuery() - Unsupported compiler." -#endif -} - -// Executes 'xgetbv' instruction. -static inline void xgetbvQuery(xgetbv_t* out, uint32_t inEcx) noexcept { -#if defined(_MSC_VER) - uint64_t value = _xgetbv(inEcx); - out->eax = uint32_t(value & 0xFFFFFFFFu); - out->edx = uint32_t(value >> 32); -#elif defined(__GNUC__) - uint32_t outEax; - uint32_t outEdx; - - // Replaced, because the world is not perfect: - // __asm__ __volatile__("xgetbv" : "=a"(outEax), "=d"(outEdx) : "c"(inEcx)); - __asm__ __volatile__(".byte 0x0F, 0x01, 0xD0" : "=a"(outEax), "=d"(outEdx) : "c"(inEcx)); - - out->eax = outEax; - out->edx = outEdx; -#else - out->eax = 0; - out->edx = 0; -#endif -} - -// Map a 12-byte vendor string returned by `cpuid` into a `CpuInfo::Vendor` ID. -static inline void simplifyCpuVendor(CpuInfo& cpu, uint32_t d0, uint32_t d1, uint32_t d2) noexcept { - struct Vendor { - char normalized[8]; - union { char text[12]; uint32_t d[3]; }; - }; - - static const Vendor table[] = { - { { 'A', 'M', 'D' }, {{ 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' }} }, - { { 'I', 'N', 'T', 'E', 'L' }, {{ 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' }} }, - { { 'V', 'I', 'A' }, {{ 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' }} }, - { { 'V', 'I', 'A' }, {{ 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 }} }, - { { 'U', 'N', 'K', 'N', 'O', 'W', 'N' }, {{ 0 }} } - }; - - uint32_t i; - for (i = 0; i < ASMJIT_ARRAY_SIZE(table) - 1; i++) - if (table[i].d[0] == d0 && table[i].d[1] == d1 && table[i].d[2] == d2) - break; - memcpy(cpu._vendor.str, table[i].normalized, 8); -} - -static inline void simplifyCpuBrand(char* s) noexcept { - char* d = s; - - char c = s[0]; - char prev = 0; - - // Used to always clear the current character to ensure that the result - // doesn't contain garbage after a new null terminator is placed at the end. - s[0] = '\0'; - - for (;;) { - if (!c) - break; - - if (!(c == ' ' && (prev == '@' || s[1] == ' ' || s[1] == '@'))) { - *d++ = c; - prev = c; - } - - c = *++s; - s[0] = '\0'; - } - - d[0] = '\0'; -} - -ASMJIT_FAVOR_SIZE void detectCpu(CpuInfo& cpu) noexcept { - using Support::bitTest; - - cpuid_t regs; - xgetbv_t xcr0 { 0, 0 }; - Features& features = cpu._features.as<Features>(); - - cpu.reset(); - cpu._arch = Environment::kArchHost; - cpu._subArch = Environment::kSubArchUnknown; - cpu._reserved = 0; - cpu._maxLogicalProcessors = 1; - features.add(Features::kI486); - - // -------------------------------------------------------------------------- - // [CPUID EAX=0] - // -------------------------------------------------------------------------- - - // Get vendor string/id. - cpuidQuery(®s, 0x0); - - uint32_t maxId = regs.eax; - uint32_t maxSubLeafId_0x7 = 0; - - simplifyCpuVendor(cpu, regs.ebx, regs.edx, regs.ecx); - - // -------------------------------------------------------------------------- - // [CPUID EAX=1] - // -------------------------------------------------------------------------- - - if (maxId >= 0x1) { - // Get feature flags in ECX/EDX and family/model in EAX. - cpuidQuery(®s, 0x1); - - // Fill family and model fields. - uint32_t modelId = (regs.eax >> 4) & 0x0F; - uint32_t familyId = (regs.eax >> 8) & 0x0F; - - // Use extended family and model fields. - if (familyId == 0x06u || familyId == 0x0Fu) - modelId += (((regs.eax >> 16) & 0x0Fu) << 4); - - if (familyId == 0x0Fu) - familyId += ((regs.eax >> 20) & 0xFFu); - - cpu._modelId = modelId; - cpu._familyId = familyId; - cpu._brandId = ((regs.ebx ) & 0xFF); - cpu._processorType = ((regs.eax >> 12) & 0x03); - cpu._maxLogicalProcessors = ((regs.ebx >> 16) & 0xFF); - cpu._stepping = ((regs.eax ) & 0x0F); - cpu._cacheLineSize = ((regs.ebx >> 8) & 0xFF) * 8; - - if (bitTest(regs.ecx, 0)) features.add(Features::kSSE3); - if (bitTest(regs.ecx, 1)) features.add(Features::kPCLMULQDQ); - if (bitTest(regs.ecx, 3)) features.add(Features::kMONITOR); - if (bitTest(regs.ecx, 5)) features.add(Features::kVMX); - if (bitTest(regs.ecx, 6)) features.add(Features::kSMX); - if (bitTest(regs.ecx, 9)) features.add(Features::kSSSE3); - if (bitTest(regs.ecx, 13)) features.add(Features::kCMPXCHG16B); - if (bitTest(regs.ecx, 19)) features.add(Features::kSSE4_1); - if (bitTest(regs.ecx, 20)) features.add(Features::kSSE4_2); - if (bitTest(regs.ecx, 22)) features.add(Features::kMOVBE); - if (bitTest(regs.ecx, 23)) features.add(Features::kPOPCNT); - if (bitTest(regs.ecx, 25)) features.add(Features::kAESNI); - if (bitTest(regs.ecx, 26)) features.add(Features::kXSAVE); - if (bitTest(regs.ecx, 27)) features.add(Features::kOSXSAVE); - if (bitTest(regs.ecx, 30)) features.add(Features::kRDRAND); - if (bitTest(regs.edx, 0)) features.add(Features::kFPU); - if (bitTest(regs.edx, 4)) features.add(Features::kRDTSC); - if (bitTest(regs.edx, 5)) features.add(Features::kMSR); - if (bitTest(regs.edx, 8)) features.add(Features::kCMPXCHG8B); - if (bitTest(regs.edx, 15)) features.add(Features::kCMOV); - if (bitTest(regs.edx, 19)) features.add(Features::kCLFLUSH); - if (bitTest(regs.edx, 23)) features.add(Features::kMMX); - if (bitTest(regs.edx, 24)) features.add(Features::kFXSR); - if (bitTest(regs.edx, 25)) features.add(Features::kSSE); - if (bitTest(regs.edx, 26)) features.add(Features::kSSE, Features::kSSE2); - if (bitTest(regs.edx, 28)) features.add(Features::kMT); - - // Get the content of XCR0 if supported by the CPU and enabled by the OS. - if (features.hasXSAVE() && features.hasOSXSAVE()) { - xgetbvQuery(&xcr0, 0); - } - - // Detect AVX+. - if (bitTest(regs.ecx, 28)) { - // - XCR0[2:1] == 11b - // XMM & YMM states need to be enabled by OS. - if ((xcr0.eax & 0x00000006u) == 0x00000006u) { - features.add(Features::kAVX); - - if (bitTest(regs.ecx, 12)) features.add(Features::kFMA); - if (bitTest(regs.ecx, 29)) features.add(Features::kF16C); - } - } - } - - constexpr uint32_t kXCR0_AMX_Bits = 0x3u << 17; - bool amxEnabledByOS = (xcr0.eax & kXCR0_AMX_Bits) == kXCR0_AMX_Bits; - -#if defined(__APPLE__) - // Apple platform provides on-demand AVX512 support. When an AVX512 instruction is used - // the first time it results in #UD, which would cause the thread being promoted to use - // AVX512 support by the OS in addition to enabling the necessary bits in XCR0 register. - bool avx512EnabledByOS = true; -#else - // - XCR0[2:1] == 11b - XMM/YMM states need to be enabled by OS. - // - XCR0[7:5] == 111b - Upper 256-bit of ZMM0-XMM15 and ZMM16-ZMM31 need to be enabled by OS. - constexpr uint32_t kXCR0_AVX512_Bits = (0x3u << 1) | (0x7u << 5); - bool avx512EnabledByOS = (xcr0.eax & kXCR0_AVX512_Bits) == kXCR0_AVX512_Bits; -#endif - - // -------------------------------------------------------------------------- - // [CPUID EAX=7 ECX=0] - // -------------------------------------------------------------------------- - - // Detect new features if the processor supports CPUID-07. - bool maybeMPX = false; - - if (maxId >= 0x7) { - cpuidQuery(®s, 0x7); - - maybeMPX = bitTest(regs.ebx, 14); - maxSubLeafId_0x7 = regs.eax; - - if (bitTest(regs.ebx, 0)) features.add(Features::kFSGSBASE); - if (bitTest(regs.ebx, 3)) features.add(Features::kBMI); - if (bitTest(regs.ebx, 4)) features.add(Features::kHLE); - if (bitTest(regs.ebx, 7)) features.add(Features::kSMEP); - if (bitTest(regs.ebx, 8)) features.add(Features::kBMI2); - if (bitTest(regs.ebx, 9)) features.add(Features::kERMS); - if (bitTest(regs.ebx, 11)) features.add(Features::kRTM); - if (bitTest(regs.ebx, 18)) features.add(Features::kRDSEED); - if (bitTest(regs.ebx, 19)) features.add(Features::kADX); - if (bitTest(regs.ebx, 20)) features.add(Features::kSMAP); - if (bitTest(regs.ebx, 23)) features.add(Features::kCLFLUSHOPT); - if (bitTest(regs.ebx, 24)) features.add(Features::kCLWB); - if (bitTest(regs.ebx, 29)) features.add(Features::kSHA); - if (bitTest(regs.ecx, 0)) features.add(Features::kPREFETCHWT1); - if (bitTest(regs.ecx, 4)) features.add(Features::kOSPKE); - if (bitTest(regs.ecx, 5)) features.add(Features::kWAITPKG); - if (bitTest(regs.ecx, 7)) features.add(Features::kCET_SS); - if (bitTest(regs.ecx, 8)) features.add(Features::kGFNI); - if (bitTest(regs.ecx, 9)) features.add(Features::kVAES); - if (bitTest(regs.ecx, 10)) features.add(Features::kVPCLMULQDQ); - if (bitTest(regs.ecx, 22)) features.add(Features::kRDPID); - if (bitTest(regs.ecx, 25)) features.add(Features::kCLDEMOTE); - if (bitTest(regs.ecx, 27)) features.add(Features::kMOVDIRI); - if (bitTest(regs.ecx, 28)) features.add(Features::kMOVDIR64B); - if (bitTest(regs.ecx, 29)) features.add(Features::kENQCMD); - if (bitTest(regs.edx, 5)) features.add(Features::kUINTR); - if (bitTest(regs.edx, 14)) features.add(Features::kSERIALIZE); - if (bitTest(regs.edx, 16)) features.add(Features::kTSXLDTRK); - if (bitTest(regs.edx, 18)) features.add(Features::kPCONFIG); - if (bitTest(regs.edx, 20)) features.add(Features::kCET_IBT); - - // Detect 'TSX' - Requires at least one of `HLE` and `RTM` features. - if (features.hasHLE() || features.hasRTM()) - features.add(Features::kTSX); - - // Detect 'AVX2' - Requires AVX as well. - if (bitTest(regs.ebx, 5) && features.hasAVX()) - features.add(Features::kAVX2); - - // Detect 'AMX'. - if (amxEnabledByOS) { - if (bitTest(regs.edx, 22)) features.add(Features::kAMX_BF16); - if (bitTest(regs.edx, 24)) features.add(Features::kAMX_TILE); - if (bitTest(regs.edx, 25)) features.add(Features::kAMX_INT8); - } - - // Detect 'AVX_512'. - if (avx512EnabledByOS && bitTest(regs.ebx, 16)) { - features.add(Features::kAVX512_F); - - if (bitTest(regs.ebx, 17)) features.add(Features::kAVX512_DQ); - if (bitTest(regs.ebx, 21)) features.add(Features::kAVX512_IFMA); - if (bitTest(regs.ebx, 26)) features.add(Features::kAVX512_PFI); - if (bitTest(regs.ebx, 27)) features.add(Features::kAVX512_ERI); - if (bitTest(regs.ebx, 28)) features.add(Features::kAVX512_CDI); - if (bitTest(regs.ebx, 30)) features.add(Features::kAVX512_BW); - if (bitTest(regs.ebx, 31)) features.add(Features::kAVX512_VL); - if (bitTest(regs.ecx, 1)) features.add(Features::kAVX512_VBMI); - if (bitTest(regs.ecx, 6)) features.add(Features::kAVX512_VBMI2); - if (bitTest(regs.ecx, 11)) features.add(Features::kAVX512_VNNI); - if (bitTest(regs.ecx, 12)) features.add(Features::kAVX512_BITALG); - if (bitTest(regs.ecx, 14)) features.add(Features::kAVX512_VPOPCNTDQ); - if (bitTest(regs.edx, 2)) features.add(Features::kAVX512_4VNNIW); - if (bitTest(regs.edx, 3)) features.add(Features::kAVX512_4FMAPS); - if (bitTest(regs.edx, 8)) features.add(Features::kAVX512_VP2INTERSECT); - } - } - - // -------------------------------------------------------------------------- - // [CPUID EAX=7 ECX=1] - // -------------------------------------------------------------------------- - - if (features.hasAVX512_F() && maxSubLeafId_0x7 >= 1) { - cpuidQuery(®s, 0x7, 1); - - if (bitTest(regs.eax, 3)) features.add(Features::kAVX_VNNI); - if (bitTest(regs.eax, 5)) features.add(Features::kAVX512_BF16); - if (bitTest(regs.eax, 22)) features.add(Features::kHRESET); - } - - // -------------------------------------------------------------------------- - // [CPUID EAX=13 ECX=0] - // -------------------------------------------------------------------------- - - if (maxId >= 0xD) { - cpuidQuery(®s, 0xD, 0); - - // Both CPUID result and XCR0 has to be enabled to have support for MPX. - if (((regs.eax & xcr0.eax) & 0x00000018u) == 0x00000018u && maybeMPX) - features.add(Features::kMPX); - - cpuidQuery(®s, 0xD, 1); - - if (bitTest(regs.eax, 0)) features.add(Features::kXSAVEOPT); - if (bitTest(regs.eax, 1)) features.add(Features::kXSAVEC); - if (bitTest(regs.eax, 3)) features.add(Features::kXSAVES); - } - - // -------------------------------------------------------------------------- - // [CPUID EAX=14 ECX=0] - // -------------------------------------------------------------------------- - - if (maxId >= 0xE) { - cpuidQuery(®s, 0xE, 0); - - if (bitTest(regs.ebx, 4)) features.add(Features::kPTWRITE); - } - - // -------------------------------------------------------------------------- - // [CPUID EAX=0x80000000...maxId] - // -------------------------------------------------------------------------- - - maxId = 0x80000000u; - uint32_t i = maxId; - - // The highest EAX that we understand. - uint32_t kHighestProcessedEAX = 0x8000001Fu; - - // Several CPUID calls are required to get the whole branc string. It's easy - // to copy one DWORD at a time instead of performing a byte copy. - uint32_t* brand = cpu._brand.u32; - do { - cpuidQuery(®s, i); - switch (i) { - case 0x80000000u: - maxId = Support::min<uint32_t>(regs.eax, kHighestProcessedEAX); - break; - - case 0x80000001u: - if (bitTest(regs.ecx, 0)) features.add(Features::kLAHFSAHF); - if (bitTest(regs.ecx, 2)) features.add(Features::kSVM); - if (bitTest(regs.ecx, 5)) features.add(Features::kLZCNT); - if (bitTest(regs.ecx, 6)) features.add(Features::kSSE4A); - if (bitTest(regs.ecx, 7)) features.add(Features::kMSSE); - if (bitTest(regs.ecx, 8)) features.add(Features::kPREFETCHW); - if (bitTest(regs.ecx, 12)) features.add(Features::kSKINIT); - if (bitTest(regs.ecx, 15)) features.add(Features::kLWP); - if (bitTest(regs.ecx, 21)) features.add(Features::kTBM); - if (bitTest(regs.ecx, 29)) features.add(Features::kMONITORX); - if (bitTest(regs.edx, 20)) features.add(Features::kNX); - if (bitTest(regs.edx, 21)) features.add(Features::kFXSROPT); - if (bitTest(regs.edx, 22)) features.add(Features::kMMX2); - if (bitTest(regs.edx, 27)) features.add(Features::kRDTSCP); - if (bitTest(regs.edx, 29)) features.add(Features::kPREFETCHW); - if (bitTest(regs.edx, 30)) features.add(Features::k3DNOW2, Features::kMMX2); - if (bitTest(regs.edx, 31)) features.add(Features::kPREFETCHW); - - if (cpu.hasFeature(Features::kAVX)) { - if (bitTest(regs.ecx, 11)) features.add(Features::kXOP); - if (bitTest(regs.ecx, 16)) features.add(Features::kFMA4); - } - - // These seem to be only supported by AMD. - if (cpu.isVendor("AMD")) { - if (bitTest(regs.ecx, 4)) features.add(Features::kALTMOVCR8); - } - break; - - case 0x80000002u: - case 0x80000003u: - case 0x80000004u: - *brand++ = regs.eax; - *brand++ = regs.ebx; - *brand++ = regs.ecx; - *brand++ = regs.edx; - - // Go directly to the next one we are interested in. - if (i == 0x80000004u) i = 0x80000008u - 1; - break; - - case 0x80000008u: - if (bitTest(regs.ebx, 0)) features.add(Features::kCLZERO); - if (bitTest(regs.ebx, 0)) features.add(Features::kRDPRU); - if (bitTest(regs.ebx, 8)) features.add(Features::kMCOMMIT); - if (bitTest(regs.ebx, 9)) features.add(Features::kWBNOINVD); - - // Go directly to the next one we are interested in. - i = 0x8000001Fu - 1; - break; - - case 0x8000001Fu: - if (bitTest(regs.eax, 4)) features.add(Features::kSNP); - break; - } - } while (++i <= maxId); - - // Simplify CPU brand string a bit by removing some unnecessary spaces. - simplifyCpuBrand(cpu._brand.str); -} - -ASMJIT_END_SUB_NAMESPACE - -#endif // !ASMJIT_NO_X86 && ASMJIT_ARCH_X86 diff --git a/src/asmjit/x86/x86features.h b/src/asmjit/x86/x86features.h deleted file mode 100644 index 4d098ec..0000000 --- a/src/asmjit/x86/x86features.h +++ /dev/null @@ -1,318 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_X86_X86FEATURES_H_INCLUDED -#define ASMJIT_X86_X86FEATURES_H_INCLUDED - -#include "../core/features.h" - -ASMJIT_BEGIN_SUB_NAMESPACE(x86) - -//! \addtogroup asmjit_x86 -//! \{ - -// ============================================================================ -// [asmjit::x86::Features] -// ============================================================================ - -//! CPU features (X86). -class Features : public BaseFeatures { -public: - //! CPU feature ID. - enum Id : uint32_t { - // @EnumValuesBegin{"enum": "x86::Features::Id"}@ - - kNone = 0, //!< No feature (never set, used internally). - - kMT, //!< CPU has multi-threading capabilities. - kNX, //!< CPU has Not-Execute-Bit aka DEP (data-execution prevention). - - k3DNOW, //!< CPU has 3DNOW (3DNOW base instructions) [AMD]. - k3DNOW2, //!< CPU has 3DNOW2 (enhanced 3DNOW) [AMD]. - kADX, //!< CPU has ADX (multi-precision add-carry instruction extensions). - kAESNI, //!< CPU has AESNI (AES encode/decode instructions). - kALTMOVCR8, //!< CPU has LOCK MOV R<->CR0 (supports `MOV R<->CR8` via `LOCK MOV R<->CR0` in 32-bit mode) [AMD]. - kAMX_BF16, //!< CPU has AMX_BF16 (advanced matrix extensions - BF16 instructions). - kAMX_INT8, //!< CPU has AMX_INT8 (advanced matrix extensions - INT8 instructions). - kAMX_TILE, //!< CPU has AMX_TILE (advanced matrix extensions). - kAVX, //!< CPU has AVX (advanced vector extensions). - kAVX2, //!< CPU has AVX2 (advanced vector extensions 2). - kAVX512_4FMAPS, //!< CPU has AVX512_FMAPS (FMA packed single). - kAVX512_4VNNIW, //!< CPU has AVX512_VNNIW (vector NN instructions word variable precision). - kAVX512_BF16, //!< CPU has AVX512_BF16 (BFLOAT16 support instruction). - kAVX512_BITALG, //!< CPU has AVX512_BITALG (VPOPCNT[B|W], VPSHUFBITQMB). - kAVX512_BW, //!< CPU has AVX512_BW (packed BYTE|WORD). - kAVX512_CDI, //!< CPU has AVX512_CDI (conflict detection). - kAVX512_DQ, //!< CPU has AVX512_DQ (packed DWORD|QWORD). - kAVX512_ERI, //!< CPU has AVX512_ERI (exponential and reciprocal). - kAVX512_F, //!< CPU has AVX512_F (AVX512 foundation). - kAVX512_IFMA, //!< CPU has AVX512_IFMA (integer fused-multiply-add using 52-bit precision). - kAVX512_PFI, //!< CPU has AVX512_PFI (prefetch instructions). - kAVX512_VBMI, //!< CPU has AVX512_VBMI (vector byte manipulation). - kAVX512_VBMI2, //!< CPU has AVX512_VBMI2 (vector byte manipulation 2). - kAVX512_VL, //!< CPU has AVX512_VL (vector length extensions). - kAVX512_VNNI, //!< CPU has AVX512_VNNI (vector neural network instructions). - kAVX512_VP2INTERSECT, //!< CPU has AVX512_VP2INTERSECT - kAVX512_VPOPCNTDQ, //!< CPU has AVX512_VPOPCNTDQ (VPOPCNT[D|Q] instructions). - kAVX_VNNI, //!< CPU has AVX_VNNI (VEX encoding of vpdpbusd/vpdpbusds/vpdpwssd/vpdpwssds). - kBMI, //!< CPU has BMI (bit manipulation instructions #1). - kBMI2, //!< CPU has BMI2 (bit manipulation instructions #2). - kCET_IBT, //!< CPU has CET-IBT (indirect branch tracking). - kCET_SS, //!< CPU has CET-SS. - kCLDEMOTE, //!< CPU has CLDEMOTE (cache line demote). - kCLFLUSH, //!< CPU has CLFUSH (Cache Line flush). - kCLFLUSHOPT, //!< CPU has CLFUSHOPT (Cache Line flush - optimized). - kCLWB, //!< CPU has CLWB. - kCLZERO, //!< CPU has CLZERO. - kCMOV, //!< CPU has CMOV (CMOV and FCMOV instructions). - kCMPXCHG16B, //!< CPU has CMPXCHG16B (compare-exchange 16 bytes) [X86_64]. - kCMPXCHG8B, //!< CPU has CMPXCHG8B (compare-exchange 8 bytes). - kENCLV, //!< CPU has ENCLV. - kENQCMD, //!< CPU has ENQCMD (enqueue stores). - kERMS, //!< CPU has ERMS (enhanced REP MOVSB/STOSB). - kF16C, //!< CPU has F16C. - kFMA, //!< CPU has FMA (fused-multiply-add 3 operand form). - kFMA4, //!< CPU has FMA4 (fused-multiply-add 4 operand form). - kFPU, //!< CPU has FPU (FPU support). - kFSGSBASE, //!< CPU has FSGSBASE. - kFXSR, //!< CPU has FXSR (FXSAVE/FXRSTOR instructions). - kFXSROPT, //!< CPU has FXSROTP (FXSAVE/FXRSTOR is optimized). - kGEODE, //!< CPU has GEODE extensions (3DNOW additions). - kGFNI, //!< CPU has GFNI (Galois field instructions). - kHLE, //!< CPU has HLE. - kHRESET, //!< CPU has HRESET. - kI486, //!< CPU has I486 features (I486+ support). - kLAHFSAHF, //!< CPU has LAHF/SAHF (LAHF/SAHF in 64-bit mode) [X86_64]. - kLWP, //!< CPU has LWP (lightweight profiling) [AMD]. - kLZCNT, //!< CPU has LZCNT (LZCNT instruction). - kMCOMMIT, //!< CPU has MCOMMIT (MCOMMIT instruction). - kMMX, //!< CPU has MMX (MMX base instructions). - kMMX2, //!< CPU has MMX2 (MMX extensions or MMX2). - kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions). - kMONITORX, //!< CPU has MONITORX (MONITORX/MWAITX instructions). - kMOVBE, //!< CPU has MOVBE (move with byte-order swap). - kMOVDIR64B, //!< CPU has MOVDIR64B (move 64 bytes as direct store). - kMOVDIRI, //!< CPU has MOVDIRI (move dword/qword as direct store). - kMPX, //!< CPU has MPX (memory protection extensions). - kMSR, //!< CPU has MSR (RDMSR/WRMSR instructions). - kMSSE, //!< CPU has MSSE (misaligned SSE support). - kOSXSAVE, //!< CPU has OSXSAVE (XSAVE enabled by OS). - kOSPKE, //!< CPU has OSPKE (PKE enabled by OS). - kPCLMULQDQ, //!< CPU has PCLMULQDQ (packed carry-less multiplication). - kPCONFIG, //!< CPU has PCONFIG (PCONFIG instruction). - kPOPCNT, //!< CPU has POPCNT (POPCNT instruction). - kPREFETCHW, //!< CPU has PREFETCHW. - kPREFETCHWT1, //!< CPU has PREFETCHWT1. - kPTWRITE, //!< CPU has PTWRITE. - kRDPID, //!< CPU has RDPID. - kRDPRU, //!< CPU has RDPRU. - kRDRAND, //!< CPU has RDRAND. - kRDSEED, //!< CPU has RDSEED. - kRDTSC, //!< CPU has RDTSC. - kRDTSCP, //!< CPU has RDTSCP. - kRTM, //!< CPU has RTM. - kSERIALIZE, //!< CPU has SERIALIZE. - kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions). - kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD]. - kSMAP, //!< CPU has SMAP (supervisor-mode access prevention). - kSMEP, //!< CPU has SMEP (supervisor-mode execution prevention). - kSMX, //!< CPU has SMX (safer mode extensions). - kSNP, //!< CPU has SNP. - kSSE, //!< CPU has SSE. - kSSE2, //!< CPU has SSE2. - kSSE3, //!< CPU has SSE3. - kSSE4_1, //!< CPU has SSE4.1. - kSSE4_2, //!< CPU has SSE4.2. - kSSE4A, //!< CPU has SSE4A [AMD]. - kSSSE3, //!< CPU has SSSE3. - kSVM, //!< CPU has SVM (virtualization) [AMD]. - kTBM, //!< CPU has TBM (trailing bit manipulation) [AMD]. - kTSX, //!< CPU has TSX. - kTSXLDTRK, //!< CPU has TSXLDTRK. - kUINTR, //!< CPU has UINTR (user interrupts). - kVAES, //!< CPU has VAES (vector AES 256|512 bit support). - kVMX, //!< CPU has VMX (virtualization) [INTEL]. - kVPCLMULQDQ, //!< CPU has VPCLMULQDQ (vector PCLMULQDQ 256|512-bit support). - kWAITPKG, //!< CPU has WAITPKG (UMONITOR, UMWAIT, TPAUSE). - kWBNOINVD, //!< CPU has WBNOINVD. - kXOP, //!< CPU has XOP (XOP instructions) [AMD]. - kXSAVE, //!< CPU has XSAVE. - kXSAVEC, //!< CPU has XSAVEC. - kXSAVEOPT, //!< CPU has XSAVEOPT. - kXSAVES, //!< CPU has XSAVES. - - // @EnumValuesEnd@ - - kCount //!< Count of X86 CPU features. - }; - - //! \name Construction / Destruction - //! \{ - - inline Features() noexcept - : BaseFeatures() {} - - inline Features(const Features& other) noexcept - : BaseFeatures(other) {} - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline Features& operator=(const Features& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - #define ASMJIT_X86_FEATURE(FEATURE) \ - inline bool has##FEATURE() const noexcept { return has(k##FEATURE); } - - ASMJIT_X86_FEATURE(MT) - ASMJIT_X86_FEATURE(NX) - - ASMJIT_X86_FEATURE(3DNOW) - ASMJIT_X86_FEATURE(3DNOW2) - ASMJIT_X86_FEATURE(ADX) - ASMJIT_X86_FEATURE(AESNI) - ASMJIT_X86_FEATURE(ALTMOVCR8) - ASMJIT_X86_FEATURE(AMX_BF16) - ASMJIT_X86_FEATURE(AMX_INT8) - ASMJIT_X86_FEATURE(AMX_TILE) - ASMJIT_X86_FEATURE(AVX) - ASMJIT_X86_FEATURE(AVX2) - ASMJIT_X86_FEATURE(AVX512_4FMAPS) - ASMJIT_X86_FEATURE(AVX512_4VNNIW) - ASMJIT_X86_FEATURE(AVX512_BF16) - ASMJIT_X86_FEATURE(AVX512_BITALG) - ASMJIT_X86_FEATURE(AVX512_BW) - ASMJIT_X86_FEATURE(AVX512_CDI) - ASMJIT_X86_FEATURE(AVX512_DQ) - ASMJIT_X86_FEATURE(AVX512_ERI) - ASMJIT_X86_FEATURE(AVX512_F) - ASMJIT_X86_FEATURE(AVX512_IFMA) - ASMJIT_X86_FEATURE(AVX512_PFI) - ASMJIT_X86_FEATURE(AVX512_VBMI) - ASMJIT_X86_FEATURE(AVX512_VBMI2) - ASMJIT_X86_FEATURE(AVX512_VL) - ASMJIT_X86_FEATURE(AVX512_VNNI) - ASMJIT_X86_FEATURE(AVX512_VP2INTERSECT) - ASMJIT_X86_FEATURE(AVX512_VPOPCNTDQ) - ASMJIT_X86_FEATURE(AVX_VNNI) - ASMJIT_X86_FEATURE(BMI) - ASMJIT_X86_FEATURE(BMI2) - ASMJIT_X86_FEATURE(CET_IBT) - ASMJIT_X86_FEATURE(CET_SS) - ASMJIT_X86_FEATURE(CLDEMOTE) - ASMJIT_X86_FEATURE(CLFLUSH) - ASMJIT_X86_FEATURE(CLFLUSHOPT) - ASMJIT_X86_FEATURE(CLWB) - ASMJIT_X86_FEATURE(CLZERO) - ASMJIT_X86_FEATURE(CMOV) - ASMJIT_X86_FEATURE(CMPXCHG16B) - ASMJIT_X86_FEATURE(CMPXCHG8B) - ASMJIT_X86_FEATURE(ENCLV) - ASMJIT_X86_FEATURE(ENQCMD) - ASMJIT_X86_FEATURE(ERMS) - ASMJIT_X86_FEATURE(F16C) - ASMJIT_X86_FEATURE(FMA) - ASMJIT_X86_FEATURE(FMA4) - ASMJIT_X86_FEATURE(FPU) - ASMJIT_X86_FEATURE(FSGSBASE) - ASMJIT_X86_FEATURE(FXSR) - ASMJIT_X86_FEATURE(FXSROPT) - ASMJIT_X86_FEATURE(GEODE) - ASMJIT_X86_FEATURE(GFNI) - ASMJIT_X86_FEATURE(HLE) - ASMJIT_X86_FEATURE(HRESET) - ASMJIT_X86_FEATURE(I486) - ASMJIT_X86_FEATURE(LAHFSAHF) - ASMJIT_X86_FEATURE(LWP) - ASMJIT_X86_FEATURE(LZCNT) - ASMJIT_X86_FEATURE(MCOMMIT) - ASMJIT_X86_FEATURE(MMX) - ASMJIT_X86_FEATURE(MMX2) - ASMJIT_X86_FEATURE(MONITOR) - ASMJIT_X86_FEATURE(MONITORX) - ASMJIT_X86_FEATURE(MOVBE) - ASMJIT_X86_FEATURE(MOVDIR64B) - ASMJIT_X86_FEATURE(MOVDIRI) - ASMJIT_X86_FEATURE(MPX) - ASMJIT_X86_FEATURE(MSR) - ASMJIT_X86_FEATURE(MSSE) - ASMJIT_X86_FEATURE(OSXSAVE) - ASMJIT_X86_FEATURE(PCLMULQDQ) - ASMJIT_X86_FEATURE(PCONFIG) - ASMJIT_X86_FEATURE(POPCNT) - ASMJIT_X86_FEATURE(PREFETCHW) - ASMJIT_X86_FEATURE(PREFETCHWT1) - ASMJIT_X86_FEATURE(PTWRITE) - ASMJIT_X86_FEATURE(RDPID) - ASMJIT_X86_FEATURE(RDPRU) - ASMJIT_X86_FEATURE(RDRAND) - ASMJIT_X86_FEATURE(RDSEED) - ASMJIT_X86_FEATURE(RDTSC) - ASMJIT_X86_FEATURE(RDTSCP) - ASMJIT_X86_FEATURE(RTM) - ASMJIT_X86_FEATURE(SERIALIZE) - ASMJIT_X86_FEATURE(SHA) - ASMJIT_X86_FEATURE(SKINIT) - ASMJIT_X86_FEATURE(SMAP) - ASMJIT_X86_FEATURE(SMEP) - ASMJIT_X86_FEATURE(SMX) - ASMJIT_X86_FEATURE(SNP) - ASMJIT_X86_FEATURE(SSE) - ASMJIT_X86_FEATURE(SSE2) - ASMJIT_X86_FEATURE(SSE3) - ASMJIT_X86_FEATURE(SSSE3) - ASMJIT_X86_FEATURE(SSE4A) - ASMJIT_X86_FEATURE(SSE4_1) - ASMJIT_X86_FEATURE(SSE4_2) - ASMJIT_X86_FEATURE(SVM) - ASMJIT_X86_FEATURE(TBM) - ASMJIT_X86_FEATURE(TSX) - ASMJIT_X86_FEATURE(TSXLDTRK) - ASMJIT_X86_FEATURE(UINTR) - ASMJIT_X86_FEATURE(XSAVE) - ASMJIT_X86_FEATURE(XSAVEC) - ASMJIT_X86_FEATURE(XSAVEOPT) - ASMJIT_X86_FEATURE(XSAVES) - ASMJIT_X86_FEATURE(VAES) - ASMJIT_X86_FEATURE(VMX) - ASMJIT_X86_FEATURE(VPCLMULQDQ) - ASMJIT_X86_FEATURE(WAITPKG) - ASMJIT_X86_FEATURE(WBNOINVD) - ASMJIT_X86_FEATURE(XOP) - - #undef ASMJIT_X86_FEATURE - - //! \} -}; - -//! \} - -ASMJIT_END_SUB_NAMESPACE - -#endif // ASMJIT_X86_X86FEATURES_H_INCLUDED diff --git a/src/asmjit/x86/x86formatter.cpp b/src/asmjit/x86/x86formatter.cpp index 2ae0f94..b667019 100644 --- a/src/asmjit/x86/x86formatter.cpp +++ b/src/asmjit/x86/x86formatter.cpp @@ -1,32 +1,14 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_LOGGING +#include "../core/cpuinfo.h" #include "../core/misc_p.h" #include "../core/support.h" -#include "../x86/x86features.h" #include "../x86/x86formatter_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86operand.h" @@ -37,9 +19,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::FormatterInternal - Constants] -// ============================================================================ +// x86::FormatterInternal - Constants +// ================================== struct RegFormatInfo { struct TypeEntry { @@ -53,67 +34,67 @@ struct RegFormatInfo { uint8_t specialCount; }; - TypeEntry typeEntries[BaseReg::kTypeMax + 1]; + TypeEntry typeEntries[uint32_t(RegType::kMaxValue) + 1]; char typeStrings[128 - 32]; - NameEntry nameEntries[BaseReg::kTypeMax + 1]; + NameEntry nameEntries[uint32_t(RegType::kMaxValue) + 1]; char nameStrings[280]; }; template<uint32_t X> struct RegFormatInfo_T { enum { - kTypeIndex = X == Reg::kTypeGpbLo ? 1 : - X == Reg::kTypeGpbHi ? 8 : - X == Reg::kTypeGpw ? 15 : - X == Reg::kTypeGpd ? 19 : - X == Reg::kTypeGpq ? 23 : - X == Reg::kTypeXmm ? 27 : - X == Reg::kTypeYmm ? 31 : - X == Reg::kTypeZmm ? 35 : - X == Reg::kTypeMm ? 50 : - X == Reg::kTypeKReg ? 53 : - X == Reg::kTypeSReg ? 43 : - X == Reg::kTypeCReg ? 59 : - X == Reg::kTypeDReg ? 62 : - X == Reg::kTypeSt ? 47 : - X == Reg::kTypeBnd ? 55 : - X == Reg::kTypeTmm ? 65 : - X == Reg::kTypeRip ? 39 : 0, - - kFormatIndex = X == Reg::kTypeGpbLo ? 1 : - X == Reg::kTypeGpbHi ? 6 : - X == Reg::kTypeGpw ? 11 : - X == Reg::kTypeGpd ? 16 : - X == Reg::kTypeGpq ? 21 : - X == Reg::kTypeXmm ? 25 : - X == Reg::kTypeYmm ? 31 : - X == Reg::kTypeZmm ? 37 : - X == Reg::kTypeMm ? 60 : - X == Reg::kTypeKReg ? 65 : - X == Reg::kTypeSReg ? 49 : - X == Reg::kTypeCReg ? 75 : - X == Reg::kTypeDReg ? 80 : - X == Reg::kTypeSt ? 55 : - X == Reg::kTypeBnd ? 69 : - X == Reg::kTypeTmm ? 89 : - X == Reg::kTypeRip ? 43 : 0, - - kSpecialIndex = X == Reg::kTypeGpbLo ? 96 : - X == Reg::kTypeGpbHi ? 128 : - X == Reg::kTypeGpw ? 161 : - X == Reg::kTypeGpd ? 160 : - X == Reg::kTypeGpq ? 192 : - X == Reg::kTypeSReg ? 224 : - X == Reg::kTypeRip ? 85 : 0, - - kSpecialCount = X == Reg::kTypeGpbLo ? 8 : - X == Reg::kTypeGpbHi ? 4 : - X == Reg::kTypeGpw ? 8 : - X == Reg::kTypeGpd ? 8 : - X == Reg::kTypeGpq ? 8 : - X == Reg::kTypeSReg ? 7 : - X == Reg::kTypeRip ? 1 : 0 + kTypeIndex = X == uint32_t(RegType::kX86_GpbLo) ? 1 : + X == uint32_t(RegType::kX86_GpbHi) ? 8 : + X == uint32_t(RegType::kX86_Gpw ) ? 15 : + X == uint32_t(RegType::kX86_Gpd ) ? 19 : + X == uint32_t(RegType::kX86_Gpq ) ? 23 : + X == uint32_t(RegType::kX86_Xmm ) ? 27 : + X == uint32_t(RegType::kX86_Ymm ) ? 31 : + X == uint32_t(RegType::kX86_Zmm ) ? 35 : + X == uint32_t(RegType::kX86_Mm ) ? 50 : + X == uint32_t(RegType::kX86_KReg ) ? 53 : + X == uint32_t(RegType::kX86_SReg ) ? 43 : + X == uint32_t(RegType::kX86_CReg ) ? 59 : + X == uint32_t(RegType::kX86_DReg ) ? 62 : + X == uint32_t(RegType::kX86_St ) ? 47 : + X == uint32_t(RegType::kX86_Bnd ) ? 55 : + X == uint32_t(RegType::kX86_Tmm ) ? 65 : + X == uint32_t(RegType::kX86_Rip ) ? 39 : 0, + + kFormatIndex = X == uint32_t(RegType::kX86_GpbLo) ? 1 : + X == uint32_t(RegType::kX86_GpbHi) ? 6 : + X == uint32_t(RegType::kX86_Gpw ) ? 11 : + X == uint32_t(RegType::kX86_Gpd ) ? 16 : + X == uint32_t(RegType::kX86_Gpq ) ? 21 : + X == uint32_t(RegType::kX86_Xmm ) ? 25 : + X == uint32_t(RegType::kX86_Ymm ) ? 31 : + X == uint32_t(RegType::kX86_Zmm ) ? 37 : + X == uint32_t(RegType::kX86_Mm ) ? 60 : + X == uint32_t(RegType::kX86_KReg ) ? 65 : + X == uint32_t(RegType::kX86_SReg ) ? 49 : + X == uint32_t(RegType::kX86_CReg ) ? 75 : + X == uint32_t(RegType::kX86_DReg ) ? 80 : + X == uint32_t(RegType::kX86_St ) ? 55 : + X == uint32_t(RegType::kX86_Bnd ) ? 69 : + X == uint32_t(RegType::kX86_Tmm ) ? 89 : + X == uint32_t(RegType::kX86_Rip ) ? 43 : 0, + + kSpecialIndex = X == uint32_t(RegType::kX86_GpbLo) ? 96 : + X == uint32_t(RegType::kX86_GpbHi) ? 128 : + X == uint32_t(RegType::kX86_Gpw ) ? 161 : + X == uint32_t(RegType::kX86_Gpd ) ? 160 : + X == uint32_t(RegType::kX86_Gpq ) ? 192 : + X == uint32_t(RegType::kX86_SReg ) ? 224 : + X == uint32_t(RegType::kX86_Rip ) ? 85 : 0, + + kSpecialCount = X == uint32_t(RegType::kX86_GpbLo) ? 8 : + X == uint32_t(RegType::kX86_GpbHi) ? 4 : + X == uint32_t(RegType::kX86_Gpw ) ? 8 : + X == uint32_t(RegType::kX86_Gpd ) ? 8 : + X == uint32_t(RegType::kX86_Gpq ) ? 8 : + X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_Rip ) ? 1 : 0 }; }; @@ -122,7 +103,7 @@ struct RegFormatInfo_T { } #define ASMJIT_REG_NAME_ENTRY(TYPE) { \ - RegTraits<TYPE>::kCount, \ + RegTraits<RegType(TYPE)>::kCount, \ RegFormatInfo_T<TYPE>::kFormatIndex, \ RegFormatInfo_T<TYPE>::kSpecialIndex, \ RegFormatInfo_T<TYPE>::kSpecialCount \ @@ -201,12 +182,11 @@ static const char* x86GetAddressSizeString(uint32_t size) noexcept { } } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Feature] -// ============================================================================ +// x86::FormatterInternal - Format FeatureId +// ========================================= Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept { - // @EnumStringBegin{"enum": "x86::Features::Id", "output": "sFeature", "strip": "k"}@ + // @EnumStringBegin{"enum": "CpuFeatures::X86", "output": "sFeature", "strip": "k"}@ static const char sFeatureString[] = "None\0" "MT\0" @@ -230,6 +210,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "AVX512_DQ\0" "AVX512_ERI\0" "AVX512_F\0" + "AVX512_FP16\0" "AVX512_IFMA\0" "AVX512_PFI\0" "AVX512_VBMI\0" @@ -328,43 +309,42 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept static const uint16_t sFeatureIndex[] = { 0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 62, 71, 75, 80, 94, 108, 120, 134, 144, - 155, 165, 176, 185, 197, 208, 220, 233, 243, 255, 275, 292, 301, 305, 310, - 318, 325, 334, 342, 353, 358, 365, 370, 381, 391, 397, 404, 409, 414, 418, - 423, 427, 436, 441, 449, 455, 460, 464, 471, 476, 485, 489, 495, 503, 507, - 512, 520, 529, 535, 545, 553, 557, 561, 566, 574, 580, 590, 598, 605, 615, - 627, 635, 641, 647, 654, 661, 667, 674, 678, 688, 692, 699, 704, 709, 713, - 717, 721, 726, 731, 738, 745, 751, 757, 761, 765, 769, 778, 784, 789, 793, - 804, 812, 821, 825, 831, 838, 847, 854 + 155, 165, 176, 185, 197, 209, 220, 232, 245, 255, 267, 287, 304, 313, 317, + 322, 330, 337, 346, 354, 365, 370, 377, 382, 393, 403, 409, 416, 421, 426, + 430, 435, 439, 448, 453, 461, 467, 472, 476, 483, 488, 497, 501, 507, 515, + 519, 524, 532, 541, 547, 557, 565, 569, 573, 578, 586, 592, 602, 610, 617, + 627, 639, 647, 653, 659, 666, 673, 679, 686, 690, 700, 704, 711, 716, 721, + 725, 729, 733, 738, 743, 750, 757, 763, 769, 773, 777, 781, 790, 796, 801, + 805, 816, 824, 833, 837, 843, 850, 859, 866 }; // @EnumStringEnd@ - return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, x86::Features::kCount)]); + return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, uint32_t(CpuFeatures::X86::kMaxValue) + 1)]); } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Register] -// ============================================================================ +// x86::FormatterInternal - Format Register +// ======================================== -ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, uint32_t flags, const BaseEmitter* emitter, uint32_t arch, uint32_t rType, uint32_t rId) noexcept { +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, FormatFlags formatFlags, const BaseEmitter* emitter, Arch arch, RegType type, uint32_t id) noexcept { DebugUtils::unused(arch); const RegFormatInfo& info = x86RegFormatInfo; #ifndef ASMJIT_NO_COMPILER - if (Operand::isVirtId(rId)) { - if (emitter && emitter->emitterType() == BaseEmitter::kTypeCompiler) { + if (Operand::isVirtId(id)) { + if (emitter && emitter->emitterType() == EmitterType::kCompiler) { const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter); - if (cc->isVirtIdValid(rId)) { - VirtReg* vReg = cc->virtRegById(rId); + if (cc->isVirtIdValid(id)) { + VirtReg* vReg = cc->virtRegById(id); ASMJIT_ASSERT(vReg != nullptr); const char* name = vReg->name(); if (name && name[0] != '\0') ASMJIT_PROPAGATE(sb.append(name)); else - ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(rId)))); + ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(id)))); - if (vReg->type() != rType && rType <= BaseReg::kTypeMax && (flags & FormatOptions::kFlagRegCasts) != 0) { - const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[rType]; + if (vReg->type() != type && uint32_t(type) <= uint32_t(RegType::kMaxValue) && Support::test(formatFlags, FormatFlags::kRegCasts)) { + const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)]; if (typeEntry.index) ASMJIT_PROPAGATE(sb.appendFormat("@%s", info.typeStrings + typeEntry.index)); } @@ -374,39 +354,38 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, uint32_t f } } #else - DebugUtils::unused(emitter, flags); + DebugUtils::unused(emitter, formatFlags); #endif - if (ASMJIT_LIKELY(rType <= BaseReg::kTypeMax)) { - const RegFormatInfo::NameEntry& nameEntry = info.nameEntries[rType]; + if (uint32_t(type) <= uint32_t(RegType::kMaxValue)) { + const RegFormatInfo::NameEntry& nameEntry = info.nameEntries[size_t(type)]; - if (rId < nameEntry.specialCount) - return sb.append(info.nameStrings + nameEntry.specialIndex + rId * 4); + if (id < nameEntry.specialCount) + return sb.append(info.nameStrings + nameEntry.specialIndex + id * 4); - if (rId < nameEntry.count) - return sb.appendFormat(info.nameStrings + nameEntry.formatIndex, unsigned(rId)); + if (id < nameEntry.count) + return sb.appendFormat(info.nameStrings + nameEntry.formatIndex, unsigned(id)); - const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[rType]; + const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)]; if (typeEntry.index) - return sb.appendFormat("%s@%u", info.typeStrings + typeEntry.index, rId); + return sb.appendFormat("%s@%u", info.typeStrings + typeEntry.index, id); } - return sb.appendFormat("<Reg-%u>?%u", rType, rId); + return sb.appendFormat("<Reg-%u>?%u", uint32_t(type), id); } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Operand] -// ============================================================================ +// x86::FormatterInternal - Format Operand +// ======================================= ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( String& sb, - uint32_t flags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const Operand_& op) noexcept { if (op.isReg()) - return formatRegister(sb, flags, emitter, arch, op.as<BaseReg>().type(), op.as<BaseReg>().id()); + return formatRegister(sb, formatFlags, emitter, arch, op.as<BaseReg>().type(), op.as<BaseReg>().id()); if (op.isMem()) { const Mem& m = op.as<Mem>(); @@ -419,21 +398,27 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( ASMJIT_PROPAGATE(sb.append('[')); switch (m.addrType()) { - case Mem::kAddrTypeAbs: ASMJIT_PROPAGATE(sb.append("abs ")); break; - case Mem::kAddrTypeRel: ASMJIT_PROPAGATE(sb.append("rel ")); break; + case Mem::AddrType::kDefault: + break; + case Mem::AddrType::kAbs: + ASMJIT_PROPAGATE(sb.append("abs ")); + break; + case Mem::AddrType::kRel: + ASMJIT_PROPAGATE(sb.append("rel ")); + break; } char opSign = '\0'; if (m.hasBase()) { opSign = '+'; if (m.hasBaseLabel()) { - ASMJIT_PROPAGATE(Formatter::formatLabel(sb, flags, emitter, m.baseId())); + ASMJIT_PROPAGATE(Formatter::formatLabel(sb, formatFlags, emitter, m.baseId())); } else { - uint32_t modifiedFlags = flags; + FormatFlags modifiedFlags = formatFlags; if (m.isRegHome()) { ASMJIT_PROPAGATE(sb.append("&")); - modifiedFlags &= ~FormatOptions::kFlagRegCasts; + modifiedFlags &= ~FormatFlags::kRegCasts; } ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId())); } @@ -444,7 +429,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( ASMJIT_PROPAGATE(sb.append(opSign)); opSign = '+'; - ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, m.indexType(), m.indexId())); + ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, arch, m.indexType(), m.indexId())); if (m.hasShift()) ASMJIT_PROPAGATE(sb.appendFormat("*%u", 1 << m.shift())); } @@ -460,7 +445,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( ASMJIT_PROPAGATE(sb.append(opSign)); uint32_t base = 10; - if ((flags & FormatOptions::kFlagHexOffsets) != 0 && off > 9) { + if (Support::test(formatFlags, FormatFlags::kHexOffsets) && off > 9) { ASMJIT_PROPAGATE(sb.append("0x", 2)); base = 16; } @@ -475,7 +460,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( const Imm& i = op.as<Imm>(); int64_t val = i.value(); - if ((flags & FormatOptions::kFlagHexImms) != 0 && uint64_t(val) > 9) { + if (Support::test(formatFlags, FormatFlags::kHexImms) && uint64_t(val) > 9) { ASMJIT_PROPAGATE(sb.append("0x", 2)); return sb.appendUInt(uint64_t(val), 16); } @@ -485,15 +470,14 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( } if (op.isLabel()) { - return Formatter::formatLabel(sb, flags, emitter, op.id()); + return Formatter::formatLabel(sb, formatFlags, emitter, op.id()); } return sb.append("<None>"); } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Immediate (Extension)] -// ============================================================================ +// x86::FormatterInternal - Format Immediate (Extension) +// ===================================================== static constexpr char kImmCharStart = '{'; static constexpr char kImmCharEnd = '}'; @@ -581,12 +565,12 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint3 ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( String& sb, - uint32_t flags, - uint32_t instId, + FormatFlags formatFlags, + InstId instId, uint32_t vecSize, const Imm& imm) noexcept { - DebugUtils::unused(flags); + DebugUtils::unused(formatFlags); static const char vcmpx[] = "EQ_OQ\0" "LT_OS\0" "LE_OS\0" "UNORD_Q\0" "NEQ_UQ\0" "NLT_US\0" "NLE_US\0" "ORD_Q\0" @@ -819,64 +803,76 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( } } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Instruction] -// ============================================================================ +// x86::FormatterInternal - Format Instruction +// =========================================== ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( String& sb, - uint32_t flags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { - uint32_t instId = inst.id(); - uint32_t options = inst.options(); + InstId instId = inst.id(); + InstOptions options = inst.options(); // Format instruction options and instruction mnemonic. if (instId < Inst::_kIdCount) { // VEX|EVEX options. - if (options & Inst::kOptionVex) ASMJIT_PROPAGATE(sb.append("{vex} ")); - if (options & Inst::kOptionVex3) ASMJIT_PROPAGATE(sb.append("{vex3} ")); - if (options & Inst::kOptionEvex) ASMJIT_PROPAGATE(sb.append("{evex} ")); + if (Support::test(options, InstOptions::kX86_Vex)) + ASMJIT_PROPAGATE(sb.append("{vex} ")); + + if (Support::test(options, InstOptions::kX86_Vex3)) + ASMJIT_PROPAGATE(sb.append("{vex3} ")); + + if (Support::test(options, InstOptions::kX86_Evex)) + ASMJIT_PROPAGATE(sb.append("{evex} ")); // MOD/RM and MOD/MR options - if (options & Inst::kOptionModRM) + if (Support::test(options, InstOptions::kX86_ModRM)) ASMJIT_PROPAGATE(sb.append("{modrm} ")); - else if (options & Inst::kOptionModMR) + else if (Support::test(options, InstOptions::kX86_ModMR)) ASMJIT_PROPAGATE(sb.append("{modmr} ")); // SHORT|LONG options. - if (options & Inst::kOptionShortForm) ASMJIT_PROPAGATE(sb.append("short ")); - if (options & Inst::kOptionLongForm) ASMJIT_PROPAGATE(sb.append("long ")); + if (Support::test(options, InstOptions::kShortForm)) + ASMJIT_PROPAGATE(sb.append("short ")); + + if (Support::test(options, InstOptions::kLongForm)) + ASMJIT_PROPAGATE(sb.append("long ")); // LOCK|XACQUIRE|XRELEASE options. - if (options & Inst::kOptionXAcquire) ASMJIT_PROPAGATE(sb.append("xacquire ")); - if (options & Inst::kOptionXRelease) ASMJIT_PROPAGATE(sb.append("xrelease ")); - if (options & Inst::kOptionLock) ASMJIT_PROPAGATE(sb.append("lock ")); + if (Support::test(options, InstOptions::kX86_XAcquire)) + ASMJIT_PROPAGATE(sb.append("xacquire ")); + + if (Support::test(options, InstOptions::kX86_XRelease)) + ASMJIT_PROPAGATE(sb.append("xrelease ")); + + if (Support::test(options, InstOptions::kX86_Lock)) + ASMJIT_PROPAGATE(sb.append("lock ")); // REP|REPNE options. - if (options & (Inst::kOptionRep | Inst::kOptionRepne)) { - sb.append((options & Inst::kOptionRep) ? "rep " : "repnz "); + if (Support::test(options, InstOptions::kX86_Rep | InstOptions::kX86_Repne)) { + sb.append(Support::test(options, InstOptions::kX86_Rep) ? "rep " : "repnz "); if (inst.hasExtraReg()) { ASMJIT_PROPAGATE(sb.append("{")); - ASMJIT_PROPAGATE(formatOperand(sb, flags, emitter, arch, inst.extraReg().toReg<BaseReg>())); + ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, emitter, arch, inst.extraReg().toReg<BaseReg>())); ASMJIT_PROPAGATE(sb.append("} ")); } } // REX options. - if (options & Inst::kOptionRex) { - const uint32_t kRXBWMask = Inst::kOptionOpCodeR | - Inst::kOptionOpCodeX | - Inst::kOptionOpCodeB | - Inst::kOptionOpCodeW ; - if (options & kRXBWMask) { - sb.append("rex."); - if (options & Inst::kOptionOpCodeR) sb.append('r'); - if (options & Inst::kOptionOpCodeX) sb.append('x'); - if (options & Inst::kOptionOpCodeB) sb.append('b'); - if (options & Inst::kOptionOpCodeW) sb.append('w'); + if (Support::test(options, InstOptions::kX86_Rex)) { + const InstOptions kRXBWMask = InstOptions::kX86_OpCodeR | + InstOptions::kX86_OpCodeX | + InstOptions::kX86_OpCodeB | + InstOptions::kX86_OpCodeW ; + if (Support::test(options, kRXBWMask)) { + ASMJIT_PROPAGATE(sb.append("rex.")); + if (Support::test(options, InstOptions::kX86_OpCodeR)) sb.append('r'); + if (Support::test(options, InstOptions::kX86_OpCodeX)) sb.append('x'); + if (Support::test(options, InstOptions::kX86_OpCodeB)) sb.append('b'); + if (Support::test(options, InstOptions::kX86_OpCodeW)) sb.append('w'); sb.append(' '); } else { @@ -895,34 +891,47 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( if (op.isNone()) break; ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); - ASMJIT_PROPAGATE(formatOperand(sb, flags, emitter, arch, op)); + ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, emitter, arch, op)); - if (op.isImm() && (flags & FormatOptions::kFlagExplainImms)) { + if (op.isImm() && uint32_t(formatFlags & FormatFlags::kExplainImms)) { uint32_t vecSize = 16; for (uint32_t j = 0; j < opCount; j++) if (operands[j].isReg()) vecSize = Support::max<uint32_t>(vecSize, operands[j].size()); - ASMJIT_PROPAGATE(FormatterInternal_explainConst(sb, flags, instId, vecSize, op.as<Imm>())); + ASMJIT_PROPAGATE(FormatterInternal_explainConst(sb, formatFlags, instId, vecSize, op.as<Imm>())); } // Support AVX-512 masking - {k}{z}. if (i == 0) { - if (inst.extraReg().group() == Reg::kGroupKReg) { + if (inst.extraReg().group() == RegGroup::kX86_K) { ASMJIT_PROPAGATE(sb.append(" {")); - ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, inst.extraReg().type(), inst.extraReg().id())); + ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, arch, inst.extraReg().type(), inst.extraReg().id())); ASMJIT_PROPAGATE(sb.append('}')); - if (options & Inst::kOptionZMask) + if (Support::test(options, InstOptions::kX86_ZMask)) ASMJIT_PROPAGATE(sb.append("{z}")); } - else if (options & Inst::kOptionZMask) { + else if (Support::test(options, InstOptions::kX86_ZMask)) { ASMJIT_PROPAGATE(sb.append(" {z}")); } } // Support AVX-512 broadcast - {1tox}. if (op.isMem() && op.as<Mem>().hasBroadcast()) { - ASMJIT_PROPAGATE(sb.appendFormat(" {1to%u}", Support::bitMask(op.as<Mem>().getBroadcast()))); + ASMJIT_PROPAGATE(sb.appendFormat(" {1to%u}", Support::bitMask(uint32_t(op.as<Mem>().getBroadcast())))); + } + } + + // Support AVX-512 embedded rounding and suppress-all-exceptions {sae}. + if (inst.hasOption(InstOptions::kX86_ER | InstOptions::kX86_SAE)) { + if (inst.hasOption(InstOptions::kX86_ER)) { + uint32_t bits = uint32_t(inst.options() & InstOptions::kX86_ERMask) >> Support::ConstCTZ<uint32_t(InstOptions::kX86_ERMask)>::value; + + const char roundingModes[] = "rn\0rd\0ru\0rz"; + ASMJIT_PROPAGATE(sb.appendFormat(", {%s-sae}", roundingModes + bits * 3)); + } + else { + ASMJIT_PROPAGATE(sb.append(", {sae}")); } } diff --git a/src/asmjit/x86/x86formatter_p.h b/src/asmjit/x86/x86formatter_p.h index d7d58e4..1dbdb68 100644 --- a/src/asmjit/x86/x86formatter_p.h +++ b/src/asmjit/x86/x86formatter_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86FORMATTER_P_H_INCLUDED #define ASMJIT_X86_X86FORMATTER_P_H_INCLUDED @@ -37,10 +19,6 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::FormatterInternal] -// ============================================================================ - namespace FormatterInternal { Error formatFeature( @@ -49,24 +27,24 @@ Error formatFeature( Error formatRegister( String& sb, - uint32_t flags, + FormatFlags flags, const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, + Arch arch, + RegType regType, uint32_t regId) noexcept; Error formatOperand( String& sb, - uint32_t flags, + FormatFlags flags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const Operand_& op) noexcept; Error formatInstruction( String& sb, - uint32_t flags, + FormatFlags flags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept; } // {FormatterInternal} diff --git a/src/asmjit/x86/x86func.cpp b/src/asmjit/x86/x86func.cpp index 8f2f077..bba9eef 100644 --- a/src/asmjit/x86/x86func.cpp +++ b/src/asmjit/x86/x86func.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) @@ -30,28 +12,19 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::FuncInternal - Init] -// ============================================================================ - namespace FuncInternal { -static inline bool shouldThreatAsCDeclIn64BitMode(uint32_t ccId) noexcept { - return ccId == CallConv::kIdCDecl || - ccId == CallConv::kIdStdCall || - ccId == CallConv::kIdThisCall || - ccId == CallConv::kIdFastCall || - ccId == CallConv::kIdRegParm1 || - ccId == CallConv::kIdRegParm2 || - ccId == CallConv::kIdRegParm3; +static inline bool shouldThreatAsCDeclIn64BitMode(CallConvId ccId) noexcept { + return ccId == CallConvId::kCDecl || + ccId == CallConvId::kStdCall || + ccId == CallConvId::kThisCall || + ccId == CallConvId::kFastCall || + ccId == CallConvId::kRegParm1 || + ccId == CallConvId::kRegParm2 || + ccId == CallConvId::kRegParm3; } -ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, uint32_t ccId, const Environment& environment) noexcept { - constexpr uint32_t kGroupGp = Reg::kGroupGp; - constexpr uint32_t kGroupVec = Reg::kGroupVec; - constexpr uint32_t kGroupMm = Reg::kGroupMm; - constexpr uint32_t kGroupKReg = Reg::kGroupKReg; - +ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept { constexpr uint32_t kZax = Gp::kIdAx; constexpr uint32_t kZbx = Gp::kIdBx; constexpr uint32_t kZcx = Gp::kIdCx; @@ -61,80 +34,80 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, uint32_t ccId, const Environm constexpr uint32_t kZsi = Gp::kIdSi; constexpr uint32_t kZdi = Gp::kIdDi; - bool winABI = environment.isPlatformWindows() || environment.isAbiMSVC(); + bool winABI = environment.isPlatformWindows() || environment.isMSVC(); cc.setArch(environment.arch()); - cc.setSaveRestoreRegSize(Reg::kGroupVec, 16); - cc.setSaveRestoreRegSize(Reg::kGroupMm, 8); - cc.setSaveRestoreRegSize(Reg::kGroupKReg, 8); - cc.setSaveRestoreAlignment(Reg::kGroupVec, 16); - cc.setSaveRestoreAlignment(Reg::kGroupMm, 8); - cc.setSaveRestoreAlignment(Reg::kGroupKReg, 8); + cc.setSaveRestoreRegSize(RegGroup::kVec, 16); + cc.setSaveRestoreRegSize(RegGroup::kX86_MM, 8); + cc.setSaveRestoreRegSize(RegGroup::kX86_K, 8); + cc.setSaveRestoreAlignment(RegGroup::kVec, 16); + cc.setSaveRestoreAlignment(RegGroup::kX86_MM, 8); + cc.setSaveRestoreAlignment(RegGroup::kX86_K, 8); if (environment.is32Bit()) { bool isStandardCallConv = true; - cc.setSaveRestoreRegSize(Reg::kGroupGp, 4); - cc.setSaveRestoreAlignment(Reg::kGroupGp, 4); + cc.setSaveRestoreRegSize(RegGroup::kGp, 4); + cc.setSaveRestoreAlignment(RegGroup::kGp, 4); - cc.setPreservedRegs(Reg::kGroupGp, Support::bitMask(Gp::kIdBx, Gp::kIdSp, Gp::kIdBp, Gp::kIdSi, Gp::kIdDi)); + cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(Gp::kIdBx, Gp::kIdSp, Gp::kIdBp, Gp::kIdSi, Gp::kIdDi)); cc.setNaturalStackAlignment(4); switch (ccId) { - case CallConv::kIdCDecl: + case CallConvId::kCDecl: break; - case CallConv::kIdStdCall: - cc.setFlags(CallConv::kFlagCalleePopsStack); + case CallConvId::kStdCall: + cc.setFlags(CallConvFlags::kCalleePopsStack); break; - case CallConv::kIdFastCall: - cc.setFlags(CallConv::kFlagCalleePopsStack); - cc.setPassedOrder(kGroupGp, kZcx, kZdx); + case CallConvId::kFastCall: + cc.setFlags(CallConvFlags::kCalleePopsStack); + cc.setPassedOrder(RegGroup::kGp, kZcx, kZdx); break; - case CallConv::kIdVectorCall: - cc.setFlags(CallConv::kFlagCalleePopsStack); - cc.setPassedOrder(kGroupGp, kZcx, kZdx); - cc.setPassedOrder(kGroupVec, 0, 1, 2, 3, 4, 5); + case CallConvId::kVectorCall: + cc.setFlags(CallConvFlags::kCalleePopsStack); + cc.setPassedOrder(RegGroup::kGp, kZcx, kZdx); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5); break; - case CallConv::kIdThisCall: - // NOTE: Even MINGW (starting with GCC 4.7.0) now uses __thiscall on MS Windows, - // so we won't bail to any other calling convention if __thiscall was specified. + case CallConvId::kThisCall: + // NOTE: Even MINGW (starting with GCC 4.7.0) now uses __thiscall on MS Windows, so we won't bail to any + // other calling convention if __thiscall was specified. if (winABI) { - cc.setFlags(CallConv::kFlagCalleePopsStack); - cc.setPassedOrder(kGroupGp, kZcx); + cc.setFlags(CallConvFlags::kCalleePopsStack); + cc.setPassedOrder(RegGroup::kGp, kZcx); } else { - ccId = CallConv::kIdCDecl; + ccId = CallConvId::kCDecl; } break; - case CallConv::kIdRegParm1: - cc.setPassedOrder(kGroupGp, kZax); + case CallConvId::kRegParm1: + cc.setPassedOrder(RegGroup::kGp, kZax); break; - case CallConv::kIdRegParm2: - cc.setPassedOrder(kGroupGp, kZax, kZdx); + case CallConvId::kRegParm2: + cc.setPassedOrder(RegGroup::kGp, kZax, kZdx); break; - case CallConv::kIdRegParm3: - cc.setPassedOrder(kGroupGp, kZax, kZdx, kZcx); + case CallConvId::kRegParm3: + cc.setPassedOrder(RegGroup::kGp, kZax, kZdx, kZcx); break; - case CallConv::kIdLightCall2: - case CallConv::kIdLightCall3: - case CallConv::kIdLightCall4: { - uint32_t n = (ccId - CallConv::kIdLightCall2) + 2; + case CallConvId::kLightCall2: + case CallConvId::kLightCall3: + case CallConvId::kLightCall4: { + uint32_t n = uint32_t(ccId) - uint32_t(CallConvId::kLightCall2) + 2; - cc.setFlags(CallConv::kFlagPassFloatsByVec); - cc.setPassedOrder(kGroupGp, kZax, kZdx, kZcx, kZsi, kZdi); - cc.setPassedOrder(kGroupMm, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPassedOrder(kGroupVec, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPassedOrder(kGroupKReg, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPreservedRegs(kGroupGp, Support::lsbMask<uint32_t>(8)); - cc.setPreservedRegs(kGroupVec, Support::lsbMask<uint32_t>(8) & ~Support::lsbMask<uint32_t>(n)); + cc.setFlags(CallConvFlags::kPassFloatsByVec); + cc.setPassedOrder(RegGroup::kGp, kZax, kZdx, kZcx, kZsi, kZdi); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPassedOrder(RegGroup::kX86_K, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPassedOrder(RegGroup::kX86_MM, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPreservedRegs(RegGroup::kGp, Support::lsbMask<uint32_t>(8)); + cc.setPreservedRegs(RegGroup::kVec, Support::lsbMask<uint32_t>(8) & ~Support::lsbMask<uint32_t>(n)); cc.setNaturalStackAlignment(16); isStandardCallConv = false; @@ -146,92 +119,90 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, uint32_t ccId, const Environm } if (isStandardCallConv) { - // MMX arguments is something where compiler vendors disagree. For example - // GCC and MSVC would pass first three via registers and the rest via stack, - // however Clang passes all via stack. Returning MMX registers is even more - // fun, where GCC uses MM0, but Clang uses EAX:EDX pair. I'm not sure it's - // something we should be worried about as MMX is deprecated anyway. - cc.setPassedOrder(kGroupMm, 0, 1, 2); - - // Vector arguments (XMM|YMM|ZMM) are passed via registers. However, if the - // function is variadic then they have to be passed via stack. - cc.setPassedOrder(kGroupVec, 0, 1, 2); - - // Functions with variable arguments always use stack for MM and vector - // arguments. - cc.addFlags(CallConv::kFlagPassVecByStackIfVA); + // MMX arguments is something where compiler vendors disagree. For example GCC and MSVC would pass first three + // via registers and the rest via stack, however Clang passes all via stack. Returning MMX registers is even + // more fun, where GCC uses MM0, but Clang uses EAX:EDX pair. I'm not sure it's something we should be worried + // about as MMX is deprecated anyway. + cc.setPassedOrder(RegGroup::kX86_MM, 0, 1, 2); + + // Vector arguments (XMM|YMM|ZMM) are passed via registers. However, if the function is variadic then they have + // to be passed via stack. + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2); + + // Functions with variable arguments always use stack for MM and vector arguments. + cc.addFlags(CallConvFlags::kPassVecByStackIfVA); } - if (ccId == CallConv::kIdCDecl) { - cc.addFlags(CallConv::kFlagVarArgCompatible); + if (ccId == CallConvId::kCDecl) { + cc.addFlags(CallConvFlags::kVarArgCompatible); } } else { - cc.setSaveRestoreRegSize(Reg::kGroupGp, 8); - cc.setSaveRestoreAlignment(Reg::kGroupGp, 8); + cc.setSaveRestoreRegSize(RegGroup::kGp, 8); + cc.setSaveRestoreAlignment(RegGroup::kGp, 8); - // Preprocess the calling convention into a common id as many conventions - // are normally ignored even by C/C++ compilers and treated as `__cdecl`. + // Preprocess the calling convention into a common id as many conventions are normally ignored even by C/C++ + // compilers and treated as `__cdecl`. if (shouldThreatAsCDeclIn64BitMode(ccId)) - ccId = winABI ? CallConv::kIdX64Windows : CallConv::kIdX64SystemV; + ccId = winABI ? CallConvId::kX64Windows : CallConvId::kX64SystemV; switch (ccId) { - case CallConv::kIdX64SystemV: { - cc.setFlags(CallConv::kFlagPassFloatsByVec | - CallConv::kFlagPassMmxByXmm | - CallConv::kFlagVarArgCompatible); + case CallConvId::kX64SystemV: { + cc.setFlags(CallConvFlags::kPassFloatsByVec | + CallConvFlags::kPassMmxByXmm | + CallConvFlags::kVarArgCompatible); cc.setNaturalStackAlignment(16); cc.setRedZoneSize(128); - cc.setPassedOrder(kGroupGp, kZdi, kZsi, kZdx, kZcx, 8, 9); - cc.setPassedOrder(kGroupVec, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPreservedRegs(kGroupGp, Support::bitMask(kZbx, kZsp, kZbp, 12, 13, 14, 15)); + cc.setPassedOrder(RegGroup::kGp, kZdi, kZsi, kZdx, kZcx, 8, 9); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(kZbx, kZsp, kZbp, 12, 13, 14, 15)); break; } - case CallConv::kIdX64Windows: { - cc.setStrategy(CallConv::kStrategyX64Windows); - cc.setFlags(CallConv::kFlagPassFloatsByVec | - CallConv::kFlagIndirectVecArgs | - CallConv::kFlagPassMmxByGp | - CallConv::kFlagVarArgCompatible); + case CallConvId::kX64Windows: { + cc.setStrategy(CallConvStrategy::kX64Windows); + cc.setFlags(CallConvFlags::kPassFloatsByVec | + CallConvFlags::kIndirectVecArgs | + CallConvFlags::kPassMmxByGp | + CallConvFlags::kVarArgCompatible); cc.setNaturalStackAlignment(16); // Maximum 4 arguments in registers, each adds 8 bytes to the spill zone. cc.setSpillZoneSize(4 * 8); - cc.setPassedOrder(kGroupGp, kZcx, kZdx, 8, 9); - cc.setPassedOrder(kGroupVec, 0, 1, 2, 3); - cc.setPreservedRegs(kGroupGp, Support::bitMask(kZbx, kZsp, kZbp, kZsi, kZdi, 12, 13, 14, 15)); - cc.setPreservedRegs(kGroupVec, Support::bitMask(6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); + cc.setPassedOrder(RegGroup::kGp, kZcx, kZdx, 8, 9); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3); + cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(kZbx, kZsp, kZbp, kZsi, kZdi, 12, 13, 14, 15)); + cc.setPreservedRegs(RegGroup::kVec, Support::bitMask(6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); break; } - case CallConv::kIdVectorCall: { - cc.setStrategy(CallConv::kStrategyX64VectorCall); - cc.setFlags(CallConv::kFlagPassFloatsByVec | - CallConv::kFlagPassMmxByGp ); + case CallConvId::kVectorCall: { + cc.setStrategy(CallConvStrategy::kX64VectorCall); + cc.setFlags(CallConvFlags::kPassFloatsByVec | + CallConvFlags::kPassMmxByGp ); cc.setNaturalStackAlignment(16); // Maximum 6 arguments in registers, each adds 8 bytes to the spill zone. cc.setSpillZoneSize(6 * 8); - cc.setPassedOrder(kGroupGp, kZcx, kZdx, 8, 9); - cc.setPassedOrder(kGroupVec, 0, 1, 2, 3, 4, 5); - cc.setPreservedRegs(kGroupGp, Support::bitMask(kZbx, kZsp, kZbp, kZsi, kZdi, 12, 13, 14, 15)); - cc.setPreservedRegs(kGroupVec, Support::bitMask(6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); + cc.setPassedOrder(RegGroup::kGp, kZcx, kZdx, 8, 9); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5); + cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(kZbx, kZsp, kZbp, kZsi, kZdi, 12, 13, 14, 15)); + cc.setPreservedRegs(RegGroup::kVec, Support::bitMask(6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); break; } - case CallConv::kIdLightCall2: - case CallConv::kIdLightCall3: - case CallConv::kIdLightCall4: { - uint32_t n = (ccId - CallConv::kIdLightCall2) + 2; + case CallConvId::kLightCall2: + case CallConvId::kLightCall3: + case CallConvId::kLightCall4: { + uint32_t n = uint32_t(ccId) - uint32_t(CallConvId::kLightCall2) + 2; - cc.setFlags(CallConv::kFlagPassFloatsByVec); + cc.setFlags(CallConvFlags::kPassFloatsByVec); cc.setNaturalStackAlignment(16); - cc.setPassedOrder(kGroupGp, kZax, kZdx, kZcx, kZsi, kZdi); - cc.setPassedOrder(kGroupMm, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPassedOrder(kGroupVec, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPassedOrder(kGroupKReg, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPassedOrder(RegGroup::kGp, kZax, kZdx, kZcx, kZsi, kZdi); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPassedOrder(RegGroup::kX86_K, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPassedOrder(RegGroup::kX86_MM, 0, 1, 2, 3, 4, 5, 6, 7); - cc.setPreservedRegs(kGroupGp, Support::lsbMask<uint32_t>(16)); - cc.setPreservedRegs(kGroupVec, ~Support::lsbMask<uint32_t>(n)); + cc.setPreservedRegs(RegGroup::kGp, Support::lsbMask<uint32_t>(16)); + cc.setPreservedRegs(RegGroup::kVec, ~Support::lsbMask<uint32_t>(n)); break; } @@ -245,24 +216,28 @@ ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, uint32_t ccId, const Environm } ASMJIT_FAVOR_SIZE void unpackValues(FuncDetail& func, FuncValuePack& pack) noexcept { - uint32_t typeId = pack[0].typeId(); + TypeId typeId = pack[0].typeId(); switch (typeId) { - case Type::kIdI64: - case Type::kIdU64: { + case TypeId::kInt64: + case TypeId::kUInt64: { if (Environment::is32Bit(func.callConv().arch())) { // Convert a 64-bit return value to two 32-bit return values. - pack[0].initTypeId(Type::kIdU32); - pack[1].initTypeId(typeId - 2); + pack[0].initTypeId(TypeId::kUInt32); + pack[1].initTypeId(TypeId(uint32_t(typeId) - 2)); break; } break; } + + default: { + break; + } } } ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept { const CallConv& cc = func.callConv(); - uint32_t arch = cc.arch(); + Arch arch = cc.arch(); uint32_t stackOffset = cc._spillZoneSize; uint32_t argCount = func.argCount(); @@ -277,63 +252,63 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si if (func.hasRet()) { unpackValues(func, func._rets); for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { - uint32_t typeId = func._rets[valueIndex].typeId(); + TypeId typeId = func._rets[valueIndex].typeId(); // Terminate at the first void type (end of the pack). - if (!typeId) + if (typeId == TypeId::kVoid) break; switch (typeId) { - case Type::kIdI64: - case Type::kIdU64: { + case TypeId::kInt64: + case TypeId::kUInt64: { if (gpReturnIndexes[valueIndex] != BaseReg::kIdBad) - func._rets[valueIndex].initReg(Reg::kTypeGpq, gpReturnIndexes[valueIndex], typeId); + func._rets[valueIndex].initReg(RegType::kX86_Gpq, gpReturnIndexes[valueIndex], typeId); else return DebugUtils::errored(kErrorInvalidState); break; } - case Type::kIdI8: - case Type::kIdI16: - case Type::kIdI32: { + case TypeId::kInt8: + case TypeId::kInt16: + case TypeId::kInt32: { if (gpReturnIndexes[valueIndex] != BaseReg::kIdBad) - func._rets[valueIndex].initReg(Reg::kTypeGpd, gpReturnIndexes[valueIndex], Type::kIdI32); + func._rets[valueIndex].initReg(RegType::kX86_Gpd, gpReturnIndexes[valueIndex], TypeId::kInt32); else return DebugUtils::errored(kErrorInvalidState); break; } - case Type::kIdU8: - case Type::kIdU16: - case Type::kIdU32: { + case TypeId::kUInt8: + case TypeId::kUInt16: + case TypeId::kUInt32: { if (gpReturnIndexes[valueIndex] != BaseReg::kIdBad) - func._rets[valueIndex].initReg(Reg::kTypeGpd, gpReturnIndexes[valueIndex], Type::kIdU32); + func._rets[valueIndex].initReg(RegType::kX86_Gpd, gpReturnIndexes[valueIndex], TypeId::kUInt32); else return DebugUtils::errored(kErrorInvalidState); break; } - case Type::kIdF32: - case Type::kIdF64: { - uint32_t regType = Environment::is32Bit(arch) ? Reg::kTypeSt : Reg::kTypeXmm; + case TypeId::kFloat32: + case TypeId::kFloat64: { + RegType regType = Environment::is32Bit(arch) ? RegType::kX86_St : RegType::kX86_Xmm; func._rets[valueIndex].initReg(regType, valueIndex, typeId); break; } - case Type::kIdF80: { + case TypeId::kFloat80: { // 80-bit floats are always returned by FP0. - func._rets[valueIndex].initReg(Reg::kTypeSt, valueIndex, typeId); + func._rets[valueIndex].initReg(RegType::kX86_St, valueIndex, typeId); break; } - case Type::kIdMmx32: - case Type::kIdMmx64: { + case TypeId::kMmx32: + case TypeId::kMmx64: { // MM registers are returned through XMM (SystemV) or GPQ (Win64). - uint32_t regType = Reg::kTypeMm; + RegType regType = RegType::kX86_Mm; uint32_t regIndex = valueIndex; if (Environment::is64Bit(arch)) { - regType = cc.strategy() == CallConv::kStrategyDefault ? Reg::kTypeXmm : Reg::kTypeGpq; - regIndex = cc.strategy() == CallConv::kStrategyDefault ? valueIndex : gpReturnIndexes[valueIndex]; + regType = cc.strategy() == CallConvStrategy::kDefault ? RegType::kX86_Xmm : RegType::kX86_Gpq; + regIndex = cc.strategy() == CallConvStrategy::kDefault ? valueIndex : gpReturnIndexes[valueIndex]; if (regIndex == BaseReg::kIdBad) return DebugUtils::errored(kErrorInvalidState); @@ -352,7 +327,7 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si } switch (cc.strategy()) { - case CallConv::kStrategyDefault: { + case CallConvStrategy::kDefault: { uint32_t gpzPos = 0; uint32_t vecPos = 0; @@ -366,56 +341,55 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si if (!arg) break; - uint32_t typeId = arg.typeId(); + TypeId typeId = arg.typeId(); - if (Type::isInt(typeId)) { + if (TypeUtils::isInt(typeId)) { uint32_t regId = BaseReg::kIdBad; if (gpzPos < CallConv::kMaxRegArgsPerGroup) - regId = cc._passedOrder[Reg::kGroupGp].id[gpzPos]; + regId = cc._passedOrder[RegGroup::kGp].id[gpzPos]; if (regId != BaseReg::kIdBad) { - uint32_t regType = (typeId <= Type::kIdU32) ? Reg::kTypeGpd : Reg::kTypeGpq; + RegType regType = typeId <= TypeId::kUInt32 ? RegType::kX86_Gpd : RegType::kX86_Gpq; arg.assignRegData(regType, regId); - func.addUsedRegs(Reg::kGroupGp, Support::bitMask(regId)); + func.addUsedRegs(RegGroup::kGp, Support::bitMask(regId)); gpzPos++; } else { - uint32_t size = Support::max<uint32_t>(Type::sizeOf(typeId), registerSize); + uint32_t size = Support::max<uint32_t>(TypeUtils::sizeOf(typeId), registerSize); arg.assignStackOffset(int32_t(stackOffset)); stackOffset += size; } continue; } - if (Type::isFloat(typeId) || Type::isVec(typeId)) { + if (TypeUtils::isFloat(typeId) || TypeUtils::isVec(typeId)) { uint32_t regId = BaseReg::kIdBad; if (vecPos < CallConv::kMaxRegArgsPerGroup) - regId = cc._passedOrder[Reg::kGroupVec].id[vecPos]; + regId = cc._passedOrder[RegGroup::kVec].id[vecPos]; - if (Type::isFloat(typeId)) { - // If this is a float, but `kFlagPassFloatsByVec` is false, we have - // to use stack instead. This should be only used by 32-bit calling - // conventions. - if (!cc.hasFlag(CallConv::kFlagPassFloatsByVec)) + if (TypeUtils::isFloat(typeId)) { + // If this is a float, but `kFlagPassFloatsByVec` is false, we have to use stack instead. This should + // be only used by 32-bit calling conventions. + if (!cc.hasFlag(CallConvFlags::kPassFloatsByVec)) regId = BaseReg::kIdBad; } else { - // Pass vector registers via stack if this is a variable arguments - // function. This should be only used by 32-bit calling conventions. - if (signature.hasVarArgs() && cc.hasFlag(CallConv::kFlagPassVecByStackIfVA)) + // Pass vector registers via stack if this is a variable arguments function. This should be only used + // by 32-bit calling conventions. + if (signature.hasVarArgs() && cc.hasFlag(CallConvFlags::kPassVecByStackIfVA)) regId = BaseReg::kIdBad; } if (regId != BaseReg::kIdBad) { arg.initTypeId(typeId); arg.assignRegData(vecTypeIdToRegType(typeId), regId); - func.addUsedRegs(Reg::kGroupVec, Support::bitMask(regId)); + func.addUsedRegs(RegGroup::kVec, Support::bitMask(regId)); vecPos++; } else { - uint32_t size = Type::sizeOf(typeId); + uint32_t size = TypeUtils::sizeOf(typeId); arg.assignStackOffset(int32_t(stackOffset)); stackOffset += size; } @@ -426,12 +400,11 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si break; } - case CallConv::kStrategyX64Windows: - case CallConv::kStrategyX64VectorCall: { - // Both X64 and VectorCall behave similarly - arguments are indexed - // from left to right. The position of the argument determines in - // which register the argument is allocated, so it's either GP or - // one of XMM/YMM/ZMM registers. + case CallConvStrategy::kX64Windows: + case CallConvStrategy::kX64VectorCall: { + // Both X64 and VectorCall behave similarly - arguments are indexed from left to right. The position of the + // argument determines in which register the argument is allocated, so it's either GP or one of XMM/YMM/ZMM + // registers. // // [ X64 ] [VecCall] // Index: #0 #1 #2 #3 #4 #5 @@ -445,7 +418,7 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si // RCX XMM1 R8 XMM3 // // Unused vector registers are used by HVA. - bool isVectorCall = (cc.strategy() == CallConv::kStrategyX64VectorCall); + bool isVectorCall = (cc.strategy() == CallConvStrategy::kX64VectorCall); for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { unpackValues(func, func._args[argIndex]); @@ -457,19 +430,19 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si if (!arg) break; - uint32_t typeId = arg.typeId(); - uint32_t size = Type::sizeOf(typeId); + TypeId typeId = arg.typeId(); + uint32_t size = TypeUtils::sizeOf(typeId); - if (Type::isInt(typeId) || Type::isMmx(typeId)) { + if (TypeUtils::isInt(typeId) || TypeUtils::isMmx(typeId)) { uint32_t regId = BaseReg::kIdBad; if (argIndex < CallConv::kMaxRegArgsPerGroup) - regId = cc._passedOrder[Reg::kGroupGp].id[argIndex]; + regId = cc._passedOrder[RegGroup::kGp].id[argIndex]; if (regId != BaseReg::kIdBad) { - uint32_t regType = (size <= 4 && !Type::isMmx(typeId)) ? Reg::kTypeGpd : Reg::kTypeGpq; + RegType regType = size <= 4 && !TypeUtils::isMmx(typeId) ? RegType::kX86_Gpd : RegType::kX86_Gpq; arg.assignRegData(regType, regId); - func.addUsedRegs(Reg::kGroupGp, Support::bitMask(regId)); + func.addUsedRegs(RegGroup::kGp, Support::bitMask(regId)); } else { arg.assignStackOffset(int32_t(stackOffset)); @@ -478,33 +451,32 @@ ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& si continue; } - if (Type::isFloat(typeId) || Type::isVec(typeId)) { + if (TypeUtils::isFloat(typeId) || TypeUtils::isVec(typeId)) { uint32_t regId = BaseReg::kIdBad; if (argIndex < CallConv::kMaxRegArgsPerGroup) - regId = cc._passedOrder[Reg::kGroupVec].id[argIndex]; + regId = cc._passedOrder[RegGroup::kVec].id[argIndex]; if (regId != BaseReg::kIdBad) { - // X64-ABI doesn't allow vector types (XMM|YMM|ZMM) to be passed - // via registers, however, VectorCall was designed for that purpose. - if (Type::isFloat(typeId) || isVectorCall) { - uint32_t regType = vecTypeIdToRegType(typeId); + // X64-ABI doesn't allow vector types (XMM|YMM|ZMM) to be passed via registers, however, VectorCall + // was designed for that purpose. + if (TypeUtils::isFloat(typeId) || isVectorCall) { + RegType regType = vecTypeIdToRegType(typeId); arg.assignRegData(regType, regId); - func.addUsedRegs(Reg::kGroupVec, Support::bitMask(regId)); + func.addUsedRegs(RegGroup::kVec, Support::bitMask(regId)); continue; } } - // Passed via stack if the argument is float/double or indirectly. - // The trap is - if the argument is passed indirectly, the address - // can be passed via register, if the argument's index has GP one. - if (Type::isFloat(typeId)) { + // Passed via stack if the argument is float/double or indirectly. The trap is - if the argument is + // passed indirectly, the address can be passed via register, if the argument's index has GP one. + if (TypeUtils::isFloat(typeId)) { arg.assignStackOffset(int32_t(stackOffset)); } else { - uint32_t gpRegId = cc._passedOrder[Reg::kGroupGp].id[argIndex]; + uint32_t gpRegId = cc._passedOrder[RegGroup::kGp].id[argIndex]; if (gpRegId != BaseReg::kIdBad) - arg.assignRegData(Reg::kTypeGpq, gpRegId); + arg.assignRegData(RegType::kX86_Gpq, gpRegId); else arg.assignStackOffset(int32_t(stackOffset)); arg.addFlags(FuncValue::kFlagIsIndirect); diff --git a/src/asmjit/x86/x86func_p.h b/src/asmjit/x86/x86func_p.h index 94745ca..0fe1da1 100644 --- a/src/asmjit/x86/x86func_p.h +++ b/src/asmjit/x86/x86func_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86FUNC_P_H_INCLUDED #define ASMJIT_X86_X86FUNC_P_H_INCLUDED @@ -32,15 +14,11 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::FuncInternal] -// ============================================================================ - //! X86-specific function API (calling conventions and other utilities). namespace FuncInternal { //! Initialize `CallConv` structure (X86 specific). -Error initCallConv(CallConv& cc, uint32_t ccId, const Environment& environment) noexcept; +Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept; //! Initialize `FuncDetail` (X86 specific). Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept; diff --git a/src/asmjit/x86/x86globals.h b/src/asmjit/x86/x86globals.h index 77458e7..803c813 100644 --- a/src/asmjit/x86/x86globals.h +++ b/src/asmjit/x86/x86globals.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86GLOBALS_H_INCLUDED #define ASMJIT_X86_X86GLOBALS_H_INCLUDED @@ -37,14 +19,100 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::Inst] -// ============================================================================ +//! Condition code. +enum class CondCode : uint8_t { + kO = 0x00u, //!< OF==1 + kNO = 0x01u, //!< OF==0 + kC = 0x02u, //!< CF==1 + kB = 0x02u, //!< CF==1 (unsigned < ) + kNAE = 0x02u, //!< CF==1 (unsigned < ) + kNC = 0x03u, //!< CF==0 + kAE = 0x03u, //!< CF==0 (unsigned >=) + kNB = 0x03u, //!< CF==0 (unsigned >=) + kE = 0x04u, //!< ZF==1 (any_sign ==) + kZ = 0x04u, //!< ZF==1 (any_sign ==) + kNE = 0x05u, //!< ZF==0 (any_sign !=) + kNZ = 0x05u, //!< ZF==0 (any_sign !=) + kBE = 0x06u, //!< CF==1 | ZF==1 (unsigned <=) + kNA = 0x06u, //!< CF==1 | ZF==1 (unsigned <=) + kA = 0x07u, //!< CF==0 & ZF==0 (unsigned > ) + kNBE = 0x07u, //!< CF==0 & ZF==0 (unsigned > ) + kS = 0x08u, //!< SF==1 (is negative) + kNS = 0x09u, //!< SF==0 (is positive or zero) + kP = 0x0Au, //!< PF==1 + kPE = 0x0Au, //!< PF==1 + kPO = 0x0Bu, //!< PF==0 + kNP = 0x0Bu, //!< PF==0 + kL = 0x0Cu, //!< SF!=OF (signed < ) + kNGE = 0x0Cu, //!< SF!=OF (signed < ) + kGE = 0x0Du, //!< SF==OF (signed >=) + kNL = 0x0Du, //!< SF==OF (signed >=) + kLE = 0x0Eu, //!< ZF==1 | SF!=OF (signed <=) + kNG = 0x0Eu, //!< ZF==1 | SF!=OF (signed <=) + kG = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) + kNLE = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) + + kZero = kZ, //!< Zero flag. + kNotZero = kNZ, //!< Non-zero flag. + + kSign = kS, //!< Sign flag. + kNotSign = kNS, //!< No sign flag. + + kNegative = kS, //!< Sign flag. + kPositive = kNS, //!< No sign flag. + + kOverflow = kO, //!< Overflow (signed). + kNotOverflow = kNO, //!< Not overflow (signed). + + kEqual = kE, //!< `a == b` (equal). + kNotEqual = kNE, //!< `a != b` (not equal). + + kSignedLT = kL, //!< `a < b` (signed). + kSignedLE = kLE, //!< `a <= b` (signed). + kSignedGT = kG, //!< `a > b` (signed). + kSignedGE = kGE, //!< `a >= b` (signed). + + kUnsignedLT = kB, //!< `a < b` (unsigned). + kUnsignedLE = kBE, //!< `a <= b` (unsigned). + kUnsignedGT = kA, //!< `a > b` (unsigned). + kUnsignedGE = kAE, //!< `a >= b` (unsigned). + + kParityEven = kP, //!< Even parity flag. + kParityOdd = kPO, //!< Odd parity flag. + + kMaxValue = 0x0Fu +}; + +//! \cond +static constexpr CondCode _reverseCondTable[] = { + CondCode::kO, // O <- O + CondCode::kNO, // NO <- NO + CondCode::kA , // A <- B + CondCode::kBE, // BE <- AE + CondCode::kE, // E <- E + CondCode::kNE, // NE <- NE + CondCode::kAE, // AE <- BE + CondCode::kB , // B <- A + CondCode::kS, // S <- S + CondCode::kNS, // NS <- NS + CondCode::kPE, // PE <- PE + CondCode::kPO, // PO <- PO + CondCode::kG, // G <- L + CondCode::kLE, // LE <- GE + CondCode::kGE, // GE <- LE + CondCode::kL // L <- G +}; +//! \endcond + +//! Reverses a condition code (reverses the corresponding operands of a comparison). +static inline constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; } +//! Negates a condition code. +static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ 1u); } //! Instruction. //! -//! \note Only used to hold x86-specific enumerations and static functions. -struct Inst : public BaseInst { +//! \note Only used to hold x86-specific instruction identifiers and some additional helper functions. +namespace Inst { //! Instruction id. enum Id : uint32_t { // ${InstId:Begin} @@ -851,8 +919,10 @@ struct Inst : public BaseInst { kIdV4fnmaddps, //!< Instruction 'v4fnmaddps' {AVX512_4FMAPS}. kIdV4fnmaddss, //!< Instruction 'v4fnmaddss' {AVX512_4FMAPS}. kIdVaddpd, //!< Instruction 'vaddpd' {AVX|AVX512_F+VL}. + kIdVaddph, //!< Instruction 'vaddph' {AVX512_FP16+VL}. kIdVaddps, //!< Instruction 'vaddps' {AVX|AVX512_F+VL}. kIdVaddsd, //!< Instruction 'vaddsd' {AVX|AVX512_F}. + kIdVaddsh, //!< Instruction 'vaddsh' {AVX512_FP16}. kIdVaddss, //!< Instruction 'vaddss' {AVX|AVX512_F}. kIdVaddsubpd, //!< Instruction 'vaddsubpd' {AVX}. kIdVaddsubps, //!< Instruction 'vaddsubps' {AVX}. @@ -889,61 +959,98 @@ struct Inst : public BaseInst { kIdVbroadcastsd, //!< Instruction 'vbroadcastsd' {AVX|AVX2|AVX512_F+VL}. kIdVbroadcastss, //!< Instruction 'vbroadcastss' {AVX|AVX2|AVX512_F+VL}. kIdVcmppd, //!< Instruction 'vcmppd' {AVX|AVX512_F+VL}. + kIdVcmpph, //!< Instruction 'vcmpph' {AVX512_FP16+VL}. kIdVcmpps, //!< Instruction 'vcmpps' {AVX|AVX512_F+VL}. kIdVcmpsd, //!< Instruction 'vcmpsd' {AVX|AVX512_F}. + kIdVcmpsh, //!< Instruction 'vcmpsh' {AVX512_FP16}. kIdVcmpss, //!< Instruction 'vcmpss' {AVX|AVX512_F}. kIdVcomisd, //!< Instruction 'vcomisd' {AVX|AVX512_F}. + kIdVcomish, //!< Instruction 'vcomish' {AVX512_FP16}. kIdVcomiss, //!< Instruction 'vcomiss' {AVX|AVX512_F}. kIdVcompresspd, //!< Instruction 'vcompresspd' {AVX512_F+VL}. kIdVcompressps, //!< Instruction 'vcompressps' {AVX512_F+VL}. kIdVcvtdq2pd, //!< Instruction 'vcvtdq2pd' {AVX|AVX512_F+VL}. + kIdVcvtdq2ph, //!< Instruction 'vcvtdq2ph' {AVX512_FP16+VL}. kIdVcvtdq2ps, //!< Instruction 'vcvtdq2ps' {AVX|AVX512_F+VL}. kIdVcvtne2ps2bf16, //!< Instruction 'vcvtne2ps2bf16' {AVX512_BF16+VL}. kIdVcvtneps2bf16, //!< Instruction 'vcvtneps2bf16' {AVX512_BF16+VL}. kIdVcvtpd2dq, //!< Instruction 'vcvtpd2dq' {AVX|AVX512_F+VL}. + kIdVcvtpd2ph, //!< Instruction 'vcvtpd2ph' {AVX512_FP16+VL}. kIdVcvtpd2ps, //!< Instruction 'vcvtpd2ps' {AVX|AVX512_F+VL}. kIdVcvtpd2qq, //!< Instruction 'vcvtpd2qq' {AVX512_DQ+VL}. kIdVcvtpd2udq, //!< Instruction 'vcvtpd2udq' {AVX512_F+VL}. kIdVcvtpd2uqq, //!< Instruction 'vcvtpd2uqq' {AVX512_DQ+VL}. + kIdVcvtph2dq, //!< Instruction 'vcvtph2dq' {AVX512_FP16+VL}. + kIdVcvtph2pd, //!< Instruction 'vcvtph2pd' {AVX512_FP16+VL}. kIdVcvtph2ps, //!< Instruction 'vcvtph2ps' {AVX512_F+VL & F16C}. + kIdVcvtph2psx, //!< Instruction 'vcvtph2psx' {AVX512_FP16+VL}. + kIdVcvtph2qq, //!< Instruction 'vcvtph2qq' {AVX512_FP16+VL}. + kIdVcvtph2udq, //!< Instruction 'vcvtph2udq' {AVX512_FP16+VL}. + kIdVcvtph2uqq, //!< Instruction 'vcvtph2uqq' {AVX512_FP16+VL}. + kIdVcvtph2uw, //!< Instruction 'vcvtph2uw' {AVX512_FP16+VL}. + kIdVcvtph2w, //!< Instruction 'vcvtph2w' {AVX512_FP16+VL}. kIdVcvtps2dq, //!< Instruction 'vcvtps2dq' {AVX|AVX512_F+VL}. kIdVcvtps2pd, //!< Instruction 'vcvtps2pd' {AVX|AVX512_F+VL}. kIdVcvtps2ph, //!< Instruction 'vcvtps2ph' {AVX512_F+VL & F16C}. + kIdVcvtps2phx, //!< Instruction 'vcvtps2phx' {AVX512_FP16+VL}. kIdVcvtps2qq, //!< Instruction 'vcvtps2qq' {AVX512_DQ+VL}. kIdVcvtps2udq, //!< Instruction 'vcvtps2udq' {AVX512_F+VL}. kIdVcvtps2uqq, //!< Instruction 'vcvtps2uqq' {AVX512_DQ+VL}. kIdVcvtqq2pd, //!< Instruction 'vcvtqq2pd' {AVX512_DQ+VL}. + kIdVcvtqq2ph, //!< Instruction 'vcvtqq2ph' {AVX512_FP16+VL}. kIdVcvtqq2ps, //!< Instruction 'vcvtqq2ps' {AVX512_DQ+VL}. + kIdVcvtsd2sh, //!< Instruction 'vcvtsd2sh' {AVX512_FP16}. kIdVcvtsd2si, //!< Instruction 'vcvtsd2si' {AVX|AVX512_F}. kIdVcvtsd2ss, //!< Instruction 'vcvtsd2ss' {AVX|AVX512_F}. kIdVcvtsd2usi, //!< Instruction 'vcvtsd2usi' {AVX512_F}. + kIdVcvtsh2sd, //!< Instruction 'vcvtsh2sd' {AVX512_FP16}. + kIdVcvtsh2si, //!< Instruction 'vcvtsh2si' {AVX512_FP16}. + kIdVcvtsh2ss, //!< Instruction 'vcvtsh2ss' {AVX512_FP16}. + kIdVcvtsh2usi, //!< Instruction 'vcvtsh2usi' {AVX512_FP16}. kIdVcvtsi2sd, //!< Instruction 'vcvtsi2sd' {AVX|AVX512_F}. + kIdVcvtsi2sh, //!< Instruction 'vcvtsi2sh' {AVX512_FP16}. kIdVcvtsi2ss, //!< Instruction 'vcvtsi2ss' {AVX|AVX512_F}. kIdVcvtss2sd, //!< Instruction 'vcvtss2sd' {AVX|AVX512_F}. + kIdVcvtss2sh, //!< Instruction 'vcvtss2sh' {AVX512_FP16}. kIdVcvtss2si, //!< Instruction 'vcvtss2si' {AVX|AVX512_F}. kIdVcvtss2usi, //!< Instruction 'vcvtss2usi' {AVX512_F}. kIdVcvttpd2dq, //!< Instruction 'vcvttpd2dq' {AVX|AVX512_F+VL}. kIdVcvttpd2qq, //!< Instruction 'vcvttpd2qq' {AVX512_F+VL}. kIdVcvttpd2udq, //!< Instruction 'vcvttpd2udq' {AVX512_F+VL}. kIdVcvttpd2uqq, //!< Instruction 'vcvttpd2uqq' {AVX512_DQ+VL}. + kIdVcvttph2dq, //!< Instruction 'vcvttph2dq' {AVX512_FP16+VL}. + kIdVcvttph2qq, //!< Instruction 'vcvttph2qq' {AVX512_FP16+VL}. + kIdVcvttph2udq, //!< Instruction 'vcvttph2udq' {AVX512_FP16+VL}. + kIdVcvttph2uqq, //!< Instruction 'vcvttph2uqq' {AVX512_FP16+VL}. + kIdVcvttph2uw, //!< Instruction 'vcvttph2uw' {AVX512_FP16+VL}. + kIdVcvttph2w, //!< Instruction 'vcvttph2w' {AVX512_FP16+VL}. kIdVcvttps2dq, //!< Instruction 'vcvttps2dq' {AVX|AVX512_F+VL}. kIdVcvttps2qq, //!< Instruction 'vcvttps2qq' {AVX512_DQ+VL}. kIdVcvttps2udq, //!< Instruction 'vcvttps2udq' {AVX512_F+VL}. kIdVcvttps2uqq, //!< Instruction 'vcvttps2uqq' {AVX512_DQ+VL}. kIdVcvttsd2si, //!< Instruction 'vcvttsd2si' {AVX|AVX512_F}. kIdVcvttsd2usi, //!< Instruction 'vcvttsd2usi' {AVX512_F}. + kIdVcvttsh2si, //!< Instruction 'vcvttsh2si' {AVX512_FP16}. + kIdVcvttsh2usi, //!< Instruction 'vcvttsh2usi' {AVX512_FP16}. kIdVcvttss2si, //!< Instruction 'vcvttss2si' {AVX|AVX512_F}. kIdVcvttss2usi, //!< Instruction 'vcvttss2usi' {AVX512_F}. kIdVcvtudq2pd, //!< Instruction 'vcvtudq2pd' {AVX512_F+VL}. + kIdVcvtudq2ph, //!< Instruction 'vcvtudq2ph' {AVX512_FP16+VL}. kIdVcvtudq2ps, //!< Instruction 'vcvtudq2ps' {AVX512_F+VL}. kIdVcvtuqq2pd, //!< Instruction 'vcvtuqq2pd' {AVX512_DQ+VL}. + kIdVcvtuqq2ph, //!< Instruction 'vcvtuqq2ph' {AVX512_FP16+VL}. kIdVcvtuqq2ps, //!< Instruction 'vcvtuqq2ps' {AVX512_DQ+VL}. kIdVcvtusi2sd, //!< Instruction 'vcvtusi2sd' {AVX512_F}. + kIdVcvtusi2sh, //!< Instruction 'vcvtusi2sh' {AVX512_FP16}. kIdVcvtusi2ss, //!< Instruction 'vcvtusi2ss' {AVX512_F}. + kIdVcvtuw2ph, //!< Instruction 'vcvtuw2ph' {AVX512_FP16+VL}. + kIdVcvtw2ph, //!< Instruction 'vcvtw2ph' {AVX512_FP16+VL}. kIdVdbpsadbw, //!< Instruction 'vdbpsadbw' {AVX512_BW+VL}. kIdVdivpd, //!< Instruction 'vdivpd' {AVX|AVX512_F+VL}. + kIdVdivph, //!< Instruction 'vdivph' {AVX512_FP16+VL}. kIdVdivps, //!< Instruction 'vdivps' {AVX|AVX512_F+VL}. kIdVdivsd, //!< Instruction 'vdivsd' {AVX|AVX512_F}. + kIdVdivsh, //!< Instruction 'vdivsh' {AVX512_FP16}. kIdVdivss, //!< Instruction 'vdivss' {AVX|AVX512_F}. kIdVdpbf16ps, //!< Instruction 'vdpbf16ps' {AVX512_BF16+VL}. kIdVdppd, //!< Instruction 'vdppd' {AVX}. @@ -965,51 +1072,75 @@ struct Inst : public BaseInst { kIdVextracti64x2, //!< Instruction 'vextracti64x2' {AVX512_DQ+VL}. kIdVextracti64x4, //!< Instruction 'vextracti64x4' {AVX512_F}. kIdVextractps, //!< Instruction 'vextractps' {AVX|AVX512_F}. + kIdVfcmaddcph, //!< Instruction 'vfcmaddcph' {AVX512_FP16+VL}. + kIdVfcmaddcsh, //!< Instruction 'vfcmaddcsh' {AVX512_FP16+VL}. + kIdVfcmulcph, //!< Instruction 'vfcmulcph' {AVX512_FP16+VL}. + kIdVfcmulcsh, //!< Instruction 'vfcmulcsh' {AVX512_FP16+VL}. kIdVfixupimmpd, //!< Instruction 'vfixupimmpd' {AVX512_F+VL}. kIdVfixupimmps, //!< Instruction 'vfixupimmps' {AVX512_F+VL}. kIdVfixupimmsd, //!< Instruction 'vfixupimmsd' {AVX512_F}. kIdVfixupimmss, //!< Instruction 'vfixupimmss' {AVX512_F}. kIdVfmadd132pd, //!< Instruction 'vfmadd132pd' {FMA|AVX512_F+VL}. + kIdVfmadd132ph, //!< Instruction 'vfmadd132ph' {AVX512_FP16+VL}. kIdVfmadd132ps, //!< Instruction 'vfmadd132ps' {FMA|AVX512_F+VL}. kIdVfmadd132sd, //!< Instruction 'vfmadd132sd' {FMA|AVX512_F}. + kIdVfmadd132sh, //!< Instruction 'vfmadd132sh' {AVX512_FP16}. kIdVfmadd132ss, //!< Instruction 'vfmadd132ss' {FMA|AVX512_F}. kIdVfmadd213pd, //!< Instruction 'vfmadd213pd' {FMA|AVX512_F+VL}. + kIdVfmadd213ph, //!< Instruction 'vfmadd213ph' {AVX512_FP16+VL}. kIdVfmadd213ps, //!< Instruction 'vfmadd213ps' {FMA|AVX512_F+VL}. kIdVfmadd213sd, //!< Instruction 'vfmadd213sd' {FMA|AVX512_F}. + kIdVfmadd213sh, //!< Instruction 'vfmadd213sh' {AVX512_FP16}. kIdVfmadd213ss, //!< Instruction 'vfmadd213ss' {FMA|AVX512_F}. kIdVfmadd231pd, //!< Instruction 'vfmadd231pd' {FMA|AVX512_F+VL}. + kIdVfmadd231ph, //!< Instruction 'vfmadd231ph' {AVX512_FP16+VL}. kIdVfmadd231ps, //!< Instruction 'vfmadd231ps' {FMA|AVX512_F+VL}. kIdVfmadd231sd, //!< Instruction 'vfmadd231sd' {FMA|AVX512_F}. + kIdVfmadd231sh, //!< Instruction 'vfmadd231sh' {AVX512_FP16}. kIdVfmadd231ss, //!< Instruction 'vfmadd231ss' {FMA|AVX512_F}. + kIdVfmaddcph, //!< Instruction 'vfmaddcph' {AVX512_FP16+VL}. + kIdVfmaddcsh, //!< Instruction 'vfmaddcsh' {AVX512_FP16+VL}. kIdVfmaddpd, //!< Instruction 'vfmaddpd' {FMA4}. kIdVfmaddps, //!< Instruction 'vfmaddps' {FMA4}. kIdVfmaddsd, //!< Instruction 'vfmaddsd' {FMA4}. kIdVfmaddss, //!< Instruction 'vfmaddss' {FMA4}. kIdVfmaddsub132pd, //!< Instruction 'vfmaddsub132pd' {FMA|AVX512_F+VL}. + kIdVfmaddsub132ph, //!< Instruction 'vfmaddsub132ph' {AVX512_FP16+VL}. kIdVfmaddsub132ps, //!< Instruction 'vfmaddsub132ps' {FMA|AVX512_F+VL}. kIdVfmaddsub213pd, //!< Instruction 'vfmaddsub213pd' {FMA|AVX512_F+VL}. + kIdVfmaddsub213ph, //!< Instruction 'vfmaddsub213ph' {AVX512_FP16+VL}. kIdVfmaddsub213ps, //!< Instruction 'vfmaddsub213ps' {FMA|AVX512_F+VL}. kIdVfmaddsub231pd, //!< Instruction 'vfmaddsub231pd' {FMA|AVX512_F+VL}. + kIdVfmaddsub231ph, //!< Instruction 'vfmaddsub231ph' {AVX512_FP16+VL}. kIdVfmaddsub231ps, //!< Instruction 'vfmaddsub231ps' {FMA|AVX512_F+VL}. kIdVfmaddsubpd, //!< Instruction 'vfmaddsubpd' {FMA4}. kIdVfmaddsubps, //!< Instruction 'vfmaddsubps' {FMA4}. kIdVfmsub132pd, //!< Instruction 'vfmsub132pd' {FMA|AVX512_F+VL}. + kIdVfmsub132ph, //!< Instruction 'vfmsub132ph' {AVX512_FP16+VL}. kIdVfmsub132ps, //!< Instruction 'vfmsub132ps' {FMA|AVX512_F+VL}. kIdVfmsub132sd, //!< Instruction 'vfmsub132sd' {FMA|AVX512_F}. + kIdVfmsub132sh, //!< Instruction 'vfmsub132sh' {AVX512_FP16}. kIdVfmsub132ss, //!< Instruction 'vfmsub132ss' {FMA|AVX512_F}. kIdVfmsub213pd, //!< Instruction 'vfmsub213pd' {FMA|AVX512_F+VL}. + kIdVfmsub213ph, //!< Instruction 'vfmsub213ph' {AVX512_FP16+VL}. kIdVfmsub213ps, //!< Instruction 'vfmsub213ps' {FMA|AVX512_F+VL}. kIdVfmsub213sd, //!< Instruction 'vfmsub213sd' {FMA|AVX512_F}. + kIdVfmsub213sh, //!< Instruction 'vfmsub213sh' {AVX512_FP16}. kIdVfmsub213ss, //!< Instruction 'vfmsub213ss' {FMA|AVX512_F}. kIdVfmsub231pd, //!< Instruction 'vfmsub231pd' {FMA|AVX512_F+VL}. + kIdVfmsub231ph, //!< Instruction 'vfmsub231ph' {AVX512_FP16+VL}. kIdVfmsub231ps, //!< Instruction 'vfmsub231ps' {FMA|AVX512_F+VL}. kIdVfmsub231sd, //!< Instruction 'vfmsub231sd' {FMA|AVX512_F}. + kIdVfmsub231sh, //!< Instruction 'vfmsub231sh' {AVX512_FP16}. kIdVfmsub231ss, //!< Instruction 'vfmsub231ss' {FMA|AVX512_F}. kIdVfmsubadd132pd, //!< Instruction 'vfmsubadd132pd' {FMA|AVX512_F+VL}. + kIdVfmsubadd132ph, //!< Instruction 'vfmsubadd132ph' {AVX512_FP16+VL}. kIdVfmsubadd132ps, //!< Instruction 'vfmsubadd132ps' {FMA|AVX512_F+VL}. kIdVfmsubadd213pd, //!< Instruction 'vfmsubadd213pd' {FMA|AVX512_F+VL}. + kIdVfmsubadd213ph, //!< Instruction 'vfmsubadd213ph' {AVX512_FP16+VL}. kIdVfmsubadd213ps, //!< Instruction 'vfmsubadd213ps' {FMA|AVX512_F+VL}. kIdVfmsubadd231pd, //!< Instruction 'vfmsubadd231pd' {FMA|AVX512_F+VL}. + kIdVfmsubadd231ph, //!< Instruction 'vfmsubadd231ph' {AVX512_FP16+VL}. kIdVfmsubadd231ps, //!< Instruction 'vfmsubadd231ps' {FMA|AVX512_F+VL}. kIdVfmsubaddpd, //!< Instruction 'vfmsubaddpd' {FMA4}. kIdVfmsubaddps, //!< Instruction 'vfmsubaddps' {FMA4}. @@ -1017,41 +1148,57 @@ struct Inst : public BaseInst { kIdVfmsubps, //!< Instruction 'vfmsubps' {FMA4}. kIdVfmsubsd, //!< Instruction 'vfmsubsd' {FMA4}. kIdVfmsubss, //!< Instruction 'vfmsubss' {FMA4}. + kIdVfmulcph, //!< Instruction 'vfmulcph' {AVX512_FP16+VL}. + kIdVfmulcsh, //!< Instruction 'vfmulcsh' {AVX512_FP16+VL}. kIdVfnmadd132pd, //!< Instruction 'vfnmadd132pd' {FMA|AVX512_F+VL}. + kIdVfnmadd132ph, //!< Instruction 'vfnmadd132ph' {AVX512_FP16+VL}. kIdVfnmadd132ps, //!< Instruction 'vfnmadd132ps' {FMA|AVX512_F+VL}. kIdVfnmadd132sd, //!< Instruction 'vfnmadd132sd' {FMA|AVX512_F}. + kIdVfnmadd132sh, //!< Instruction 'vfnmadd132sh' {AVX512_FP16}. kIdVfnmadd132ss, //!< Instruction 'vfnmadd132ss' {FMA|AVX512_F}. kIdVfnmadd213pd, //!< Instruction 'vfnmadd213pd' {FMA|AVX512_F+VL}. + kIdVfnmadd213ph, //!< Instruction 'vfnmadd213ph' {AVX512_FP16+VL}. kIdVfnmadd213ps, //!< Instruction 'vfnmadd213ps' {FMA|AVX512_F+VL}. kIdVfnmadd213sd, //!< Instruction 'vfnmadd213sd' {FMA|AVX512_F}. + kIdVfnmadd213sh, //!< Instruction 'vfnmadd213sh' {AVX512_FP16}. kIdVfnmadd213ss, //!< Instruction 'vfnmadd213ss' {FMA|AVX512_F}. kIdVfnmadd231pd, //!< Instruction 'vfnmadd231pd' {FMA|AVX512_F+VL}. + kIdVfnmadd231ph, //!< Instruction 'vfnmadd231ph' {AVX512_FP16+VL}. kIdVfnmadd231ps, //!< Instruction 'vfnmadd231ps' {FMA|AVX512_F+VL}. kIdVfnmadd231sd, //!< Instruction 'vfnmadd231sd' {FMA|AVX512_F}. + kIdVfnmadd231sh, //!< Instruction 'vfnmadd231sh' {AVX512_FP16}. kIdVfnmadd231ss, //!< Instruction 'vfnmadd231ss' {FMA|AVX512_F}. kIdVfnmaddpd, //!< Instruction 'vfnmaddpd' {FMA4}. kIdVfnmaddps, //!< Instruction 'vfnmaddps' {FMA4}. kIdVfnmaddsd, //!< Instruction 'vfnmaddsd' {FMA4}. kIdVfnmaddss, //!< Instruction 'vfnmaddss' {FMA4}. kIdVfnmsub132pd, //!< Instruction 'vfnmsub132pd' {FMA|AVX512_F+VL}. + kIdVfnmsub132ph, //!< Instruction 'vfnmsub132ph' {AVX512_FP16+VL}. kIdVfnmsub132ps, //!< Instruction 'vfnmsub132ps' {FMA|AVX512_F+VL}. kIdVfnmsub132sd, //!< Instruction 'vfnmsub132sd' {FMA|AVX512_F}. + kIdVfnmsub132sh, //!< Instruction 'vfnmsub132sh' {AVX512_FP16}. kIdVfnmsub132ss, //!< Instruction 'vfnmsub132ss' {FMA|AVX512_F}. kIdVfnmsub213pd, //!< Instruction 'vfnmsub213pd' {FMA|AVX512_F+VL}. + kIdVfnmsub213ph, //!< Instruction 'vfnmsub213ph' {AVX512_FP16+VL}. kIdVfnmsub213ps, //!< Instruction 'vfnmsub213ps' {FMA|AVX512_F+VL}. kIdVfnmsub213sd, //!< Instruction 'vfnmsub213sd' {FMA|AVX512_F}. + kIdVfnmsub213sh, //!< Instruction 'vfnmsub213sh' {AVX512_FP16}. kIdVfnmsub213ss, //!< Instruction 'vfnmsub213ss' {FMA|AVX512_F}. kIdVfnmsub231pd, //!< Instruction 'vfnmsub231pd' {FMA|AVX512_F+VL}. + kIdVfnmsub231ph, //!< Instruction 'vfnmsub231ph' {AVX512_FP16+VL}. kIdVfnmsub231ps, //!< Instruction 'vfnmsub231ps' {FMA|AVX512_F+VL}. kIdVfnmsub231sd, //!< Instruction 'vfnmsub231sd' {FMA|AVX512_F}. + kIdVfnmsub231sh, //!< Instruction 'vfnmsub231sh' {AVX512_FP16}. kIdVfnmsub231ss, //!< Instruction 'vfnmsub231ss' {FMA|AVX512_F}. kIdVfnmsubpd, //!< Instruction 'vfnmsubpd' {FMA4}. kIdVfnmsubps, //!< Instruction 'vfnmsubps' {FMA4}. kIdVfnmsubsd, //!< Instruction 'vfnmsubsd' {FMA4}. kIdVfnmsubss, //!< Instruction 'vfnmsubss' {FMA4}. kIdVfpclasspd, //!< Instruction 'vfpclasspd' {AVX512_DQ+VL}. + kIdVfpclassph, //!< Instruction 'vfpclassph' {AVX512_FP16+VL}. kIdVfpclassps, //!< Instruction 'vfpclassps' {AVX512_DQ+VL}. kIdVfpclasssd, //!< Instruction 'vfpclasssd' {AVX512_DQ}. + kIdVfpclasssh, //!< Instruction 'vfpclasssh' {AVX512_FP16}. kIdVfpclassss, //!< Instruction 'vfpclassss' {AVX512_DQ}. kIdVfrczpd, //!< Instruction 'vfrczpd' {XOP}. kIdVfrczps, //!< Instruction 'vfrczps' {XOP}. @@ -1070,12 +1217,16 @@ struct Inst : public BaseInst { kIdVgatherqpd, //!< Instruction 'vgatherqpd' {AVX2|AVX512_F+VL}. kIdVgatherqps, //!< Instruction 'vgatherqps' {AVX2|AVX512_F+VL}. kIdVgetexppd, //!< Instruction 'vgetexppd' {AVX512_F+VL}. + kIdVgetexpph, //!< Instruction 'vgetexpph' {AVX512_FP16+VL}. kIdVgetexpps, //!< Instruction 'vgetexpps' {AVX512_F+VL}. kIdVgetexpsd, //!< Instruction 'vgetexpsd' {AVX512_F}. + kIdVgetexpsh, //!< Instruction 'vgetexpsh' {AVX512_FP16}. kIdVgetexpss, //!< Instruction 'vgetexpss' {AVX512_F}. kIdVgetmantpd, //!< Instruction 'vgetmantpd' {AVX512_F+VL}. + kIdVgetmantph, //!< Instruction 'vgetmantph' {AVX512_FP16+VL}. kIdVgetmantps, //!< Instruction 'vgetmantps' {AVX512_F+VL}. kIdVgetmantsd, //!< Instruction 'vgetmantsd' {AVX512_F}. + kIdVgetmantsh, //!< Instruction 'vgetmantsh' {AVX512_FP16}. kIdVgetmantss, //!< Instruction 'vgetmantss' {AVX512_F}. kIdVgf2p8affineinvqb, //!< Instruction 'vgf2p8affineinvqb' {AVX|AVX512_F+VL & GFNI}. kIdVgf2p8affineqb, //!< Instruction 'vgf2p8affineqb' {AVX|AVX512_F+VL & GFNI}. @@ -1101,15 +1252,19 @@ struct Inst : public BaseInst { kIdVmaskmovpd, //!< Instruction 'vmaskmovpd' {AVX}. kIdVmaskmovps, //!< Instruction 'vmaskmovps' {AVX}. kIdVmaxpd, //!< Instruction 'vmaxpd' {AVX|AVX512_F+VL}. + kIdVmaxph, //!< Instruction 'vmaxph' {AVX512_FP16+VL}. kIdVmaxps, //!< Instruction 'vmaxps' {AVX|AVX512_F+VL}. kIdVmaxsd, //!< Instruction 'vmaxsd' {AVX|AVX512_F+VL}. + kIdVmaxsh, //!< Instruction 'vmaxsh' {AVX512_FP16}. kIdVmaxss, //!< Instruction 'vmaxss' {AVX|AVX512_F+VL}. kIdVmcall, //!< Instruction 'vmcall' {VMX}. kIdVmclear, //!< Instruction 'vmclear' {VMX}. kIdVmfunc, //!< Instruction 'vmfunc' {VMX}. kIdVminpd, //!< Instruction 'vminpd' {AVX|AVX512_F+VL}. + kIdVminph, //!< Instruction 'vminph' {AVX512_FP16+VL}. kIdVminps, //!< Instruction 'vminps' {AVX|AVX512_F+VL}. kIdVminsd, //!< Instruction 'vminsd' {AVX|AVX512_F+VL}. + kIdVminsh, //!< Instruction 'vminsh' {AVX512_FP16}. kIdVminss, //!< Instruction 'vminss' {AVX|AVX512_F+VL}. kIdVmlaunch, //!< Instruction 'vmlaunch' {VMX}. kIdVmload, //!< Instruction 'vmload' {SVM}. @@ -1140,11 +1295,13 @@ struct Inst : public BaseInst { kIdVmovntps, //!< Instruction 'vmovntps' {AVX|AVX512_F+VL}. kIdVmovq, //!< Instruction 'vmovq' {AVX|AVX512_F}. kIdVmovsd, //!< Instruction 'vmovsd' {AVX|AVX512_F}. + kIdVmovsh, //!< Instruction 'vmovsh' {AVX512_FP16}. kIdVmovshdup, //!< Instruction 'vmovshdup' {AVX|AVX512_F+VL}. kIdVmovsldup, //!< Instruction 'vmovsldup' {AVX|AVX512_F+VL}. kIdVmovss, //!< Instruction 'vmovss' {AVX|AVX512_F}. kIdVmovupd, //!< Instruction 'vmovupd' {AVX|AVX512_F+VL}. kIdVmovups, //!< Instruction 'vmovups' {AVX|AVX512_F+VL}. + kIdVmovw, //!< Instruction 'vmovw' {AVX512_FP16}. kIdVmpsadbw, //!< Instruction 'vmpsadbw' {AVX|AVX2}. kIdVmptrld, //!< Instruction 'vmptrld' {VMX}. kIdVmptrst, //!< Instruction 'vmptrst' {VMX}. @@ -1153,8 +1310,10 @@ struct Inst : public BaseInst { kIdVmrun, //!< Instruction 'vmrun' {SVM}. kIdVmsave, //!< Instruction 'vmsave' {SVM}. kIdVmulpd, //!< Instruction 'vmulpd' {AVX|AVX512_F+VL}. + kIdVmulph, //!< Instruction 'vmulph' {AVX512_FP16+VL}. kIdVmulps, //!< Instruction 'vmulps' {AVX|AVX512_F+VL}. kIdVmulsd, //!< Instruction 'vmulsd' {AVX|AVX512_F}. + kIdVmulsh, //!< Instruction 'vmulsh' {AVX512_FP16}. kIdVmulss, //!< Instruction 'vmulss' {AVX|AVX512_F}. kIdVmwrite, //!< Instruction 'vmwrite' {VMX}. kIdVmxon, //!< Instruction 'vmxon' {VMX}. @@ -1503,15 +1662,21 @@ struct Inst : public BaseInst { kIdVrcp28ps, //!< Instruction 'vrcp28ps' {AVX512_ERI}. kIdVrcp28sd, //!< Instruction 'vrcp28sd' {AVX512_ERI}. kIdVrcp28ss, //!< Instruction 'vrcp28ss' {AVX512_ERI}. + kIdVrcpph, //!< Instruction 'vrcpph' {AVX512_FP16}. kIdVrcpps, //!< Instruction 'vrcpps' {AVX}. + kIdVrcpsh, //!< Instruction 'vrcpsh' {AVX512_FP16}. kIdVrcpss, //!< Instruction 'vrcpss' {AVX}. kIdVreducepd, //!< Instruction 'vreducepd' {AVX512_DQ+VL}. + kIdVreduceph, //!< Instruction 'vreduceph' {AVX512_FP16+VL}. kIdVreduceps, //!< Instruction 'vreduceps' {AVX512_DQ+VL}. kIdVreducesd, //!< Instruction 'vreducesd' {AVX512_DQ}. + kIdVreducesh, //!< Instruction 'vreducesh' {AVX512_FP16}. kIdVreducess, //!< Instruction 'vreducess' {AVX512_DQ}. kIdVrndscalepd, //!< Instruction 'vrndscalepd' {AVX512_F+VL}. + kIdVrndscaleph, //!< Instruction 'vrndscaleph' {AVX512_FP16+VL}. kIdVrndscaleps, //!< Instruction 'vrndscaleps' {AVX512_F+VL}. kIdVrndscalesd, //!< Instruction 'vrndscalesd' {AVX512_F}. + kIdVrndscalesh, //!< Instruction 'vrndscalesh' {AVX512_FP16}. kIdVrndscaless, //!< Instruction 'vrndscaless' {AVX512_F}. kIdVroundpd, //!< Instruction 'vroundpd' {AVX}. kIdVroundps, //!< Instruction 'vroundps' {AVX}. @@ -1525,11 +1690,15 @@ struct Inst : public BaseInst { kIdVrsqrt28ps, //!< Instruction 'vrsqrt28ps' {AVX512_ERI}. kIdVrsqrt28sd, //!< Instruction 'vrsqrt28sd' {AVX512_ERI}. kIdVrsqrt28ss, //!< Instruction 'vrsqrt28ss' {AVX512_ERI}. + kIdVrsqrtph, //!< Instruction 'vrsqrtph' {AVX512_FP16+VL}. kIdVrsqrtps, //!< Instruction 'vrsqrtps' {AVX}. + kIdVrsqrtsh, //!< Instruction 'vrsqrtsh' {AVX512_FP16}. kIdVrsqrtss, //!< Instruction 'vrsqrtss' {AVX}. kIdVscalefpd, //!< Instruction 'vscalefpd' {AVX512_F+VL}. + kIdVscalefph, //!< Instruction 'vscalefph' {AVX512_FP16+VL}. kIdVscalefps, //!< Instruction 'vscalefps' {AVX512_F+VL}. kIdVscalefsd, //!< Instruction 'vscalefsd' {AVX512_F}. + kIdVscalefsh, //!< Instruction 'vscalefsh' {AVX512_FP16}. kIdVscalefss, //!< Instruction 'vscalefss' {AVX512_F}. kIdVscatterdpd, //!< Instruction 'vscatterdpd' {AVX512_F+VL}. kIdVscatterdps, //!< Instruction 'vscatterdps' {AVX512_F+VL}. @@ -1550,17 +1719,22 @@ struct Inst : public BaseInst { kIdVshufpd, //!< Instruction 'vshufpd' {AVX|AVX512_F+VL}. kIdVshufps, //!< Instruction 'vshufps' {AVX|AVX512_F+VL}. kIdVsqrtpd, //!< Instruction 'vsqrtpd' {AVX|AVX512_F+VL}. + kIdVsqrtph, //!< Instruction 'vsqrtph' {AVX512_FP16+VL}. kIdVsqrtps, //!< Instruction 'vsqrtps' {AVX|AVX512_F+VL}. kIdVsqrtsd, //!< Instruction 'vsqrtsd' {AVX|AVX512_F}. + kIdVsqrtsh, //!< Instruction 'vsqrtsh' {AVX512_FP16}. kIdVsqrtss, //!< Instruction 'vsqrtss' {AVX|AVX512_F}. kIdVstmxcsr, //!< Instruction 'vstmxcsr' {AVX}. kIdVsubpd, //!< Instruction 'vsubpd' {AVX|AVX512_F+VL}. + kIdVsubph, //!< Instruction 'vsubph' {AVX512_FP16+VL}. kIdVsubps, //!< Instruction 'vsubps' {AVX|AVX512_F+VL}. kIdVsubsd, //!< Instruction 'vsubsd' {AVX|AVX512_F}. + kIdVsubsh, //!< Instruction 'vsubsh' {AVX512_FP16}. kIdVsubss, //!< Instruction 'vsubss' {AVX|AVX512_F}. kIdVtestpd, //!< Instruction 'vtestpd' {AVX}. kIdVtestps, //!< Instruction 'vtestps' {AVX}. kIdVucomisd, //!< Instruction 'vucomisd' {AVX|AVX512_F}. + kIdVucomish, //!< Instruction 'vucomish' {AVX512_FP16}. kIdVucomiss, //!< Instruction 'vucomiss' {AVX|AVX512_F}. kIdVunpckhpd, //!< Instruction 'vunpckhpd' {AVX|AVX512_F+VL}. kIdVunpckhps, //!< Instruction 'vunpckhps' {AVX|AVX512_F+VL}. @@ -1609,560 +1783,383 @@ struct Inst : public BaseInst { // ${InstId:End} }; - //! Instruction options. - enum Options : uint32_t { - kOptionModMR = 0x00000100u, //!< Use ModMR instead of ModRM if applicable. - kOptionModRM = 0x00000200u, //!< Use ModRM instead of ModMR if applicable. - kOptionVex3 = 0x00000400u, //!< Use 3-byte VEX prefix if possible (AVX) (must be 0x00000400). - kOptionVex = 0x00000800u, //!< Use VEX prefix when both VEX|EVEX prefixes are available (HINT: AVX_VNNI). - kOptionEvex = 0x00001000u, //!< Use 4-byte EVEX prefix if possible (AVX-512) (must be 0x00001000). - - kOptionLock = 0x00002000u, //!< LOCK prefix (lock-enabled instructions only). - kOptionRep = 0x00004000u, //!< REP prefix (string instructions only). - kOptionRepne = 0x00008000u, //!< REPNE prefix (string instructions only). - - kOptionXAcquire = 0x00010000u, //!< XACQUIRE prefix (only allowed instructions). - kOptionXRelease = 0x00020000u, //!< XRELEASE prefix (only allowed instructions). - - kOptionER = 0x00040000u, //!< AVX-512: embedded-rounding {er} and implicit {sae}. - kOptionSAE = 0x00080000u, //!< AVX-512: suppress-all-exceptions {sae}. - kOptionRN_SAE = 0x00000000u, //!< AVX-512: round-to-nearest (even) {rn-sae} (bits 00). - kOptionRD_SAE = 0x00200000u, //!< AVX-512: round-down (toward -inf) {rd-sae} (bits 01). - kOptionRU_SAE = 0x00400000u, //!< AVX-512: round-up (toward +inf) {ru-sae} (bits 10). - kOptionRZ_SAE = 0x00600000u, //!< AVX-512: round-toward-zero (truncate) {rz-sae} (bits 11). - kOptionZMask = 0x00800000u, //!< AVX-512: Use zeroing {k}{z} instead of merging {k}. - _kOptionAvx512Mask = 0x00FC0000u, //!< AVX-512: Mask of all possible AVX-512 options except EVEX prefix flag. - - kOptionOpCodeB = 0x01000000u, //!< REX.B and/or VEX.B field (X64). - kOptionOpCodeX = 0x02000000u, //!< REX.X and/or VEX.X field (X64). - kOptionOpCodeR = 0x04000000u, //!< REX.R and/or VEX.R field (X64). - kOptionOpCodeW = 0x08000000u, //!< REX.W and/or VEX.W field (X64). - kOptionRex = 0x40000000u, //!< Force REX prefix (X64). - _kOptionInvalidRex = 0x80000000u //!< Invalid REX prefix (set by X86 or when AH|BH|CH|DH regs are used on X64). - }; - - // -------------------------------------------------------------------------- - // [Statics] - // -------------------------------------------------------------------------- - - //! Tests whether the `instId` is defined (counts also Inst::kIdNone, which must be zero). - static inline bool isDefinedId(uint32_t instId) noexcept { return instId < _kIdCount; } -}; - -// ============================================================================ -// [asmjit::x86::Condition] -// ============================================================================ - -namespace Condition { - //! Condition code. - enum Code : uint32_t { - kO = 0x00u, //!< OF==1 - kNO = 0x01u, //!< OF==0 - kB = 0x02u, //!< CF==1 (unsigned < ) - kC = 0x02u, //!< CF==1 - kNAE = 0x02u, //!< CF==1 (unsigned < ) - kAE = 0x03u, //!< CF==0 (unsigned >=) - kNB = 0x03u, //!< CF==0 (unsigned >=) - kNC = 0x03u, //!< CF==0 - kE = 0x04u, //!< ZF==1 (any_sign ==) - kZ = 0x04u, //!< ZF==1 (any_sign ==) - kNE = 0x05u, //!< ZF==0 (any_sign !=) - kNZ = 0x05u, //!< ZF==0 (any_sign !=) - kBE = 0x06u, //!< CF==1 | ZF==1 (unsigned <=) - kNA = 0x06u, //!< CF==1 | ZF==1 (unsigned <=) - kA = 0x07u, //!< CF==0 & ZF==0 (unsigned > ) - kNBE = 0x07u, //!< CF==0 & ZF==0 (unsigned > ) - kS = 0x08u, //!< SF==1 (is negative) - kNS = 0x09u, //!< SF==0 (is positive or zero) - kP = 0x0Au, //!< PF==1 - kPE = 0x0Au, //!< PF==1 - kPO = 0x0Bu, //!< PF==0 - kNP = 0x0Bu, //!< PF==0 - kL = 0x0Cu, //!< SF!=OF (signed < ) - kNGE = 0x0Cu, //!< SF!=OF (signed < ) - kGE = 0x0Du, //!< SF==OF (signed >=) - kNL = 0x0Du, //!< SF==OF (signed >=) - kLE = 0x0Eu, //!< ZF==1 | SF!=OF (signed <=) - kNG = 0x0Eu, //!< ZF==1 | SF!=OF (signed <=) - kG = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) - kNLE = 0x0Fu, //!< ZF==0 & SF==OF (signed > ) - kCount = 0x10u, - - kSign = kS, //!< Sign. - kNotSign = kNS, //!< Not Sign. - - kOverflow = kO, //!< Signed overflow. - kNotOverflow = kNO, //!< Not signed overflow. - - kEqual = kE, //!< Equal `a == b`. - kNotEqual = kNE, //!< Not Equal `a != b`. - - kSignedLT = kL, //!< Signed `a < b`. - kSignedLE = kLE, //!< Signed `a <= b`. - kSignedGT = kG, //!< Signed `a > b`. - kSignedGE = kGE, //!< Signed `a >= b`. - - kUnsignedLT = kB, //!< Unsigned `a < b`. - kUnsignedLE = kBE, //!< Unsigned `a <= b`. - kUnsignedGT = kA, //!< Unsigned `a > b`. - kUnsignedGE = kAE, //!< Unsigned `a >= b`. - - kZero = kZ, //!< Zero flag. - kNotZero = kNZ, //!< Non-zero flag. - - kNegative = kS, //!< Sign flag. - kPositive = kNS, //!< No sign flag. - - kParityEven = kP, //!< Even parity flag. - kParityOdd = kPO //!< Odd parity flag. - }; - - static constexpr uint8_t reverseTable[kCount] = { - kO, kNO, kA , kBE, // O|NO|B |AE - kE, kNE, kAE, kB , // E|NE|BE|A - kS, kNS, kPE, kPO, // S|NS|PE|PO - kG, kLE, kGE, kL // L|GE|LE|G - }; + //! Tests whether the `instId` is defined. + static inline constexpr bool isDefinedId(InstId instId) noexcept { return instId < _kIdCount; } + //! \cond #define ASMJIT_INST_FROM_COND(ID) \ ID##o, ID##no, ID##b , ID##ae, \ ID##e, ID##ne, ID##be, ID##a , \ ID##s, ID##ns, ID##pe, ID##po, \ ID##l, ID##ge, ID##le, ID##g - static constexpr uint16_t jccTable[] = { ASMJIT_INST_FROM_COND(Inst::kIdJ) }; - static constexpr uint16_t setccTable[] = { ASMJIT_INST_FROM_COND(Inst::kIdSet) }; - static constexpr uint16_t cmovccTable[] = { ASMJIT_INST_FROM_COND(Inst::kIdCmov) }; - #undef ASMJIT_INST_FROM_COND - //! Reverses a condition code (reverses the corresponding operands of a comparison). - static constexpr uint32_t reverse(uint32_t cond) noexcept { return reverseTable[cond]; } - //! Negates a condition code. - static constexpr uint32_t negate(uint32_t cond) noexcept { return cond ^ 1u; } + static constexpr uint16_t _jccTable[] = { ASMJIT_INST_FROM_COND(Inst::kIdJ) }; + static constexpr uint16_t _setccTable[] = { ASMJIT_INST_FROM_COND(Inst::kIdSet) }; + static constexpr uint16_t _cmovccTable[] = { ASMJIT_INST_FROM_COND(Inst::kIdCmov) }; + + #undef ASMJIT_INST_FROM_COND + //! \endcond //! Translates a condition code `cond` to a `jcc` instruction id. - static constexpr uint32_t toJcc(uint32_t cond) noexcept { return jccTable[cond]; } + static constexpr InstId jccFromCond(CondCode cond) noexcept { return _jccTable[uint8_t(cond)]; } //! Translates a condition code `cond` to a `setcc` instruction id. - static constexpr uint32_t toSetcc(uint32_t cond) noexcept { return setccTable[cond]; } + static constexpr InstId setccFromCond(CondCode cond) noexcept { return _setccTable[uint8_t(cond)]; } //! Translates a condition code `cond` to a `cmovcc` instruction id. - static constexpr uint32_t toCmovcc(uint32_t cond) noexcept { return cmovccTable[cond]; } -} + static constexpr InstId cmovccFromCond(CondCode cond) noexcept { return _cmovccTable[uint8_t(cond)]; } +} // {Inst} + +//! FPU status word bits. +enum class FpuStatusWord : uint16_t { + kNone = 0x0000u, //!< No bits set. + + kInvalid = 0x0001u, //!< Invalid operation. + kDenormalized = 0x0002u, //!< Denormalized operand. + kDivByZero = 0x0004u, //!< Division by zero. + kOverflow = 0x0008u, //!< Overflown. + kUnderflow = 0x0010u, //!< Underflown. + kPrecision = 0x0020u, //!< Precision lost. + kStackFault = 0x0040u, //!< Stack fault. + kInterrupt = 0x0080u, //!< Interrupt. + kC0 = 0x0100u, //!< C0 flag. + kC1 = 0x0200u, //!< C1 flag. + kC2 = 0x0400u, //!< C2 flag. + kTopMask = 0x3800u, //!< Top of the stack (mask). + kC3 = 0x4000u, //!< C3 flag. + kBusy = 0x8000u //!< FPU is busy. +}; +ASMJIT_DEFINE_ENUM_FLAGS(FpuStatusWord) + +//! FPU control word bits. +enum class FpuControlWord : uint16_t { + kNone = 0x0000u, //!< No bits set. + + // Bits 0-5 + // -------- + + kEM_Mask = 0x003Fu, //!< Exception mask (0x3F). + kEM_Invalid = 0x0001u, //!< Invalid operation exception. + kEM_Denormal = 0x0002u, //!< Denormalized operand exception. + kEM_DivByZero = 0x0004u, //!< Division by zero exception. + kEM_Overflow = 0x0008u, //!< Overflow exception. + kEM_Underflow = 0x0010u, //!< Underflow exception. + kEM_Inexact = 0x0020u, //!< Inexact operation exception. + + // Bits 8-9 + // -------- + + kPC_Mask = 0x0300u, //!< Precision control mask. + kPC_Float = 0x0000u, //!< Single precision (24 bits). + kPC_Reserved = 0x0100u, //!< Reserved. + kPC_Double = 0x0200u, //!< Double precision (53 bits). + kPC_Extended = 0x0300u, //!< Extended precision (64 bits). + + // Bits 10-11 + // ---------- + + kRC_Mask = 0x0C00u, //!< Rounding control mask. + kRC_Nearest = 0x0000u, //!< Round to nearest even. + kRC_Down = 0x0400u, //!< Round down (floor). + kRC_Up = 0x0800u, //!< Round up (ceil). + kRC_Truncate = 0x0C00u, //!< Round towards zero (truncate). + + // Bit 12 + // ------ + + kIC_Mask = 0x1000u, //!< Infinity control. + kIC_Projective = 0x0000u, //!< Projective (not supported on X64). + kIC_Affine = 0x1000u //!< Affine (default). +}; +ASMJIT_DEFINE_ENUM_FLAGS(FpuControlWord) + +//! An immediate value that can be used with CMP[PD|PS|SD|SS] instructions. +enum class CmpImm : uint8_t { + kEQ = 0x00u, //!< Equal (Quiet), same as \ref VCmpImm::kEQ_OQ. + kLT = 0x01u, //!< Less (Signaling), same as \ref VCmpImm::kLT_OS. + kLE = 0x02u, //!< Less/Equal (Signaling), same as \ref VCmpImm::kLE_OS. + kUNORD = 0x03u, //!< Unordered (Quiet), same as \ref VCmpImm::kUNORD_Q. + kNEQ = 0x04u, //!< Not Equal (Quiet), same as \ref VCmpImm::kNEQ_UQ. + kNLT = 0x05u, //!< Not Less (Signaling), same as \ref VCmpImm::kNLT_US. + kNLE = 0x06u, //!< Not Less/Equal (Signaling), same as \ref VCmpImm::kNLE_US. + kORD = 0x07u //!< Ordered (Quiet), same as \ref VCmpImm::kORD_Q. +}; -// ============================================================================ -// [asmjit::x86::FpuWord] -// ============================================================================ - -//! FPU control and status words. -namespace FpuWord { - //! FPU status word. - enum Status : uint32_t { - //! Invalid operation. - kStatusInvalid = 0x0001u, - //! Denormalized operand. - kStatusDenormalized = 0x0002u, - //! Division by zero. - kStatusDivByZero = 0x0004u, - //! Overflown. - kStatusOverflow = 0x0008u, - //! Underflown. - kStatusUnderflow = 0x0010u, - //! Precision lost. - kStatusPrecision = 0x0020u, - //! Stack fault. - kStatusStackFault = 0x0040u, - //! Interrupt. - kStatusInterrupt = 0x0080u, - //! C0 flag. - kStatusC0 = 0x0100u, - //! C1 flag. - kStatusC1 = 0x0200u, - //! C2 flag. - kStatusC2 = 0x0400u, - //! Top of the stack. - kStatusTop = 0x3800u, - //! C3 flag. - kStatusC3 = 0x4000u, - //! FPU is busy. - kStatusBusy = 0x8000u - }; +//! An immediate value that can be used with [V]PCMP[I|E]STR[I|M] instructions. +enum class PCmpStrImm : uint8_t { + // Source Data Format + // ------------------ - //! FPU control word. - enum Control : uint32_t { - // [Bits 0-5] - - //! Exception mask (0x3F). - kControlEM_Mask = 0x003Fu, - //! Invalid operation exception. - kControlEM_Invalid = 0x0001u, - //! Denormalized operand exception. - kControlEM_Denormal = 0x0002u, - //! Division by zero exception. - kControlEM_DivByZero = 0x0004u, - //! Overflow exception. - kControlEM_Overflow = 0x0008u, - //! Underflow exception. - kControlEM_Underflow = 0x0010u, - //! Inexact operation exception. - kControlEM_Inexact = 0x0020u, - - // [Bits 8-9] - - //! Precision control mask. - kControlPC_Mask = 0x0300u, - //! Single precision (24 bits). - kControlPC_Float = 0x0000u, - //! Reserved. - kControlPC_Reserved = 0x0100u, - //! Double precision (53 bits). - kControlPC_Double = 0x0200u, - //! Extended precision (64 bits). - kControlPC_Extended = 0x0300u, - - // [Bits 10-11] - - //! Rounding control mask. - kControlRC_Mask = 0x0C00u, - //! Round to nearest even. - kControlRC_Nearest = 0x0000u, - //! Round down (floor). - kControlRC_Down = 0x0400u, - //! Round up (ceil). - kControlRC_Up = 0x0800u, - //! Round towards zero (truncate). - kControlRC_Truncate = 0x0C00u, - - // [Bit 12] - - //! Infinity control. - kControlIC_Mask = 0x1000u, - //! Projective (not supported on X64). - kControlIC_Projective = 0x0000u, - //! Affine (default). - kControlIC_Affine = 0x1000u - }; -} + kUB = 0x00u << 0, //!< The source data format is unsigned bytes. + kUW = 0x01u << 0, //!< The source data format is unsigned words. + kSB = 0x02u << 0, //!< The source data format is signed bytes. + kSW = 0x03u << 0, //!< The source data format is signed words. -// ============================================================================ -// [asmjit::x86::Status] -// ============================================================================ - -//! CPU and FPU status flags. -namespace Status { - //! CPU and FPU status flags used by `InstRWInfo` - enum Flags : uint32_t { - // ------------------------------------------------------------------------ - // [Architecture Neutral Flags - 0x000000FF] - // ------------------------------------------------------------------------ - - //! Carry flag. - kCF = 0x00000001u, - //! Signed overflow flag. - kOF = 0x00000002u, - //! Sign flag (negative/sign, if set). - kSF = 0x00000004u, - //! Zero and/or equality flag (1 if zero/equal). - kZF = 0x00000008u, - - // ------------------------------------------------------------------------ - // [Architecture Specific Flags - 0xFFFFFF00] - // ------------------------------------------------------------------------ - - //! Adjust flag. - kAF = 0x00000100u, - //! Parity flag. - kPF = 0x00000200u, - //! Direction flag. - kDF = 0x00000400u, - //! Interrupt enable flag. - kIF = 0x00000800u, - - //! Alignment check. - kAC = 0x00001000u, - - //! FPU C0 status flag. - kC0 = 0x00010000u, - //! FPU C1 status flag. - kC1 = 0x00020000u, - //! FPU C2 status flag. - kC2 = 0x00040000u, - //! FPU C3 status flag. - kC3 = 0x00080000u - }; -} + // Aggregation Operation + // --------------------- -// ============================================================================ -// [asmjit::x86::Predicate] -// ============================================================================ - -//! Contains predicates used by SIMD instructions. -namespace Predicate { - //! A predicate used by CMP[PD|PS|SD|SS] instructions. - enum Cmp : uint32_t { - kCmpEQ = 0x00u, //!< Equal (Quiet). - kCmpLT = 0x01u, //!< Less (Signaling). - kCmpLE = 0x02u, //!< Less/Equal (Signaling). - kCmpUNORD = 0x03u, //!< Unordered (Quiet). - kCmpNEQ = 0x04u, //!< Not Equal (Quiet). - kCmpNLT = 0x05u, //!< Not Less (Signaling). - kCmpNLE = 0x06u, //!< Not Less/Equal (Signaling). - kCmpORD = 0x07u //!< Ordered (Quiet). - }; + kEqualAny = 0x00u << 2, //!< The arithmetic comparison is "equal". + kRanges = 0x01u << 2, //!< The arithmetic comparison is "greater than or equal" between even indexed + //!< elements and "less than or equal" between odd indexed elements. + kEqualEach = 0x02u << 2, //!< The arithmetic comparison is "equal". + kEqualOrdered = 0x03u << 2, //!< The arithmetic comparison is "equal". - //! A predicate used by [V]PCMP[I|E]STR[I|M] instructions. - enum PCmpStr : uint32_t { - // Source data format: - kPCmpStrUB = 0x00u << 0, //!< The source data format is unsigned bytes. - kPCmpStrUW = 0x01u << 0, //!< The source data format is unsigned words. - kPCmpStrSB = 0x02u << 0, //!< The source data format is signed bytes. - kPCmpStrSW = 0x03u << 0, //!< The source data format is signed words. - - // Aggregation operation: - kPCmpStrEqualAny = 0x00u << 2, //!< The arithmetic comparison is "equal". - kPCmpStrRanges = 0x01u << 2, //!< The arithmetic comparison is "greater than or equal" - //!< between even indexed elements and "less than or equal" - //!< between odd indexed elements. - kPCmpStrEqualEach = 0x02u << 2, //!< The arithmetic comparison is "equal". - kPCmpStrEqualOrdered = 0x03u << 2, //!< The arithmetic comparison is "equal". - - // Polarity: - kPCmpStrPosPolarity = 0x00u << 4, //!< IntRes2 = IntRes1. - kPCmpStrNegPolarity = 0x01u << 4, //!< IntRes2 = -1 XOR IntRes1. - kPCmpStrPosMasked = 0x02u << 4, //!< IntRes2 = IntRes1. - kPCmpStrNegMasked = 0x03u << 4, //!< IntRes2[i] = second[i] == invalid ? IntRes1[i] : ~IntRes1[i]. - - // Output selection (pcmpstri): - kPCmpStrOutputLSI = 0x00u << 6, //!< The index returned to ECX is of the least significant set bit in IntRes2. - kPCmpStrOutputMSI = 0x01u << 6, //!< The index returned to ECX is of the most significant set bit in IntRes2. - - // Output selection (pcmpstrm): - kPCmpStrBitMask = 0x00u << 6, //!< IntRes2 is returned as the mask to the least significant bits of XMM0. - kPCmpStrIndexMask = 0x01u << 6 //!< IntRes2 is expanded into a byte/word mask and placed in XMM0. - }; + // Polarity + // -------- - //! A predicate used by ROUND[PD|PS|SD|SS] instructions. - enum Round : uint32_t { - //! Round to nearest (even). - kRoundNearest = 0x00u, - //! Round to down toward -INF (floor), - kRoundDown = 0x01u, - //! Round to up toward +INF (ceil). - kRoundUp = 0x02u, - //! Round toward zero (truncate). - kRoundTrunc = 0x03u, - //! Round to the current rounding mode set (ignores other RC bits). - kRoundCurrent = 0x04u, - //! Avoids inexact exception, if set. - kRoundInexact = 0x08u - }; + kPosPolarity = 0x00u << 4, //!< IntRes2 = IntRes1. + kNegPolarity = 0x01u << 4, //!< IntRes2 = -1 XOR IntRes1. + kPosMasked = 0x02u << 4, //!< IntRes2 = IntRes1. + kNegMasked = 0x03u << 4, //!< IntRes2[i] = second[i] == invalid ? IntRes1[i] : ~IntRes1[i]. - //! A predicate used by VCMP[PD|PS|SD|SS] instructions. - //! - //! The first 8 values are compatible with `Cmp`. - enum VCmp : uint32_t { - kVCmpEQ_OQ = kCmpEQ, //!< Equal (Quiet , Ordered). - kVCmpLT_OS = kCmpLT, //!< Less (Signaling, Ordered). - kVCmpLE_OS = kCmpLE, //!< Less/Equal (Signaling, Ordered). - kVCmpUNORD_Q = kCmpUNORD, //!< Unordered (Quiet). - kVCmpNEQ_UQ = kCmpNEQ, //!< Not Equal (Quiet , Unordered). - kVCmpNLT_US = kCmpNLT, //!< Not Less (Signaling, Unordered). - kVCmpNLE_US = kCmpNLE, //!< Not Less/Equal (Signaling, Unordered). - kVCmpORD_Q = kCmpORD, //!< Ordered (Quiet). - kVCmpEQ_UQ = 0x08u, //!< Equal (Quiet , Unordered). - kVCmpNGE_US = 0x09u, //!< Not Greater/Equal (Signaling, Unordered). - kVCmpNGT_US = 0x0Au, //!< Not Greater (Signaling, Unordered). - kVCmpFALSE_OQ = 0x0Bu, //!< False (Quiet , Ordered). - kVCmpNEQ_OQ = 0x0Cu, //!< Not Equal (Quiet , Ordered). - kVCmpGE_OS = 0x0Du, //!< Greater/Equal (Signaling, Ordered). - kVCmpGT_OS = 0x0Eu, //!< Greater (Signaling, Ordered). - kVCmpTRUE_UQ = 0x0Fu, //!< True (Quiet , Unordered). - kVCmpEQ_OS = 0x10u, //!< Equal (Signaling, Ordered). - kVCmpLT_OQ = 0x11u, //!< Less (Quiet , Ordered). - kVCmpLE_OQ = 0x12u, //!< Less/Equal (Quiet , Ordered). - kVCmpUNORD_S = 0x13u, //!< Unordered (Signaling). - kVCmpNEQ_US = 0x14u, //!< Not Equal (Signaling, Unordered). - kVCmpNLT_UQ = 0x15u, //!< Not Less (Quiet , Unordered). - kVCmpNLE_UQ = 0x16u, //!< Not Less/Equal (Quiet , Unordered). - kVCmpORD_S = 0x17u, //!< Ordered (Signaling). - kVCmpEQ_US = 0x18u, //!< Equal (Signaling, Unordered). - kVCmpNGE_UQ = 0x19u, //!< Not Greater/Equal (Quiet , Unordered). - kVCmpNGT_UQ = 0x1Au, //!< Not Greater (Quiet , Unordered). - kVCmpFALSE_OS = 0x1Bu, //!< False (Signaling, Ordered). - kVCmpNEQ_OS = 0x1Cu, //!< Not Equal (Signaling, Ordered). - kVCmpGE_OQ = 0x1Du, //!< Greater/Equal (Quiet , Ordered). - kVCmpGT_OQ = 0x1Eu, //!< Greater (Quiet , Ordered). - kVCmpTRUE_US = 0x1Fu //!< True (Signaling, Unordered). - }; + // Output Selection (pcmpstri) + // --------------------------- - //! A predicate used by VFIXUPIMM[PD|PS|SD|SS] instructions (AVX-512). - enum VFixupImm : uint32_t { - kVFixupImmZEOnZero = 0x01u, - kVFixupImmIEOnZero = 0x02u, - kVFixupImmZEOnOne = 0x04u, - kVFixupImmIEOnOne = 0x08u, - kVFixupImmIEOnSNaN = 0x10u, - kVFixupImmIEOnNInf = 0x20u, - kVFixupImmIEOnNegative= 0x40u, - kVFixupImmIEOnPInf = 0x80u - }; + kOutputLSI = 0x00u << 6, //!< The index returned to ECX is of the least significant set bit in IntRes2. + kOutputMSI = 0x01u << 6, //!< The index returned to ECX is of the most significant set bit in IntRes2. - //! A predicate used by VFPCLASS[PD|PS|SD|SS] instructions (AVX-512). - //! - //! \note Values can be combined together to form the final 8-bit mask. - enum VFPClass : uint32_t { - kVFPClassQNaN = 0x01u, //!< Checks for QNaN. - kVFPClassPZero = 0x02u, //!< Checks for +0. - kVFPClassNZero = 0x04u, //!< Checks for -0. - kVFPClassPInf = 0x08u, //!< Checks for +Inf. - kVFPClassNInf = 0x10u, //!< Checks for -Inf. - kVFPClassDenormal = 0x20u, //!< Checks for denormal. - kVFPClassNegative = 0x40u, //!< Checks for negative finite value. - kVFPClassSNaN = 0x80u //!< Checks for SNaN. - }; + // Output Selection (pcmpstrm) + // --------------------------- - //! A predicate used by VGETMANT[PD|PS|SD|SS] instructions (AVX-512). - enum VGetMant : uint32_t { - kVGetMant1To2 = 0x00u, - kVGetMant1Div2To2 = 0x01u, - kVGetMant1Div2To1 = 0x02u, - kVGetMant3Div4To3Div2 = 0x03u, - kVGetMantNoSign = 0x04u, - kVGetMantQNaNIfSign = 0x08u - }; + kBitMask = 0x00u << 6, //!< IntRes2 is returned as the mask to the least significant bits of XMM0. + kIndexMask = 0x01u << 6 //!< IntRes2 is expanded into a byte/word mask and placed in XMM0. +}; +ASMJIT_DEFINE_ENUM_FLAGS(PCmpStrImm) - //! A predicate used by VPCMP[U][B|W|D|Q] instructions (AVX-512). - enum VPCmp : uint32_t { - kVPCmpEQ = 0x00u, //!< Equal. - kVPCmpLT = 0x01u, //!< Less. - kVPCmpLE = 0x02u, //!< Less/Equal. - kVPCmpFALSE = 0x03u, //!< False. - kVPCmpNE = 0x04u, //!< Not Equal. - kVPCmpGE = 0x05u, //!< Greater/Equal. - kVPCmpGT = 0x06u, //!< Greater. - kVPCmpTRUE = 0x07u //!< True. - }; +//! An immediate value that can be used with ROUND[PD|PS|SD|SS] instructions. +//! +//! \note `kSuppress` is a mask that can be used with any other value. +enum class RoundImm : uint8_t { + kNearest = 0x00u, //!< Round to nearest (even). + kDown = 0x01u, //!< Round to down toward -INF (floor), + kUp = 0x02u, //!< Round to up toward +INF (ceil). + kTrunc = 0x03u, //!< Round toward zero (truncate). + kCurrent = 0x04u, //!< Round to the current rounding mode set (ignores other RC bits). + kSuppress = 0x08u //!< Supress exceptions (avoids inexact exception, if set). +}; +ASMJIT_DEFINE_ENUM_FLAGS(RoundImm) - //! A predicate used by VPCOM[U][B|W|D|Q] instructions (XOP). - enum VPCom : uint32_t { - kVPComLT = 0x00u, //!< Less. - kVPComLE = 0x01u, //!< Less/Equal - kVPComGT = 0x02u, //!< Greater. - kVPComGE = 0x03u, //!< Greater/Equal. - kVPComEQ = 0x04u, //!< Equal. - kVPComNE = 0x05u, //!< Not Equal. - kVPComFALSE = 0x06u, //!< False. - kVPComTRUE = 0x07u //!< True. - }; +//! An immediate value that can be used with VCMP[PD|PS|SD|SS] instructions (AVX). +//! +//! The first 8 values are compatible with \ref CmpImm. +enum class VCmpImm : uint8_t { + kEQ_OQ = 0x00u, //!< Equal (Quiet , Ordered) , same as \ref CmpImm::kEQ. + kLT_OS = 0x01u, //!< Less (Signaling, Ordered) , same as \ref CmpImm::kLT. + kLE_OS = 0x02u, //!< Less/Equal (Signaling, Ordered) , same as \ref CmpImm::kLE. + kUNORD_Q = 0x03u, //!< Unordered (Quiet) , same as \ref CmpImm::kUNORD. + kNEQ_UQ = 0x04u, //!< Not Equal (Quiet , Unordered), same as \ref CmpImm::kNEQ. + kNLT_US = 0x05u, //!< Not Less (Signaling, Unordered), same as \ref CmpImm::kNLT. + kNLE_US = 0x06u, //!< Not Less/Equal (Signaling, Unordered), same as \ref CmpImm::kNLE. + kORD_Q = 0x07u, //!< Ordered (Quiet) , same as \ref CmpImm::kORD. + kEQ_UQ = 0x08u, //!< Equal (Quiet , Unordered). + kNGE_US = 0x09u, //!< Not Greater/Equal (Signaling, Unordered). + kNGT_US = 0x0Au, //!< Not Greater (Signaling, Unordered). + kFALSE_OQ = 0x0Bu, //!< False (Quiet , Ordered). + kNEQ_OQ = 0x0Cu, //!< Not Equal (Quiet , Ordered). + kGE_OS = 0x0Du, //!< Greater/Equal (Signaling, Ordered). + kGT_OS = 0x0Eu, //!< Greater (Signaling, Ordered). + kTRUE_UQ = 0x0Fu, //!< True (Quiet , Unordered). + kEQ_OS = 0x10u, //!< Equal (Signaling, Ordered). + kLT_OQ = 0x11u, //!< Less (Quiet , Ordered). + kLE_OQ = 0x12u, //!< Less/Equal (Quiet , Ordered). + kUNORD_S = 0x13u, //!< Unordered (Signaling). + kNEQ_US = 0x14u, //!< Not Equal (Signaling, Unordered). + kNLT_UQ = 0x15u, //!< Not Less (Quiet , Unordered). + kNLE_UQ = 0x16u, //!< Not Less/Equal (Quiet , Unordered). + kORD_S = 0x17u, //!< Ordered (Signaling). + kEQ_US = 0x18u, //!< Equal (Signaling, Unordered). + kNGE_UQ = 0x19u, //!< Not Greater/Equal (Quiet , Unordered). + kNGT_UQ = 0x1Au, //!< Not Greater (Quiet , Unordered). + kFALSE_OS = 0x1Bu, //!< False (Signaling, Ordered). + kNEQ_OS = 0x1Cu, //!< Not Equal (Signaling, Ordered). + kGE_OQ = 0x1Du, //!< Greater/Equal (Quiet , Ordered). + kGT_OQ = 0x1Eu, //!< Greater (Quiet , Ordered). + kTRUE_US = 0x1Fu //!< True (Signaling, Unordered). +}; - //! A predicate used by VRANGE[PD|PS|SD|SS] instructions (AVX-512). - enum VRange : uint32_t { - kVRangeSelectMin = 0x00u, //!< Select minimum value. - kVRangeSelectMax = 0x01u, //!< Select maximum value. - kVRangeSelectAbsMin = 0x02u, //!< Select minimum absolute value. - kVRangeSelectAbsMax = 0x03u, //!< Select maximum absolute value. - kVRangeSignSrc1 = 0x00u, //!< Select sign of SRC1. - kVRangeSignSrc2 = 0x04u, //!< Select sign of SRC2. - kVRangeSign0 = 0x08u, //!< Set sign to 0. - kVRangeSign1 = 0x0Cu //!< Set sign to 1. - }; +//! An immediate value that can be used with VFIXUPIMM[PD|PS|SD|SS] instructions (AVX-512). +//! +//! The final immediate is a combination of all possible control bits. +enum class VFixupImm : uint8_t { + kNone = 0x00u, + kZEOnZero = 0x01u, + kIEOnZero = 0x02u, + kZEOnOne = 0x04u, + kIEOnOne = 0x08u, + kIEOnSNaN = 0x10u, + kIEOnNInf = 0x20u, + kIEOnNegative = 0x40u, + kIEOnPInf = 0x80u +}; +ASMJIT_DEFINE_ENUM_FLAGS(VFixupImm) - //! A predicate used by VREDUCE[PD|PS|SD|SS] instructions (AVX-512). - enum VReduce : uint32_t { - kVReduceRoundCurrent = 0x00u, //!< Round to the current mode set. - kVReduceRoundEven = 0x04u, //!< Round to nearest even. - kVReduceRoundDown = 0x05u, //!< Round down. - kVReduceRoundUp = 0x06u, //!< Round up. - kVReduceRoundTrunc = 0x07u, //!< Truncate. - kVReduceSuppress = 0x08u //!< Suppress exceptions. - }; +//! An immediate value that can be used with VFPCLASS[PD|PS|SD|SS] instructions (AVX-512). +//! +//! The values can be combined together to form the final 8-bit mask. +enum class VFPClassImm : uint8_t { + kNone = 0x00u, + kQNaN = 0x01u, //!< Checks for QNaN. + kPZero = 0x02u, //!< Checks for +0. + kNZero = 0x04u, //!< Checks for -0. + kPInf = 0x08u, //!< Checks for +Inf. + kNInf = 0x10u, //!< Checks for -Inf. + kDenormal = 0x20u, //!< Checks for denormal. + kNegative = 0x40u, //!< Checks for negative finite value. + kSNaN = 0x80u //!< Checks for SNaN. +}; +ASMJIT_DEFINE_ENUM_FLAGS(VFPClassImm) + +//! An immediate value that can be used with VGETMANT[PD|PS|SD|SS] instructions (AVX-512). +//! +//! The value is a combination of a normalization interval and a sign control. +enum class VGetMantImm : uint8_t { + // Normalization Interval + // ---------------------- + + k1To2 = 0x00u, //!< Normalization interval is [1, 2) + k1Div2To2 = 0x01u, //!< Normalization interval is [0.5, 2) + k1Div2To1 = 0x02u, //!< Normalization interval is [0.5, 1) + k3Div4To3Div2 = 0x03u, //!< Normalization interval is [3/4, 3/2) + + // Sign Control + // ------------ + + kSrcSign = 0x00u, //!< Source sign. + kNoSign = 0x04u, //!< Zero sign + kQNaNIfSign = 0x08u //!< QNAN_Indefinite if sign(src) != 0, regardless of `kSignSrc` or `kNoSign`. +}; +ASMJIT_DEFINE_ENUM_FLAGS(VGetMantImm) + +//! A predicate used by VPCMP[U][B|W|D|Q] instructions (AVX-512). +enum class VPCmpImm : uint8_t { + kEQ = 0x00u, //!< Equal. + kLT = 0x01u, //!< Less. + kLE = 0x02u, //!< Less/Equal. + kFALSE = 0x03u, //!< False. + kNE = 0x04u, //!< Not Equal. + kGE = 0x05u, //!< Greater/Equal. + kGT = 0x06u, //!< Greater. + kTRUE = 0x07u //!< True. +}; + +//! A predicate used by VPCOM[U][B|W|D|Q] instructions (XOP). +enum class VPComImm : uint8_t { + kLT = 0x00u, //!< Less. + kLE = 0x01u, //!< Less/Equal + kGT = 0x02u, //!< Greater. + kGE = 0x03u, //!< Greater/Equal. + kEQ = 0x04u, //!< Equal. + kNE = 0x05u, //!< Not Equal. + kFALSE = 0x06u, //!< False. + kTRUE = 0x07u //!< True. +}; - //! Pack a shuffle constant to be used by SSE/AVX/AVX-512 instructions (2 values). - //! - //! \param a Position of the first component [0, 1]. - //! \param b Position of the second component [0, 1]. - //! - //! Shuffle constants can be used to encode an immediate for these instructions: - //! - `shufpd|vshufpd` - static constexpr uint32_t shuf(uint32_t a, uint32_t b) noexcept { - return (a << 1) | b; - } - - //! Pack a shuffle constant to be used by SSE/AVX/AVX-512 instructions (4 values). - //! - //! \param a Position of the first component [0, 3]. - //! \param b Position of the second component [0, 3]. - //! \param c Position of the third component [0, 3]. - //! \param d Position of the fourth component [0, 3]. - //! - //! Shuffle constants can be used to encode an immediate for these instructions: - //! - `pshufw` - //! - `pshuflw|vpshuflw` - //! - `pshufhw|vpshufhw` - //! - `pshufd|vpshufd` - //! - `shufps|vshufps` - static constexpr uint32_t shuf(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { - return (a << 6) | (b << 4) | (c << 2) | d; - } +//! A predicate used by VRANGE[PD|PS|SD|SS] instructions (AVX-512). +enum class VRangeImm : uint8_t { + // Selector + // -------- + + kSelectMin = 0x00u, //!< Select minimum value. + kSelectMax = 0x01u, //!< Select maximum value. + kSelectAbsMin = 0x02u, //!< Select minimum absolute value. + kSelectAbsMax = 0x03u, //!< Select maximum absolute value. + + // Sign + // ---- + + kSignSrc1 = 0x00u, //!< Select sign of SRC1. + kSignSrc2 = 0x04u, //!< Select sign of SRC2. + kSign0 = 0x08u, //!< Set sign to 0. + kSign1 = 0x0Cu //!< Set sign to 1. +}; +ASMJIT_DEFINE_ENUM_FLAGS(VRangeImm) + +//! A predicate used by VREDUCE[PD|PS|SD|SS] instructions (AVX-512). +enum class VReduceImm : uint8_t { + kRoundEven = 0x00u, //!< Round to nearest even. + kRoundDown = 0x01u, //!< Round down. + kRoundUp = 0x02u, //!< Round up. + kRoundTrunc = 0x03u, //!< Truncate. + kRoundCurrent = 0x04u, //!< Round to the current mode set. + kSuppress = 0x08u, //!< Suppress exceptions. + kFixedImmMask = 0xF0u //!< Fixed length value mask. +}; +ASMJIT_DEFINE_ENUM_FLAGS(VReduceImm) + +//! Creates a \ref VReduceImm from a combination of `flags` and `fixedPointLength`. +static inline constexpr VReduceImm vReduceImm(VReduceImm flags, uint32_t fixedPointLength) noexcept { + return flags | VReduceImm(fixedPointLength << 4); } -// ============================================================================ -// [asmjit::x86::TLog] -// ============================================================================ - -//! Bitwise ternary logic between 3 operands introduced by AVX-512. -namespace TLog { - //! A predicate that can be used to create a common predicate for VPTERNLOG[D|Q]. - //! - //! There are 3 inputs to the instruction (\ref kA, \ref kB, \ref kC), and - //! ternary logic can define any combination that would be performed on these - //! 3 inputs to get the desired output - any combination of AND, OR, XOR, NOT. - enum Operator : uint32_t { - //! 0 value. - k0 = 0x00u, - //! 1 value. - k1 = 0xFFu, - //! A value. - kA = 0xF0u, - //! B value. - kB = 0xCCu, - //! C value. - kC = 0xAAu, - - //! `!A` expression. - kNotA = kA ^ k1, - //! `!B` expression. - kNotB = kB ^ k1, - //! `!C` expression. - kNotC = kC ^ k1, - - //! `A & B` expression. - kAB = kA & kB, - //! `A & C` expression. - kAC = kA & kC, - //! `B & C` expression. - kBC = kB & kC, - //! `!(A & B)` expression. - kNotAB = kAB ^ k1, - //! `!(A & C)` expression. - kNotAC = kAC ^ k1, - //! `!(B & C)` expression. - kNotBC = kBC ^ k1, - - //! `A & B & C` expression. - kABC = kAB & kC, - //! `!(A & B & C)` expression. - kNotABC = kABC ^ k1 - }; +//! A predicate that can be used as an immediate value with VPTERNLOG[D|Q] instruction. +//! +//! There are 3 inputs to the instruction (\ref kA, \ref kB, \ref kC). Ternary logic can define any combination +//! that would be performed on these 3 inputs to get the desired output - any combination of AND, OR, XOR, NOT +//! is possible. +//! +//! \sa \ref tLogFromBits and \ref fLogIfElse +enum class TLogImm : uint8_t { + k0 = 0x00u, //!< 0 value. + k1 = 0xFFu, //!< 1 value. + kA = 0xF0u, //!< A value. + kB = 0xCCu, //!< B value. + kC = 0xAAu, //!< C value. + + kNotA = kA ^ k1, //!< `!A` expression. + kNotB = kB ^ k1, //!< `!B` expression. + kNotC = kC ^ k1, //!< `!C` expression. + + kAB = kA & kB, //!< `A & B` expression. + kAC = kA & kC, //!< `A & C` expression. + kBC = kB & kC, //!< `B & C` expression. + kNotAB = kAB ^ k1, //!< `!(A & B)` expression. + kNotAC = kAC ^ k1, //!< `!(A & C)` expression. + kNotBC = kBC ^ k1, //!< `!(B & C)` expression. + + kABC = kAB & kC, //!< `A & B & C` expression. + kNotABC = kABC ^ k1 //!< `!(A & B & C)` expression. +}; +ASMJIT_DEFINE_ENUM_FLAGS(TLogImm) + +//! Creates an immediate that can be used by VPTERNLOG[D|Q] instructions. +static inline constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t b010, uint8_t b011, uint8_t b100, uint8_t b101, uint8_t b110, uint8_t b111) noexcept { + return TLogImm(uint8_t(b000 << 0) | + uint8_t(b001 << 1) | + uint8_t(b010 << 2) | + uint8_t(b011 << 3) | + uint8_t(b100 << 4) | + uint8_t(b101 << 5) | + uint8_t(b110 << 6) | + uint8_t(b111 << 7)); +} + +//! Creates an if/else logic that can be used by VPTERNLOG[D|Q] instructions. +static inline constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm b) noexcept { return (condition & a) | (~condition & b); } - //! Creates an immediate that can be used by VPTERNLOG[D|Q] instructions. - static constexpr uint32_t make(uint32_t b000, uint32_t b001, uint32_t b010, uint32_t b011, uint32_t b100, uint32_t b101, uint32_t b110, uint32_t b111) noexcept { - return (b000 << 0) | (b001 << 1) | (b010 << 2) | (b011 << 3) | (b100 << 4) | (b101 << 5) | (b110 << 6) | (b111 << 7); - } - - //! Creates an immediate that can be used by VPTERNLOG[D|Q] instructions. - static constexpr uint32_t value(uint32_t x) noexcept { return x & 0xFF; } - //! Negate an immediate that can be used by VPTERNLOG[D|Q] instructions. - static constexpr uint32_t negate(uint32_t x) noexcept { return x ^ 0xFF; } - //! Creates an if/else logic that can be used by VPTERNLOG[D|Q] instructions. - static constexpr uint32_t ifElse(uint32_t condition, uint32_t a, uint32_t b) noexcept { return (condition & a) | (negate(condition) & b); } +//! Creates a shuffle immediate value that be used with SSE/AVX/AVX-512 instructions to shuffle 2 elements in a vector. +//! +//! \param a Position of the first component [0, 1]. +//! \param b Position of the second component [0, 1]. +//! +//! Shuffle constants can be used to encode an immediate for these instructions: +//! - `shufpd|vshufpd` +static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept { + return (a << 1) | b; +} + +//! Creates a shuffle immediate value that be used with SSE/AVX/AVX-512 instructions to shuffle 4 elements in a vector. +//! +//! \param a Position of the first component [0, 3]. +//! \param b Position of the second component [0, 3]. +//! \param c Position of the third component [0, 3]. +//! \param d Position of the fourth component [0, 3]. +//! +//! Shuffle constants can be used to encode an immediate for these instructions: +//! - `pshufw` +//! - `pshuflw|vpshuflw` +//! - `pshufhw|vpshufhw` +//! - `pshufd|vpshufd` +//! - `shufps|vshufps` +static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept { + return (a << 6) | (b << 4) | (c << 2) | d; } //! \} diff --git a/src/asmjit/x86/x86instapi.cpp b/src/asmjit/x86/x86instapi.cpp index 664cfae..3580fe6 100644 --- a/src/asmjit/x86/x86instapi.cpp +++ b/src/asmjit/x86/x86instapi.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib // ---------------------------------------------------------------------------- // IMPORTANT: AsmJit now uses an external instruction database to populate @@ -45,7 +27,6 @@ #include "../core/cpuinfo.h" #include "../core/misc_p.h" #include "../core/support.h" -#include "../x86/x86features.h" #include "../x86/x86instapi_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86opcode_p.h" @@ -53,12 +34,11 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::InstInternal - Text] -// ============================================================================ +// x86::InstInternal - Text +// ======================== #ifndef ASMJIT_NO_TEXT -Error InstInternal::instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept { +Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept { DebugUtils::unused(arch); if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId))) @@ -68,7 +48,7 @@ Error InstInternal::instIdToString(uint32_t arch, uint32_t instId, String& outpu return output.append(InstDB::_nameData + info._nameDataIndex); } -uint32_t InstInternal::stringToInstId(uint32_t arch, const char* s, size_t len) noexcept { +InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept { DebugUtils::unused(arch); if (ASMJIT_UNLIKELY(!s)) @@ -107,109 +87,113 @@ uint32_t InstInternal::stringToInstId(uint32_t arch, const char* s, size_t len) if (result > 0) continue; - return uint32_t((size_t)(cur - table)); + return InstId((size_t)(cur - table)); } return Inst::kIdNone; } #endif // !ASMJIT_NO_TEXT -// ============================================================================ -// [asmjit::x86::InstInternal - Validate] -// ============================================================================ +// x86::InstInternal - Validate +// ============================ #ifndef ASMJIT_NO_VALIDATION struct X86ValidationData { - //! Allowed registers by reg-type (x86::Reg::kType...). - uint32_t allowedRegMask[Reg::kTypeMax + 1]; + //! Allowed registers by \ref RegType. + RegMask allowedRegMask[uint32_t(RegType::kMaxValue) + 1]; uint32_t allowedMemBaseRegs; uint32_t allowedMemIndexRegs; }; #define VALUE(x) \ - (x == Reg::kTypeGpbLo) ? InstDB::kOpGpbLo : \ - (x == Reg::kTypeGpbHi) ? InstDB::kOpGpbHi : \ - (x == Reg::kTypeGpw ) ? InstDB::kOpGpw : \ - (x == Reg::kTypeGpd ) ? InstDB::kOpGpd : \ - (x == Reg::kTypeGpq ) ? InstDB::kOpGpq : \ - (x == Reg::kTypeXmm ) ? InstDB::kOpXmm : \ - (x == Reg::kTypeYmm ) ? InstDB::kOpYmm : \ - (x == Reg::kTypeZmm ) ? InstDB::kOpZmm : \ - (x == Reg::kTypeMm ) ? InstDB::kOpMm : \ - (x == Reg::kTypeKReg ) ? InstDB::kOpKReg : \ - (x == Reg::kTypeSReg ) ? InstDB::kOpSReg : \ - (x == Reg::kTypeCReg ) ? InstDB::kOpCReg : \ - (x == Reg::kTypeDReg ) ? InstDB::kOpDReg : \ - (x == Reg::kTypeSt ) ? InstDB::kOpSt : \ - (x == Reg::kTypeBnd ) ? InstDB::kOpBnd : \ - (x == Reg::kTypeTmm ) ? InstDB::kOpTmm : \ - (x == Reg::kTypeRip ) ? InstDB::kOpNone : InstDB::kOpNone -static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP_TABLE_32(VALUE, 0) }; + (x == uint32_t(RegType::kX86_GpbLo)) ? InstDB::OpFlags::kRegGpbLo : \ + (x == uint32_t(RegType::kX86_GpbHi)) ? InstDB::OpFlags::kRegGpbHi : \ + (x == uint32_t(RegType::kX86_Gpw )) ? InstDB::OpFlags::kRegGpw : \ + (x == uint32_t(RegType::kX86_Gpd )) ? InstDB::OpFlags::kRegGpd : \ + (x == uint32_t(RegType::kX86_Gpq )) ? InstDB::OpFlags::kRegGpq : \ + (x == uint32_t(RegType::kX86_Xmm )) ? InstDB::OpFlags::kRegXmm : \ + (x == uint32_t(RegType::kX86_Ymm )) ? InstDB::OpFlags::kRegYmm : \ + (x == uint32_t(RegType::kX86_Zmm )) ? InstDB::OpFlags::kRegZmm : \ + (x == uint32_t(RegType::kX86_Mm )) ? InstDB::OpFlags::kRegMm : \ + (x == uint32_t(RegType::kX86_KReg )) ? InstDB::OpFlags::kRegKReg : \ + (x == uint32_t(RegType::kX86_SReg )) ? InstDB::OpFlags::kRegSReg : \ + (x == uint32_t(RegType::kX86_CReg )) ? InstDB::OpFlags::kRegCReg : \ + (x == uint32_t(RegType::kX86_DReg )) ? InstDB::OpFlags::kRegDReg : \ + (x == uint32_t(RegType::kX86_St )) ? InstDB::OpFlags::kRegSt : \ + (x == uint32_t(RegType::kX86_Bnd )) ? InstDB::OpFlags::kRegBnd : \ + (x == uint32_t(RegType::kX86_Tmm )) ? InstDB::OpFlags::kRegTmm : \ + (x == uint32_t(RegType::kX86_Rip )) ? InstDB::OpFlags::kNone : InstDB::OpFlags::kNone +static const InstDB::OpFlags _x86OpFlagFromRegType[uint32_t(RegType::kMaxValue) + 1] = { ASMJIT_LOOKUP_TABLE_32(VALUE, 0) }; #undef VALUE #define REG_MASK_FROM_REG_TYPE_X86(x) \ - (x == Reg::kTypeGpbLo) ? 0x0000000Fu : \ - (x == Reg::kTypeGpbHi) ? 0x0000000Fu : \ - (x == Reg::kTypeGpw ) ? 0x000000FFu : \ - (x == Reg::kTypeGpd ) ? 0x000000FFu : \ - (x == Reg::kTypeGpq ) ? 0x000000FFu : \ - (x == Reg::kTypeXmm ) ? 0x000000FFu : \ - (x == Reg::kTypeYmm ) ? 0x000000FFu : \ - (x == Reg::kTypeZmm ) ? 0x000000FFu : \ - (x == Reg::kTypeMm ) ? 0x000000FFu : \ - (x == Reg::kTypeKReg ) ? 0x000000FFu : \ - (x == Reg::kTypeSReg ) ? 0x0000007Eu : \ - (x == Reg::kTypeCReg ) ? 0x0000FFFFu : \ - (x == Reg::kTypeDReg ) ? 0x000000FFu : \ - (x == Reg::kTypeSt ) ? 0x000000FFu : \ - (x == Reg::kTypeBnd ) ? 0x0000000Fu : \ - (x == Reg::kTypeTmm ) ? 0x000000FFu : \ - (x == Reg::kTypeRip ) ? 0x00000001u : 0u + (x == uint32_t(RegType::kX86_GpbLo)) ? 0x0000000Fu : \ + (x == uint32_t(RegType::kX86_GpbHi)) ? 0x0000000Fu : \ + (x == uint32_t(RegType::kX86_Gpw )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Gpd )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Gpq )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Xmm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Ymm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Zmm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Mm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_KReg )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_SReg )) ? 0x0000007Eu : \ + (x == uint32_t(RegType::kX86_CReg )) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_DReg )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_St )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Bnd )) ? 0x0000000Fu : \ + (x == uint32_t(RegType::kX86_Tmm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Rip )) ? 0x00000001u : 0u #define REG_MASK_FROM_REG_TYPE_X64(x) \ - (x == Reg::kTypeGpbLo) ? 0x0000FFFFu : \ - (x == Reg::kTypeGpbHi) ? 0x0000000Fu : \ - (x == Reg::kTypeGpw ) ? 0x0000FFFFu : \ - (x == Reg::kTypeGpd ) ? 0x0000FFFFu : \ - (x == Reg::kTypeGpq ) ? 0x0000FFFFu : \ - (x == Reg::kTypeXmm ) ? 0xFFFFFFFFu : \ - (x == Reg::kTypeYmm ) ? 0xFFFFFFFFu : \ - (x == Reg::kTypeZmm ) ? 0xFFFFFFFFu : \ - (x == Reg::kTypeMm ) ? 0x000000FFu : \ - (x == Reg::kTypeKReg ) ? 0x000000FFu : \ - (x == Reg::kTypeSReg ) ? 0x0000007Eu : \ - (x == Reg::kTypeCReg ) ? 0x0000FFFFu : \ - (x == Reg::kTypeDReg ) ? 0x0000FFFFu : \ - (x == Reg::kTypeSt ) ? 0x000000FFu : \ - (x == Reg::kTypeBnd ) ? 0x0000000Fu : \ - (x == Reg::kTypeTmm ) ? 0x000000FFu : \ - (x == Reg::kTypeRip ) ? 0x00000001u : 0u + (x == uint32_t(RegType::kX86_GpbLo)) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_GpbHi)) ? 0x0000000Fu : \ + (x == uint32_t(RegType::kX86_Gpw )) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_Gpd )) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_Gpq )) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_Xmm )) ? 0xFFFFFFFFu : \ + (x == uint32_t(RegType::kX86_Ymm )) ? 0xFFFFFFFFu : \ + (x == uint32_t(RegType::kX86_Zmm )) ? 0xFFFFFFFFu : \ + (x == uint32_t(RegType::kX86_Mm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_KReg )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_SReg )) ? 0x0000007Eu : \ + (x == uint32_t(RegType::kX86_CReg )) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_DReg )) ? 0x0000FFFFu : \ + (x == uint32_t(RegType::kX86_St )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Bnd )) ? 0x0000000Fu : \ + (x == uint32_t(RegType::kX86_Tmm )) ? 0x000000FFu : \ + (x == uint32_t(RegType::kX86_Rip )) ? 0x00000001u : 0u + +#define B(RegType) (uint32_t(1) << uint32_t(RegType)) static const X86ValidationData _x86ValidationData = { { ASMJIT_LOOKUP_TABLE_32(REG_MASK_FROM_REG_TYPE_X86, 0) }, - (1u << Reg::kTypeGpw) | (1u << Reg::kTypeGpd) | (1u << Reg::kTypeRip) | (1u << Label::kLabelTag), - (1u << Reg::kTypeGpw) | (1u << Reg::kTypeGpd) | (1u << Reg::kTypeXmm) | (1u << Reg::kTypeYmm) | (1u << Reg::kTypeZmm) + B(RegType::kX86_Gpw) | B(RegType::kX86_Gpd) | B(RegType::kX86_Rip) | B(RegType::kLabelTag), + B(RegType::kX86_Gpw) | B(RegType::kX86_Gpd) | B(RegType::kX86_Xmm) | B(RegType::kX86_Ymm) | B(RegType::kX86_Zmm) }; static const X86ValidationData _x64ValidationData = { { ASMJIT_LOOKUP_TABLE_32(REG_MASK_FROM_REG_TYPE_X64, 0) }, - (1u << Reg::kTypeGpd) | (1u << Reg::kTypeGpq) | (1u << Reg::kTypeRip) | (1u << Label::kLabelTag), - (1u << Reg::kTypeGpd) | (1u << Reg::kTypeGpq) | (1u << Reg::kTypeXmm) | (1u << Reg::kTypeYmm) | (1u << Reg::kTypeZmm) + B(RegType::kX86_Gpd) | B(RegType::kX86_Gpq) | B(RegType::kX86_Rip) | B(RegType::kLabelTag), + B(RegType::kX86_Gpd) | B(RegType::kX86_Gpq) | B(RegType::kX86_Xmm) | B(RegType::kX86_Ymm) | B(RegType::kX86_Zmm) }; +#undef B + #undef REG_MASK_FROM_REG_TYPE_X64 #undef REG_MASK_FROM_REG_TYPE_X86 -static ASMJIT_INLINE bool x86IsZmmOrM512(const Operand_& op) noexcept { +static ASMJIT_FORCE_INLINE bool x86IsZmmOrM512(const Operand_& op) noexcept { return Reg::isZmm(op) || (op.isMem() && op.size() == 64); } -static ASMJIT_INLINE bool x86CheckOSig(const InstDB::OpSignature& op, const InstDB::OpSignature& ref, bool& immOutOfRange) noexcept { +static ASMJIT_FORCE_INLINE bool x86CheckOSig(const InstDB::OpSignature& op, const InstDB::OpSignature& ref, bool& immOutOfRange) noexcept { // Fail if operand types are incompatible. - uint32_t opFlags = op.opFlags; - if ((opFlags & ref.opFlags) == 0) { + InstDB::OpFlags commonFlags = op.flags() & ref.flags(); + + if (!Support::test(commonFlags, InstDB::OpFlags::kOpMask)) { // Mark temporarily `immOutOfRange` so we can return a more descriptive error later. - if ((opFlags & InstDB::kOpAllImm) && (ref.opFlags & InstDB::kOpAllImm)) { + if (op.hasImm() && ref.hasImm()) { immOutOfRange = true; return true; } @@ -217,43 +201,37 @@ static ASMJIT_INLINE bool x86CheckOSig(const InstDB::OpSignature& op, const Inst return false; } - // Fail if memory specific flags and sizes do not match the signature. - uint32_t opMemFlags = op.memFlags; - if (opMemFlags != 0) { - uint32_t refMemFlags = ref.memFlags; - if ((refMemFlags & opMemFlags) == 0) - return false; - - if ((refMemFlags & InstDB::kMemOpBaseOnly) && !(opMemFlags & InstDB::kMemOpBaseOnly)) + // Fail if some memory specific flags do not match. + if (Support::test(commonFlags, InstDB::OpFlags::kMemMask)) { + if (ref.hasFlag(InstDB::OpFlags::kFlagMemBase) && !op.hasFlag(InstDB::OpFlags::kFlagMemBase)) return false; } - // Specific register index. - if (opFlags & InstDB::kOpAllRegs) { - uint32_t refRegMask = ref.regMask; - if (refRegMask && !(op.regMask & refRegMask)) + // Fail if register indexes do not match. + if (Support::test(commonFlags, InstDB::OpFlags::kRegMask)) { + if (ref.regMask() && !Support::test(op.regMask(), ref.regMask())) return false; } return true; } -ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags) noexcept { +ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { // Only called when `arch` matches X86 family. ASMJIT_ASSERT(Environment::isFamilyX86(arch)); const X86ValidationData* vd; - if (arch == Environment::kArchX86) + if (arch == Arch::kX86) vd = &_x86ValidationData; else vd = &_x64ValidationData; uint32_t i; - uint32_t mode = InstDB::modeFromArch(arch); + InstDB::Mode mode = InstDB::modeFromArch(arch); // Get the instruction data. - uint32_t instId = inst.id(); - uint32_t options = inst.options(); + InstId instId = inst.id(); + InstOptions options = inst.options(); if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId))) return DebugUtils::errored(kErrorInvalidInstruction); @@ -261,89 +239,87 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in const InstDB::InstInfo& instInfo = InstDB::infoById(instId); const InstDB::CommonInfo& commonInfo = instInfo.commonInfo(); - uint32_t iFlags = instInfo.flags(); + InstDB::InstFlags iFlags = instInfo.flags(); + + constexpr InstOptions kRepAny = InstOptions::kX86_Rep | InstOptions::kX86_Repne; + constexpr InstOptions kXAcqXRel = InstOptions::kX86_XAcquire | InstOptions::kX86_XRelease; + constexpr InstOptions kAvx512Options = InstOptions::kX86_ZMask | InstOptions::kX86_ER | InstOptions::kX86_SAE; - // -------------------------------------------------------------------------- - // [Validate LOCK|XACQUIRE|XRELEASE] - // -------------------------------------------------------------------------- + // Validate LOCK|XACQUIRE|XRELEASE Prefixes + // ---------------------------------------- - const uint32_t kLockXAcqRel = Inst::kOptionXAcquire | Inst::kOptionXRelease; - if (options & (Inst::kOptionLock | kLockXAcqRel)) { - if (options & Inst::kOptionLock) { - if (ASMJIT_UNLIKELY(!(iFlags & InstDB::kFlagLock) && !(options & kLockXAcqRel))) + if (Support::test(options, InstOptions::kX86_Lock | kXAcqXRel)) { + if (Support::test(options, InstOptions::kX86_Lock)) { + if (ASMJIT_UNLIKELY(!Support::test(iFlags, InstDB::InstFlags::kLock) && !Support::test(options, kXAcqXRel))) return DebugUtils::errored(kErrorInvalidLockPrefix); if (ASMJIT_UNLIKELY(opCount < 1 || !operands[0].isMem())) return DebugUtils::errored(kErrorInvalidLockPrefix); } - if (options & kLockXAcqRel) { - if (ASMJIT_UNLIKELY(!(options & Inst::kOptionLock) || (options & kLockXAcqRel) == kLockXAcqRel)) + if (Support::test(options, kXAcqXRel)) { + if (ASMJIT_UNLIKELY(!Support::test(options, InstOptions::kX86_Lock) || (options & kXAcqXRel) == kXAcqXRel)) return DebugUtils::errored(kErrorInvalidPrefixCombination); - if (ASMJIT_UNLIKELY((options & Inst::kOptionXAcquire) && !(iFlags & InstDB::kFlagXAcquire))) + if (ASMJIT_UNLIKELY(Support::test(options, InstOptions::kX86_XAcquire) && !Support::test(iFlags, InstDB::InstFlags::kXAcquire))) return DebugUtils::errored(kErrorInvalidXAcquirePrefix); - if (ASMJIT_UNLIKELY((options & Inst::kOptionXRelease) && !(iFlags & InstDB::kFlagXRelease))) + if (ASMJIT_UNLIKELY(Support::test(options, InstOptions::kX86_XRelease) && !Support::test(iFlags, InstDB::InstFlags::kXRelease))) return DebugUtils::errored(kErrorInvalidXReleasePrefix); } } - // Validate REP and REPNE prefixes. - const uint32_t kRepAny = Inst::kOptionRep | Inst::kOptionRepne; - if (options & kRepAny) { + // Validate REP and REPNE Prefixes + // ------------------------------- + + if (Support::test(options, kRepAny)) { if (ASMJIT_UNLIKELY((options & kRepAny) == kRepAny)) return DebugUtils::errored(kErrorInvalidPrefixCombination); - if (ASMJIT_UNLIKELY(!(iFlags & InstDB::kFlagRep))) + if (ASMJIT_UNLIKELY(!Support::test(iFlags, InstDB::InstFlags::kRep))) return DebugUtils::errored(kErrorInvalidRepPrefix); } - // -------------------------------------------------------------------------- - // [Translate Each Operand to the Corresponding OpSignature] - // -------------------------------------------------------------------------- + // Translate Each Operand to the Corresponding OpSignature + // ------------------------------------------------------- InstDB::OpSignature oSigTranslated[Globals::kMaxOpCount]; - uint32_t combinedOpFlags = 0; + InstDB::OpFlags combinedOpFlags = InstDB::OpFlags::kNone; uint32_t combinedRegMask = 0; const Mem* memOp = nullptr; for (i = 0; i < opCount; i++) { const Operand_& op = operands[i]; - if (op.opType() == Operand::kOpNone) + if (op.opType() == OperandType::kNone) break; - uint32_t opFlags = 0; - uint32_t memFlags = 0; - uint32_t regMask = 0; + InstDB::OpFlags opFlags = InstDB::OpFlags::kNone; + RegMask regMask = 0; switch (op.opType()) { - case Operand::kOpReg: { - uint32_t regType = op.as<BaseReg>().type(); - if (ASMJIT_UNLIKELY(regType >= Reg::kTypeCount)) - return DebugUtils::errored(kErrorInvalidRegType); + case OperandType::kReg: { + RegType regType = op.as<BaseReg>().type(); + opFlags = _x86OpFlagFromRegType[size_t(regType)]; - opFlags = _x86OpFlagFromRegType[regType]; - if (ASMJIT_UNLIKELY(opFlags == 0)) + if (ASMJIT_UNLIKELY(opFlags == InstDB::OpFlags::kNone)) return DebugUtils::errored(kErrorInvalidRegType); - // If `regId` is equal or greater than Operand::kVirtIdMin it means - // that the register is virtual and its index will be assigned later - // by the register allocator. We must pass unless asked to disallow - // virtual registers. + // If `regId` is equal or greater than Operand::kVirtIdMin it means that the register is virtual and its + // index will be assigned later by the register allocator. We must pass unless asked to disallow virtual + // registers. uint32_t regId = op.id(); if (regId < Operand::kVirtIdMin) { if (ASMJIT_UNLIKELY(regId >= 32)) return DebugUtils::errored(kErrorInvalidPhysId); - if (ASMJIT_UNLIKELY(Support::bitTest(vd->allowedRegMask[regType], regId) == 0)) + if (ASMJIT_UNLIKELY(Support::bitTest(vd->allowedRegMask[size_t(regType)], regId) == 0)) return DebugUtils::errored(kErrorInvalidPhysId); regMask = Support::bitMask(regId); combinedRegMask |= regMask; } else { - if (!(validationFlags & InstAPI::kValidationFlagVirtRegs)) + if (uint32_t(validationFlags & ValidationFlags::kEnableVirtRegs) == 0) return DebugUtils::errored(kErrorIllegalVirtReg); regMask = 0xFFFFFFFFu; } @@ -351,13 +327,13 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in } // TODO: Validate base and index and combine these with `combinedRegMask`. - case Operand::kOpMem: { + case OperandType::kMem: { const Mem& m = op.as<Mem>(); memOp = &m; uint32_t memSize = m.size(); - uint32_t baseType = m.baseType(); - uint32_t indexType = m.indexType(); + RegType baseType = m.baseType(); + RegType indexType = m.indexType(); if (m.segmentId() > 6) return DebugUtils::errored(kErrorInvalidSegment); @@ -374,28 +350,28 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in } else { // If there is no size we implicitly calculate it so we can validate N in {1toN} properly. - memSize = commonInfo.hasAvx512B32() ? 4 : 8; + memSize = commonInfo.hasAvx512B64() ? 8 : + commonInfo.hasAvx512B32() ? 4 : 2; } - memSize <<= m.getBroadcast(); + memSize <<= uint32_t(m.getBroadcast()); } - if (baseType != 0 && baseType > Label::kLabelTag) { + if (baseType != RegType::kNone && baseType > RegType::kLabelTag) { uint32_t baseId = m.baseId(); if (m.isRegHome()) { - // Home address of a virtual register. In such case we don't want to - // validate the type of the base register as it will always be patched - // to ESP|RSP. + // Home address of a virtual register. In such case we don't want to validate the type of the + // base register as it will always be patched to ESP|RSP. } else { - if (ASMJIT_UNLIKELY((vd->allowedMemBaseRegs & (1u << baseType)) == 0)) + if (ASMJIT_UNLIKELY(!Support::bitTest(vd->allowedMemBaseRegs, baseType))) return DebugUtils::errored(kErrorInvalidAddress); } - // Create information that will be validated only if this is an implicit - // memory operand. Basically only usable for string instructions and other - // instructions where memory operand is implicit and has 'seg:[reg]' form. + // Create information that will be validated only if this is an implicit memory operand. Basically + // only usable for string instructions and other instructions where memory operand is implicit and + // has 'seg:[reg]' form. if (baseId < Operand::kVirtIdMin) { if (ASMJIT_UNLIKELY(baseId >= 32)) return DebugUtils::errored(kErrorInvalidPhysId); @@ -405,71 +381,66 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in combinedRegMask |= regMask; } else { - // Virtual base id - fill the whole mask for implicit mem validation. - // The register is not assigned yet, so we cannot predict the phys id. - if (!(validationFlags & InstAPI::kValidationFlagVirtRegs)) + // Virtual base id - fill the whole mask for implicit mem validation. The register is not assigned + // yet, so we cannot predict the phys id. + if (uint32_t(validationFlags & ValidationFlags::kEnableVirtRegs) == 0) return DebugUtils::errored(kErrorIllegalVirtReg); regMask = 0xFFFFFFFFu; } - if (!indexType && !m.offsetLo32()) - memFlags |= InstDB::kMemOpBaseOnly; + if (indexType == RegType::kNone && !m.offsetLo32()) + opFlags |= InstDB::OpFlags::kFlagMemBase; } - else if (baseType == Label::kLabelTag) { + else if (baseType == RegType::kLabelTag) { // [Label] - there is no need to validate the base as it's label. } else { // Base is a 64-bit address. int64_t offset = m.offset(); if (!Support::isInt32(offset)) { - if (mode == InstDB::kModeX86) { + if (mode == InstDB::Mode::kX86) { // 32-bit mode: Make sure that the address is either `int32_t` or `uint32_t`. if (!Support::isUInt32(offset)) return DebugUtils::errored(kErrorInvalidAddress64Bit); } else { - // 64-bit mode: Zero extension is allowed if the address has 32-bit index - // register or the address has no index register (it's still encodable). - if (indexType) { + // 64-bit mode: Zero extension is allowed if the address has 32-bit index register or the address + // has no index register (it's still encodable). + if (indexType != RegType::kNone) { if (!Support::isUInt32(offset)) return DebugUtils::errored(kErrorInvalidAddress64Bit); - if (indexType != Reg::kTypeGpd) + if (indexType != RegType::kX86_Gpd) return DebugUtils::errored(kErrorInvalidAddress64BitZeroExtension); } else { - // We don't validate absolute 64-bit addresses without an index register - // as this also depends on the target's base address. We don't have the - // information to do it at this moment. + // We don't validate absolute 64-bit addresses without an index register as this also depends + // on the target's base address. We don't have the information to do it at this moment. } } } } - if (indexType) { - if (ASMJIT_UNLIKELY((vd->allowedMemIndexRegs & (1u << indexType)) == 0)) + if (indexType != RegType::kNone) { + if (ASMJIT_UNLIKELY(!Support::bitTest(vd->allowedMemIndexRegs, indexType))) return DebugUtils::errored(kErrorInvalidAddress); - if (indexType == Reg::kTypeXmm) { - opFlags |= InstDB::kOpVm; - memFlags |= InstDB::kMemOpVm32x | InstDB::kMemOpVm64x; + if (indexType == RegType::kX86_Xmm) { + opFlags |= InstDB::OpFlags::kVm32x | InstDB::OpFlags::kVm64x; } - else if (indexType == Reg::kTypeYmm) { - opFlags |= InstDB::kOpVm; - memFlags |= InstDB::kMemOpVm32y | InstDB::kMemOpVm64y; + else if (indexType == RegType::kX86_Ymm) { + opFlags |= InstDB::OpFlags::kVm32y | InstDB::OpFlags::kVm64y; } - else if (indexType == Reg::kTypeZmm) { - opFlags |= InstDB::kOpVm; - memFlags |= InstDB::kMemOpVm32z | InstDB::kMemOpVm64z; + else if (indexType == RegType::kX86_Zmm) { + opFlags |= InstDB::OpFlags::kVm32z | InstDB::OpFlags::kVm64z; } else { - opFlags |= InstDB::kOpMem; - if (baseType) - memFlags |= InstDB::kMemOpMib; + if (baseType != RegType::kNone) + opFlags |= InstDB::OpFlags::kFlagMib; } // [RIP + {XMM|YMM|ZMM}] is not allowed. - if (baseType == Reg::kTypeRip && (opFlags & InstDB::kOpVm)) + if (baseType == RegType::kX86_Rip && Support::test(opFlags, InstDB::OpFlags::kVmMask)) return DebugUtils::errored(kErrorInvalidAddress); uint32_t indexId = m.indexId(); @@ -480,28 +451,26 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in combinedRegMask |= Support::bitMask(indexId); } else { - if (!(validationFlags & InstAPI::kValidationFlagVirtRegs)) + if (uint32_t(validationFlags & ValidationFlags::kEnableVirtRegs) == 0) return DebugUtils::errored(kErrorIllegalVirtReg); } // Only used for implicit memory operands having 'seg:[reg]' form, so clear it. regMask = 0; } - else { - opFlags |= InstDB::kOpMem; - } switch (memSize) { - case 0: memFlags |= InstDB::kMemOpAny ; break; - case 1: memFlags |= InstDB::kMemOpM8 ; break; - case 2: memFlags |= InstDB::kMemOpM16 ; break; - case 4: memFlags |= InstDB::kMemOpM32 ; break; - case 6: memFlags |= InstDB::kMemOpM48 ; break; - case 8: memFlags |= InstDB::kMemOpM64 ; break; - case 10: memFlags |= InstDB::kMemOpM80 ; break; - case 16: memFlags |= InstDB::kMemOpM128; break; - case 32: memFlags |= InstDB::kMemOpM256; break; - case 64: memFlags |= InstDB::kMemOpM512; break; + case 0: opFlags |= InstDB::OpFlags::kMemUnspecified; break; + case 1: opFlags |= InstDB::OpFlags::kMem8; break; + case 2: opFlags |= InstDB::OpFlags::kMem16; break; + case 4: opFlags |= InstDB::OpFlags::kMem32; break; + case 6: opFlags |= InstDB::OpFlags::kMem48; break; + case 8: opFlags |= InstDB::OpFlags::kMem64; break; + case 10: opFlags |= InstDB::OpFlags::kMem80; break; + case 16: opFlags |= InstDB::OpFlags::kMem128; break; + case 32: opFlags |= InstDB::OpFlags::kMem256; break; + case 64: opFlags |= InstDB::OpFlags::kMem512; break; + default: return DebugUtils::errored(kErrorInvalidOperandSize); } @@ -509,59 +478,57 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in break; } - case Operand::kOpImm: { + case OperandType::kImm: { uint64_t immValue = op.as<Imm>().valueAs<uint64_t>(); - uint32_t immFlags = 0; if (int64_t(immValue) >= 0) { if (immValue <= 0x7u) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32 | - InstDB::kOpI16 | InstDB::kOpU16 | InstDB::kOpI8 | InstDB::kOpU8 | - InstDB::kOpI4 | InstDB::kOpU4 ; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32 | + InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmU16 | InstDB::OpFlags::kImmI8 | InstDB::OpFlags::kImmU8 | + InstDB::OpFlags::kImmI4 | InstDB::OpFlags::kImmU4 ; else if (immValue <= 0xFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32 | - InstDB::kOpI16 | InstDB::kOpU16 | InstDB::kOpI8 | InstDB::kOpU8 | - InstDB::kOpU4 ; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32 | + InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmU16 | InstDB::OpFlags::kImmI8 | InstDB::OpFlags::kImmU8 | + InstDB::OpFlags::kImmU4 ; else if (immValue <= 0x7Fu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32 | - InstDB::kOpI16 | InstDB::kOpU16 | InstDB::kOpI8 | InstDB::kOpU8 ; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32 | + InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmU16 | InstDB::OpFlags::kImmI8 | InstDB::OpFlags::kImmU8 ; else if (immValue <= 0xFFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32 | - InstDB::kOpI16 | InstDB::kOpU16 | InstDB::kOpU8 ; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32 | + InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmU16 | InstDB::OpFlags::kImmU8 ; else if (immValue <= 0x7FFFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32 | - InstDB::kOpI16 | InstDB::kOpU16 ; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32 | + InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmU16 ; else if (immValue <= 0xFFFFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32 | - InstDB::kOpU16 ; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32 | + InstDB::OpFlags::kImmU16 ; else if (immValue <= 0x7FFFFFFFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpI32 | InstDB::kOpU32; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmU32; else if (immValue <= 0xFFFFFFFFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64 | InstDB::kOpU32; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64 | InstDB::OpFlags::kImmU32; else if (immValue <= 0x7FFFFFFFFFFFFFFFu) - immFlags = InstDB::kOpI64 | InstDB::kOpU64; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmU64; else - immFlags = InstDB::kOpU64; + opFlags = InstDB::OpFlags::kImmU64; } else { immValue = Support::neg(immValue); if (immValue <= 0x8u) - immFlags = InstDB::kOpI64 | InstDB::kOpI32 | InstDB::kOpI16 | InstDB::kOpI8 | InstDB::kOpI4; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmI8 | InstDB::OpFlags::kImmI4; else if (immValue <= 0x80u) - immFlags = InstDB::kOpI64 | InstDB::kOpI32 | InstDB::kOpI16 | InstDB::kOpI8; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmI16 | InstDB::OpFlags::kImmI8; else if (immValue <= 0x8000u) - immFlags = InstDB::kOpI64 | InstDB::kOpI32 | InstDB::kOpI16; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmI32 | InstDB::OpFlags::kImmI16; else if (immValue <= 0x80000000u) - immFlags = InstDB::kOpI64 | InstDB::kOpI32; + opFlags = InstDB::OpFlags::kImmI64 | InstDB::OpFlags::kImmI32; else - immFlags = InstDB::kOpI64; + opFlags = InstDB::OpFlags::kImmI64; } - opFlags |= immFlags; break; } - case Operand::kOpLabel: { - opFlags |= InstDB::kOpRel8 | InstDB::kOpRel32; + case OperandType::kLabel: { + opFlags |= InstDB::OpFlags::kRel8 | InstDB::OpFlags::kRel32; break; } @@ -570,16 +537,14 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in } InstDB::OpSignature& oSigDst = oSigTranslated[i]; - oSigDst.opFlags = opFlags; - oSigDst.memFlags = uint16_t(memFlags); - oSigDst.regMask = uint8_t(regMask & 0xFFu); + oSigDst._flags = uint64_t(opFlags) & 0x00FFFFFFFFFFFFFFu; + oSigDst._regMask = uint8_t(regMask & 0xFFu); combinedOpFlags |= opFlags; } - // Decrease the number of operands of those that are none. This is important - // as Assembler and Compiler may just pass more operands padded with none - // (which means that no operand is given at that index). However, validate - // that there are no gaps (like [reg, none, reg] or [none, reg]). + // Decrease the number of operands of those that are none. This is important as Assembler and Compiler may just pass + // more operands padded with none (which means that no operand is given at that index). However, validate that there + // are no gaps (like [reg, none, reg] or [none, reg]). if (i < opCount) { while (--opCount > i) if (ASMJIT_UNLIKELY(!operands[opCount].isNone())) @@ -587,22 +552,20 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in } // Validate X86 and X64 specific cases. - if (mode == InstDB::kModeX86) { + if (mode == InstDB::Mode::kX86) { // Illegal use of 64-bit register in 32-bit mode. - if (ASMJIT_UNLIKELY((combinedOpFlags & InstDB::kOpGpq) != 0)) + if (ASMJIT_UNLIKELY(Support::test(combinedOpFlags, InstDB::OpFlags::kRegGpq))) return DebugUtils::errored(kErrorInvalidUseOfGpq); } else { // Illegal use of a high 8-bit register with REX prefix. - bool hasREX = inst.hasOption(Inst::kOptionRex) || - ((combinedRegMask & 0xFFFFFF00u) != 0); - if (ASMJIT_UNLIKELY(hasREX && (combinedOpFlags & InstDB::kOpGpbHi) != 0)) + bool hasREX = inst.hasOption(InstOptions::kX86_Rex) || (combinedRegMask & 0xFFFFFF00u) != 0; + if (ASMJIT_UNLIKELY(hasREX && Support::test(combinedOpFlags, InstDB::OpFlags::kRegGpbHi))) return DebugUtils::errored(kErrorInvalidUseOfGpbHi); } - // -------------------------------------------------------------------------- - // [Validate Instruction Signature by Comparing Against All `iSig` Rows] - // -------------------------------------------------------------------------- + // Validate Instruction Signature by Comparing Against All `iSig` Rows + // ------------------------------------------------------------------- const InstDB::InstSignature* iSig = InstDB::_instSignatureTable + commonInfo._iSignatureIndex; const InstDB::InstSignature* iEnd = iSig + commonInfo._iSignatureCount; @@ -616,28 +579,28 @@ ASMJIT_FAVOR_SIZE Error InstInternal::validate(uint32_t arch, const BaseInst& in do { // Check if the architecture is compatible. - if ((iSig->modes & mode) == 0) + if (!iSig->supportsMode(mode)) continue; // Compare the operands table with reference operands. uint32_t j = 0; - uint32_t iSigCount = iSig->opCount; + uint32_t iSigCount = iSig->opCount(); bool localImmOutOfRange = false; if (iSigCount == opCount) { for (j = 0; j < opCount; j++) - if (!x86CheckOSig(oSigTranslated[j], opSignatureTable[iSig->operands[j]], localImmOutOfRange)) + if (!x86CheckOSig(oSigTranslated[j], iSig->opSignature(j), localImmOutOfRange)) break; } - else if (iSigCount - iSig->implicit == opCount) { + else if (iSigCount - iSig->implicitOpCount() == opCount) { uint32_t r = 0; for (j = 0; j < opCount && r < iSigCount; j++, r++) { const InstDB::OpSignature* oChk = oSigTranslated + j; const InstDB::OpSignature* oRef; Next: - oRef = opSignatureTable + iSig->operands[r]; - // Skip implicit. - if ((oRef->opFlags & InstDB::kOpImplicit) != 0) { + oRef = opSignatureTable + iSig->opSignatureIndex(r); + // Skip implicit operands. + if (oRef->isImplicit()) { if (++r >= iSigCount) break; else @@ -667,31 +630,27 @@ Next: } } - // -------------------------------------------------------------------------- - // [Validate AVX512 Options] - // -------------------------------------------------------------------------- + // Validate AVX512 Options + // ----------------------- const RegOnly& extraReg = inst.extraReg(); - const uint32_t kAvx512Options = Inst::kOptionZMask | - Inst::kOptionER | - Inst::kOptionSAE ; - if (options & kAvx512Options) { - if (commonInfo.hasFlag(InstDB::kFlagEvex)) { + if (Support::test(options, kAvx512Options)) { + if (commonInfo.hasFlag(InstDB::InstFlags::kEvex)) { // Validate AVX-512 {z}. - if ((options & Inst::kOptionZMask)) { - if (ASMJIT_UNLIKELY((options & Inst::kOptionZMask) != 0 && !commonInfo.hasAvx512Z())) + if (Support::test(options, InstOptions::kX86_ZMask)) { + if (ASMJIT_UNLIKELY(Support::test(options, InstOptions::kX86_ZMask) && !commonInfo.hasAvx512Z())) return DebugUtils::errored(kErrorInvalidKZeroUse); } // Validate AVX-512 {sae} and {er}. - if (options & (Inst::kOptionSAE | Inst::kOptionER)) { + if (Support::test(options, InstOptions::kX86_SAE | InstOptions::kX86_ER)) { // Rounding control is impossible if the instruction is not reg-to-reg. if (ASMJIT_UNLIKELY(memOp)) return DebugUtils::errored(kErrorInvalidEROrSAE); // Check if {sae} or {er} is supported by the instruction. - if (options & Inst::kOptionER) { + if (Support::test(options, InstOptions::kX86_ER)) { // NOTE: if both {sae} and {er} are set, we don't care, as {sae} is implied. if (ASMJIT_UNLIKELY(!commonInfo.hasAvx512ER())) return DebugUtils::errored(kErrorInvalidEROrSAE); @@ -701,16 +660,13 @@ Next: return DebugUtils::errored(kErrorInvalidEROrSAE); } - // {sae} and {er} are defined for either scalar ops or vector ops that - // require LL to be 10 (512-bit vector operations). We don't need any - // more bits in the instruction database to be able to validate this, as - // each AVX512 instruction that has broadcast is vector instruction (in - // this case we require zmm registers), otherwise it's a scalar instruction, - // which is valid. + // {sae} and {er} are defined for either scalar ops or vector ops that require LL to be 10 (512-bit vector + // operations). We don't need any more bits in the instruction database to be able to validate this, as + // each AVX512 instruction that has broadcast is vector instruction (in this case we require zmm registers), + // otherwise it's a scalar instruction, which is valid. if (commonInfo.hasAvx512B()) { - // Supports broadcast, thus we require LL to be '10', which means there - // have to be ZMM registers used. We don't calculate LL here, but we know - // that it would be '10' if there is at least one ZMM register used. + // Supports broadcast, thus we require LL to be '10', which means there have to be ZMM registers used. We + // don't calculate LL here, but we know that it would be '10' if there is at least one ZMM register used. // There is no {er}/{sae}-enabled instruction with less than two operands. ASMJIT_ASSERT(opCount >= 2); @@ -720,21 +676,19 @@ Next: } } else { - // Not AVX512 instruction - maybe OpExtra is xCX register used by REP/REPNE - // prefix. Otherwise the instruction is invalid. - if ((options & kAvx512Options) || (options & kRepAny) == 0) + // Not an AVX512 instruction - maybe OpExtra is xCX register used by REP/REPNE prefix. + if (Support::test(options, kAvx512Options) || !Support::test(options, kRepAny)) return DebugUtils::errored(kErrorInvalidInstruction); } } - // -------------------------------------------------------------------------- - // [Validate {Extra} Register] - // -------------------------------------------------------------------------- + // Validate {Extra} Register + // ------------------------- if (extraReg.isReg()) { - if (options & kRepAny) { + if (Support::test(options, kRepAny)) { // Validate REP|REPNE {cx|ecx|rcx}. - if (ASMJIT_UNLIKELY(iFlags & InstDB::kFlagRepIgnored)) + if (ASMJIT_UNLIKELY(Support::test(iFlags, InstDB::InstFlags::kRepIgnored))) return DebugUtils::errored(kErrorInvalidExtraReg); if (extraReg.isPhysReg()) { @@ -748,9 +702,9 @@ Next: if (ASMJIT_UNLIKELY(!memOp || extraReg.type() != memOp->baseType())) return DebugUtils::errored(kErrorInvalidExtraReg); } - else if (commonInfo.hasFlag(InstDB::kFlagEvex)) { + else if (commonInfo.hasFlag(InstDB::InstFlags::kEvex)) { // Validate AVX-512 {k}. - if (ASMJIT_UNLIKELY(extraReg.type() != Reg::kTypeKReg)) + if (ASMJIT_UNLIKELY(extraReg.type() != RegType::kX86_KReg)) return DebugUtils::errored(kErrorInvalidExtraReg); if (ASMJIT_UNLIKELY(extraReg.id() == 0 || !commonInfo.hasAvx512K())) @@ -765,12 +719,11 @@ Next: } #endif // !ASMJIT_NO_VALIDATION -// ============================================================================ -// [asmjit::x86::InstInternal - QueryRWInfo] -// ============================================================================ +// x86::InstInternal - QueryRWInfo +// =============================== #ifndef ASMJIT_NO_INTROSPECTION -static const uint64_t rwRegGroupByteMask[Reg::kGroupCount] = { +static const Support::Array<uint64_t, uint32_t(RegGroup::kMaxValue) + 1> rwRegGroupByteMask = {{ 0x00000000000000FFu, // GP. 0xFFFFFFFFFFFFFFFFu, // XMM|YMM|ZMM. 0x00000000000000FFu, // MM. @@ -781,41 +734,41 @@ static const uint64_t rwRegGroupByteMask[Reg::kGroupCount] = { 0x00000000000003FFu, // St(). 0x000000000000FFFFu, // BND. 0x00000000000000FFu // RIP. -}; +}}; -static ASMJIT_INLINE void rwZeroExtendGp(OpRWInfo& opRwInfo, const Gp& reg, uint32_t nativeGpSize) noexcept { +static ASMJIT_FORCE_INLINE void rwZeroExtendGp(OpRWInfo& opRwInfo, const Gp& reg, uint32_t nativeGpSize) noexcept { ASMJIT_ASSERT(BaseReg::isGp(reg.as<Operand>())); if (reg.size() + 4 == nativeGpSize) { - opRwInfo.addOpFlags(OpRWInfo::kZExt); + opRwInfo.addOpFlags(OpRWFlags::kZExt); opRwInfo.setExtendByteMask(~opRwInfo.writeByteMask() & 0xFFu); } } -static ASMJIT_INLINE void rwZeroExtendAvxVec(OpRWInfo& opRwInfo, const Vec& reg) noexcept { +static ASMJIT_FORCE_INLINE void rwZeroExtendAvxVec(OpRWInfo& opRwInfo, const Vec& reg) noexcept { DebugUtils::unused(reg); uint64_t msk = ~Support::fillTrailingBits(opRwInfo.writeByteMask()); if (msk) { - opRwInfo.addOpFlags(OpRWInfo::kZExt); + opRwInfo.addOpFlags(OpRWFlags::kZExt); opRwInfo.setExtendByteMask(msk); } } -static ASMJIT_INLINE void rwZeroExtendNonVec(OpRWInfo& opRwInfo, const Reg& reg) noexcept { +static ASMJIT_FORCE_INLINE void rwZeroExtendNonVec(OpRWInfo& opRwInfo, const Reg& reg) noexcept { uint64_t msk = ~Support::fillTrailingBits(opRwInfo.writeByteMask()) & rwRegGroupByteMask[reg.group()]; if (msk) { - opRwInfo.addOpFlags(OpRWInfo::kZExt); + opRwInfo.addOpFlags(OpRWFlags::kZExt); opRwInfo.setExtendByteMask(msk); } } -static ASMJIT_INLINE Error rwHandleAVX512(const BaseInst& inst, InstRWInfo* out) noexcept { - if (inst.hasExtraReg() && inst.extraReg().type() == Reg::kTypeKReg && out->opCount() > 0) { +static ASMJIT_FORCE_INLINE Error rwHandleAVX512(const BaseInst& inst, const InstDB::CommonInfo& commonInfo, InstRWInfo* out) noexcept { + if (inst.hasExtraReg() && inst.extraReg().type() == RegType::kX86_KReg && out->opCount() > 0) { // AVX-512 instruction that uses a destination with {k} register (zeroing vs masking). - out->_extraReg.addOpFlags(OpRWInfo::kRead); + out->_extraReg.addOpFlags(OpRWFlags::kRead); out->_extraReg.setReadByteMask(0xFF); - if (!inst.hasOption(Inst::kOptionZMask)) { - out->_operands[0].addOpFlags(OpRWInfo::kRead); + if (!inst.hasOption(InstOptions::kX86_ZMask) && !commonInfo.hasAvx512Flag(InstDB::Avx512Flags::kImplicitZ)) { + out->_operands[0].addOpFlags(OpRWFlags::kRead); out->_operands[0]._readByteMask |= out->_operands[0]._writeByteMask; } } @@ -823,28 +776,27 @@ static ASMJIT_INLINE Error rwHandleAVX512(const BaseInst& inst, InstRWInfo* out) return kErrorOk; } -Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { - using namespace Status; - +Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { // Only called when `arch` matches X86 family. ASMJIT_ASSERT(Environment::isFamilyX86(arch)); // Get the instruction data. - uint32_t instId = inst.id(); + InstId instId = inst.id(); if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId))) return DebugUtils::errored(kErrorInvalidInstruction); // Read/Write flags. - const InstDB::CommonInfoTableB& tabB = InstDB::_commonInfoTableB[InstDB::_instInfoTable[instId]._commonInfoIndexB]; - const InstDB::RWFlagsInfoTable& rwFlags = InstDB::_rwFlagsInfoTable[tabB._rwFlagsIndex]; - + const InstDB::InstInfo& instInfo = InstDB::_instInfoTable[instId]; + const InstDB::CommonInfo& commonInfo = InstDB::_commonInfoTable[instInfo._commonInfoIndex]; + const InstDB::AdditionalInfo& additionalInfo = InstDB::_additionalInfoTable[instInfo._additionalInfoIndex]; + const InstDB::RWFlagsInfoTable& rwFlags = InstDB::_rwFlagsInfoTable[additionalInfo._rwFlagsIndex]; // There are two data tables, one for `opCount == 2` and the second for // `opCount != 2`. There are two reasons for that: - // - There are instructions that share the same name that have both 2 - // or 3 operands, which have different RW information / semantics. - // - There must be 2 tables otherwise the lookup index won't fit into - // 8 bits (there is more than 256 records of combined rwInfo A and B). + // - There are instructions that share the same name that have both 2 or 3 operands, which have different + // RW information / semantics. + // - There must be 2 tables otherwise the lookup index won't fit into 8 bits (there is more than 256 records + // of combined rwInfo A and B). const InstDB::RWInfo& instRwInfo = opCount == 2 ? InstDB::rwInfoA[InstDB::rwInfoIndexA[instId]] : InstDB::rwInfoB[InstDB::rwInfoIndexB[instId]]; const InstDB::RWInfoRm& instRmInfo = InstDB::rwInfoRm[instRwInfo.rmInfo]; @@ -853,17 +805,17 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera out->_opCount = uint8_t(opCount); out->_rmFeature = instRmInfo.rmFeature; out->_extraReg.reset(); - out->_readFlags = rwFlags.readFlags; - out->_writeFlags = rwFlags.writeFlags; + out->_readFlags = CpuRWFlags(rwFlags.readFlags); + out->_writeFlags = CpuRWFlags(rwFlags.writeFlags); uint32_t nativeGpSize = Environment::registerSizeFromArch(arch); - constexpr uint32_t R = OpRWInfo::kRead; - constexpr uint32_t W = OpRWInfo::kWrite; - constexpr uint32_t X = OpRWInfo::kRW; - constexpr uint32_t RegM = OpRWInfo::kRegMem; - constexpr uint32_t RegPhys = OpRWInfo::kRegPhysId; - constexpr uint32_t MibRead = OpRWInfo::kMemBaseRead | OpRWInfo::kMemIndexRead; + constexpr OpRWFlags R = OpRWFlags::kRead; + constexpr OpRWFlags W = OpRWFlags::kWrite; + constexpr OpRWFlags X = OpRWFlags::kRW; + constexpr OpRWFlags RegM = OpRWFlags::kRegMem; + constexpr OpRWFlags RegPhys = OpRWFlags::kRegPhysId; + constexpr OpRWFlags MibRead = OpRWFlags::kMemBaseRead | OpRWFlags::kMemIndexRead; if (instRwInfo.category == InstDB::RWInfo::kCategoryGeneric) { uint32_t i; @@ -880,7 +832,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera continue; } - op._opFlags = rwOpData.flags & ~(OpRWInfo::kZExt); + op._opFlags = rwOpData.flags & ~OpRWFlags::kZExt; op._physId = rwOpData.physId; op._rmSize = 0; op._resetReserved(); @@ -894,6 +846,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera op._readByteMask = rByteMask; op._writeByteMask = wByteMask; op._extendByteMask = 0; + op._consecutiveLeadCount = rwOpData.consecutiveLeadCount; if (srcOp.isReg()) { // Zero extension. @@ -904,7 +857,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera // - 32-bit writes ARE zero extended. rwZeroExtendGp(op, srcOp.as<Gp>(), nativeGpSize); } - else if (rwOpData.flags & OpRWInfo::kZExt) { + else if (Support::test(rwOpData.flags, OpRWFlags::kZExt)) { // Otherwise follow ZExt. rwZeroExtendNonVec(op, srcOp.as<Gp>()); } @@ -918,10 +871,10 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera const x86::Mem& memOp = srcOp.as<x86::Mem>(); // The RW flags of BASE+INDEX are either provided by the data, which means // that the instruction is border-case, or they are deduced from the operand. - if (memOp.hasBaseReg() && !(op.opFlags() & OpRWInfo::kMemBaseRW)) - op.addOpFlags(OpRWInfo::kMemBaseRead); - if (memOp.hasIndexReg() && !(op.opFlags() & OpRWInfo::kMemIndexRW)) - op.addOpFlags(OpRWInfo::kMemIndexRead); + if (memOp.hasBaseReg() && !op.hasOpFlag(OpRWFlags::kMemBaseRW)) + op.addOpFlags(OpRWFlags::kMemBaseRead); + if (memOp.hasIndexReg() && !op.hasOpFlag(OpRWFlags::kMemIndexRW)) + op.addOpFlags(OpRWFlags::kMemIndexRead); } } @@ -954,14 +907,13 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera } while (it.hasNext()); } - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } switch (instRwInfo.category) { case InstDB::RWInfo::kCategoryMov: { - // Special case for 'mov' instruction. Here there are some variants that - // we have to handle as 'mov' can be used to move between GP, segment, - // control and debug registers. Moving between GP registers also allow to + // Special case for 'mov' instruction. Here there are some variants that we have to handle as 'mov' can be + // used to move between GP, segment, control and debug registers. Moving between GP registers also allow to // use memory operand. if (opCount == 2) { @@ -994,14 +946,24 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera if (o0.isGp() && (o1.isCReg() || o1.isDReg())) { out->_operands[0].reset(W, nativeGpSize); out->_operands[1].reset(R, nativeGpSize); - out->_writeFlags = kOF | kSF | kZF | kAF | kPF | kCF; + out->_writeFlags = CpuRWFlags::kX86_OF | + CpuRWFlags::kX86_SF | + CpuRWFlags::kX86_ZF | + CpuRWFlags::kX86_AF | + CpuRWFlags::kX86_PF | + CpuRWFlags::kX86_CF; return kErrorOk; } if ((o0.isCReg() || o0.isDReg()) && o1.isGp()) { out->_operands[0].reset(W, nativeGpSize); out->_operands[1].reset(R, nativeGpSize); - out->_writeFlags = kOF | kSF | kZF | kAF | kPF | kCF; + out->_writeFlags = CpuRWFlags::kX86_OF | + CpuRWFlags::kX86_SF | + CpuRWFlags::kX86_ZF | + CpuRWFlags::kX86_AF | + CpuRWFlags::kX86_PF | + CpuRWFlags::kX86_CF; return kErrorOk; } } @@ -1159,9 +1121,8 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera } case InstDB::RWInfo::kCategoryMovh64: { - // Special case for 'movhpd|movhps' instructions. Note that this is only - // required for legacy (non-AVX) variants as AVX instructions use either - // 2 or 3 operands that are in `kCategoryGeneric` category. + // Special case for 'movhpd|movhps' instructions. Note that this is only required for legacy (non-AVX) + // variants as AVX instructions use either 2 or 3 operands that are in `kCategoryGeneric` category. if (opCount == 2) { if (BaseReg::isVec(operands[0]) && operands[1].isMem()) { out->_operands[0].reset(W, 8); @@ -1243,9 +1204,8 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera } case InstDB::RWInfo::kCategoryVmovddup: { - // Special case for 'vmovddup' instruction. This instruction has an - // interesting semantic as 128-bit XMM version only uses 64-bit memory - // operand (m64), however, 256/512-bit versions use 256/512-bit memory + // Special case for 'vmovddup' instruction. This instruction has an interesting semantic as 128-bit XMM + // version only uses 64-bit memory operand (m64), however, 256/512-bit versions use 256/512-bit memory // operand, respectively. if (opCount == 2) { if (BaseReg::isVec(operands[0]) && BaseReg::isVec(operands[1])) { @@ -1257,7 +1217,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera out->_operands[1]._readByteMask &= 0x00FF00FF00FF00FFu; rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>()); - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } if (BaseReg::isVec(operands[0]) && operands[1].isMem()) { @@ -1268,7 +1228,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera out->_operands[1].reset(R | MibRead, o1Size); rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>()); - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } } break; @@ -1342,7 +1302,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera if (BaseReg::isVec(operands[0])) rwZeroExtendAvxVec(out->_operands[0], operands[0].as<Vec>()); - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } if (operands[0].isReg() && operands[1].isMem()) { @@ -1361,7 +1321,7 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera out->_operands[0].reset(W | MibRead, size0); out->_operands[1].reset(R, size1); - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } } break; @@ -1413,13 +1373,13 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera out->_operands[1].setRmSize(size1); } - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } if (operands[0].isReg() && operands[1].isMem()) { out->_operands[1].addOpFlags(MibRead); - return rwHandleAVX512(inst, out); + return rwHandleAVX512(inst, commonInfo, out); } } break; @@ -1430,16 +1390,15 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera } #endif // !ASMJIT_NO_INTROSPECTION -// ============================================================================ -// [asmjit::x86::InstInternal - QueryFeatures] -// ============================================================================ +// x86::InstInternal - QueryFeatures +// ================================= #ifndef ASMJIT_NO_INTROSPECTION struct RegAnalysis { uint32_t regTypeMask; uint32_t highVecUsed; - inline bool hasRegType(uint32_t regType) const noexcept { + inline bool hasRegType(RegType regType) const noexcept { return Support::bitTest(regTypeMask, regType); } }; @@ -1469,31 +1428,31 @@ static RegAnalysis InstInternal_regAnalysis(const Operand_* operands, size_t opC return RegAnalysis { mask, highVecUsed }; } -static ASMJIT_INLINE uint32_t InstInternal_usesAvx512(uint32_t instOptions, const RegOnly& extraReg, const RegAnalysis& regAnalysis) noexcept { - uint32_t hasEvex = instOptions & (Inst::kOptionEvex | Inst::_kOptionAvx512Mask); - uint32_t hasKMask = extraReg.type() == Reg::kTypeKReg; - uint32_t hasKOrZmm = regAnalysis.regTypeMask & Support::bitMask(Reg::kTypeZmm, Reg::kTypeKReg); +static inline uint32_t InstInternal_usesAvx512(InstOptions instOptions, const RegOnly& extraReg, const RegAnalysis& regAnalysis) noexcept { + uint32_t hasEvex = uint32_t(instOptions & (InstOptions::kX86_Evex | InstOptions::kX86_AVX512Mask)); + uint32_t hasKMask = extraReg.type() == RegType::kX86_KReg; + uint32_t hasKOrZmm = regAnalysis.regTypeMask & Support::bitMask(RegType::kX86_Zmm, RegType::kX86_KReg); return hasEvex | hasKMask | hasKOrZmm; } -Error InstInternal::queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept { +Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { // Only called when `arch` matches X86 family. DebugUtils::unused(arch); ASMJIT_ASSERT(Environment::isFamilyX86(arch)); // Get the instruction data. - uint32_t instId = inst.id(); - uint32_t options = inst.options(); + InstId instId = inst.id(); + InstOptions options = inst.options(); if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId))) return DebugUtils::errored(kErrorInvalidInstruction); const InstDB::InstInfo& instInfo = InstDB::infoById(instId); - const InstDB::CommonInfoTableB& tableB = InstDB::_commonInfoTableB[instInfo._commonInfoIndexB]; + const InstDB::AdditionalInfo& additionalInfo = InstDB::_additionalInfoTable[instInfo._additionalInfoIndex]; - const uint8_t* fData = tableB.featuresBegin(); - const uint8_t* fEnd = tableB.featuresEnd(); + const uint8_t* fData = additionalInfo.featuresBegin(); + const uint8_t* fEnd = additionalInfo.featuresEnd(); // Copy all features to `out`. out->reset(); @@ -1506,92 +1465,87 @@ Error InstInternal::queryFeatures(uint32_t arch, const BaseInst& inst, const Ope // Since AsmJit aggregates instructions that share the same name we have to // deal with some special cases and also with MMX/SSE and AVX/AVX2 overlaps. - if (fData != tableB.featuresBegin()) { + if (fData != additionalInfo.featuresBegin()) { RegAnalysis regAnalysis = InstInternal_regAnalysis(operands, opCount); // Handle MMX vs SSE overlap. - if (out->has(Features::kMMX) || out->has(Features::kMMX2)) { - // Only instructions defined by SSE and SSE2 overlap. Instructions - // introduced by newer instruction sets like SSE3+ don't state MMX as - // they require SSE3+. - if (out->has(Features::kSSE) || out->has(Features::kSSE2)) { - if (!regAnalysis.hasRegType(Reg::kTypeXmm)) { + if (out->has(CpuFeatures::X86::kMMX) || out->has(CpuFeatures::X86::kMMX2)) { + // Only instructions defined by SSE and SSE2 overlap. Instructions introduced by newer instruction sets like + // SSE3+ don't state MMX as they require SSE3+. + if (out->has(CpuFeatures::X86::kSSE) || out->has(CpuFeatures::X86::kSSE2)) { + if (!regAnalysis.hasRegType(RegType::kX86_Xmm)) { // The instruction doesn't use XMM register(s), thus it's MMX/MMX2 only. - out->remove(Features::kSSE); - out->remove(Features::kSSE2); - out->remove(Features::kSSE4_1); + out->remove(CpuFeatures::X86::kSSE); + out->remove(CpuFeatures::X86::kSSE2); + out->remove(CpuFeatures::X86::kSSE4_1); } else { - out->remove(Features::kMMX); - out->remove(Features::kMMX2); + out->remove(CpuFeatures::X86::kMMX); + out->remove(CpuFeatures::X86::kMMX2); } - // Special case: PEXTRW instruction is MMX/SSE2 instruction. However, - // MMX/SSE version cannot access memory (only register to register - // extract) so when SSE4.1 introduced the whole family of PEXTR/PINSR - // instructions they also introduced PEXTRW with a new opcode 0x15 that - // can extract directly to memory. This instruction is, of course, not - // compatible with MMX/SSE2 and would #UD if SSE4.1 is not supported. + // Special case: PEXTRW instruction is MMX/SSE2 instruction. However, MMX/SSE version cannot access memory + // (only register to register extract) so when SSE4.1 introduced the whole family of PEXTR/PINSR instructions + // they also introduced PEXTRW with a new opcode 0x15 that can extract directly to memory. This instruction + // is, of course, not compatible with MMX/SSE2 and would #UD if SSE4.1 is not supported. if (instId == Inst::kIdPextrw) { if (opCount >= 1 && operands[0].isMem()) - out->remove(Features::kSSE2); + out->remove(CpuFeatures::X86::kSSE2); else - out->remove(Features::kSSE4_1); + out->remove(CpuFeatures::X86::kSSE4_1); } } } // Handle PCLMULQDQ vs VPCLMULQDQ. - if (out->has(Features::kVPCLMULQDQ)) { - if (regAnalysis.hasRegType(Reg::kTypeZmm) || Support::bitTest(options, Inst::kOptionEvex)) { + if (out->has(CpuFeatures::X86::kVPCLMULQDQ)) { + if (regAnalysis.hasRegType(RegType::kX86_Zmm) || Support::test(options, InstOptions::kX86_Evex)) { // AVX512_F & VPCLMULQDQ. - out->remove(Features::kAVX, Features::kPCLMULQDQ); + out->remove(CpuFeatures::X86::kAVX, CpuFeatures::X86::kPCLMULQDQ); } - else if (regAnalysis.hasRegType(Reg::kTypeYmm)) { - out->remove(Features::kAVX512_F, Features::kAVX512_VL); + else if (regAnalysis.hasRegType(RegType::kX86_Ymm)) { + out->remove(CpuFeatures::X86::kAVX512_F, CpuFeatures::X86::kAVX512_VL); } else { // AVX & PCLMULQDQ. - out->remove(Features::kAVX512_F, Features::kAVX512_VL, Features::kVPCLMULQDQ); + out->remove(CpuFeatures::X86::kAVX512_F, CpuFeatures::X86::kAVX512_VL, CpuFeatures::X86::kVPCLMULQDQ); } } // Handle AVX vs AVX2 overlap. - if (out->has(Features::kAVX) && out->has(Features::kAVX2)) { + if (out->has(CpuFeatures::X86::kAVX) && out->has(CpuFeatures::X86::kAVX2)) { bool isAVX2 = true; - // Special case: VBROADCASTSS and VBROADCASTSD were introduced in AVX, but - // only version that uses memory as a source operand. AVX2 then added support - // for register source operand. + // Special case: VBROADCASTSS and VBROADCASTSD were introduced in AVX, but only version that uses memory as a + // source operand. AVX2 then added support for register source operand. if (instId == Inst::kIdVbroadcastss || instId == Inst::kIdVbroadcastsd) { if (opCount > 1 && operands[1].isMem()) isAVX2 = false; } else { - // AVX instruction set doesn't support integer operations on YMM registers - // as these were later introcuced by AVX2. In our case we have to check if - // YMM register(s) are in use and if that is the case this is an AVX2 instruction. - if (!(regAnalysis.regTypeMask & Support::bitMask(Reg::kTypeYmm, Reg::kTypeZmm))) + // AVX instruction set doesn't support integer operations on YMM registers as these were later introcuced by + // AVX2. In our case we have to check if YMM register(s) are in use and if that is the case this is an AVX2 + // instruction. + if (!(regAnalysis.regTypeMask & Support::bitMask(RegType::kX86_Ymm, RegType::kX86_Zmm))) isAVX2 = false; } if (isAVX2) - out->remove(Features::kAVX); + out->remove(CpuFeatures::X86::kAVX); else - out->remove(Features::kAVX2); + out->remove(CpuFeatures::X86::kAVX2); } // Handle AVX|AVX2|FMA|F16C vs AVX512 overlap. - if (out->has(Features::kAVX) || out->has(Features::kAVX2) || out->has(Features::kFMA) || out->has(Features::kF16C)) { + if (out->has(CpuFeatures::X86::kAVX) || out->has(CpuFeatures::X86::kAVX2) || out->has(CpuFeatures::X86::kFMA) || out->has(CpuFeatures::X86::kF16C)) { // Only AVX512-F|BW|DQ allow to encode AVX/AVX2/FMA/F16C instructions - if (out->has(Features::kAVX512_F) || out->has(Features::kAVX512_BW) || out->has(Features::kAVX512_DQ)) { + if (out->has(CpuFeatures::X86::kAVX512_F) || out->has(CpuFeatures::X86::kAVX512_BW) || out->has(CpuFeatures::X86::kAVX512_DQ)) { uint32_t usesAvx512 = InstInternal_usesAvx512(options, inst.extraReg(), regAnalysis); uint32_t mustUseEvex = 0; switch (instId) { - // Special case: VPSLLDQ and VPSRLDQ instructions only allow `reg, reg. imm` - // combination in AVX|AVX2 mode, then AVX-512 introduced `reg, reg/mem, imm` - // combination that uses EVEX prefix. This means that if the second operand - // is memory then this is AVX-512_BW instruction and not AVX/AVX2 instruction. + // Special case: VPSLLDQ and VPSRLDQ instructions only allow `reg, reg. imm` combination in AVX|AVX2 mode, + // then AVX-512 introduced `reg, reg/mem, imm` combination that uses EVEX prefix. This means that if the + // second operand is memory then this is AVX-512_BW instruction and not AVX/AVX2 instruction. case Inst::kIdVpslldq: case Inst::kIdVpsrldq: mustUseEvex = opCount >= 2 && operands[1].isMem(); @@ -1617,37 +1571,35 @@ Error InstInternal::queryFeatures(uint32_t arch, const BaseInst& inst, const Ope } if (!(usesAvx512 | mustUseEvex | regAnalysis.highVecUsed)) - out->remove(Features::kAVX512_F, Features::kAVX512_BW, Features::kAVX512_DQ, Features::kAVX512_VL); + out->remove(CpuFeatures::X86::kAVX512_F, CpuFeatures::X86::kAVX512_BW, CpuFeatures::X86::kAVX512_DQ, CpuFeatures::X86::kAVX512_VL); else - out->remove(Features::kAVX, Features::kAVX2, Features::kFMA, Features::kF16C); + out->remove(CpuFeatures::X86::kAVX, CpuFeatures::X86::kAVX2, CpuFeatures::X86::kFMA, CpuFeatures::X86::kF16C); } } // Handle AVX_VNNI vs AVX512_VNNI overlap. - if (out->has(Features::kAVX512_VNNI)) { - // By default the AVX512_VNNI instruction should be used, because it was - // introduced first. However, VEX|VEX3 prefix can be used to force AVX_VNNI - // instead. + if (out->has(CpuFeatures::X86::kAVX512_VNNI)) { + // By default the AVX512_VNNI instruction should be used, because it was introduced first. However, VEX|VEX3 + // prefix can be used to force AVX_VNNI instead. uint32_t usesAvx512 = InstInternal_usesAvx512(options, inst.extraReg(), regAnalysis); - if (!usesAvx512 && (options & (Inst::kOptionVex | Inst::kOptionVex3)) != 0) - out->remove(Features::kAVX512_VNNI, Features::kAVX512_VL); + if (!usesAvx512 && Support::test(options, InstOptions::kX86_Vex | InstOptions::kX86_Vex3)) + out->remove(CpuFeatures::X86::kAVX512_VNNI, CpuFeatures::X86::kAVX512_VL); else - out->remove(Features::kAVX_VNNI); + out->remove(CpuFeatures::X86::kAVX_VNNI); } // Clear AVX512_VL if ZMM register is used. - if (regAnalysis.hasRegType(Reg::kTypeZmm)) - out->remove(Features::kAVX512_VL); + if (regAnalysis.hasRegType(RegType::kX86_Zmm)) + out->remove(CpuFeatures::X86::kAVX512_VL); } return kErrorOk; } #endif // !ASMJIT_NO_INTROSPECTION -// ============================================================================ -// [asmjit::x86::InstInternal - Unit] -// ============================================================================ +// x86::InstInternal - Tests +// ========================= #if defined(ASMJIT_TEST) UNIT(x86_inst_api_text) { @@ -1655,12 +1607,12 @@ UNIT(x86_inst_api_text) { INFO("Matching all X86 instructions"); for (uint32_t a = 1; a < Inst::_kIdCount; a++) { StringTmp<128> aName; - EXPECT(InstInternal::instIdToString(0, a, aName) == kErrorOk, + EXPECT(InstInternal::instIdToString(Arch::kX86, a, aName) == kErrorOk, "Failed to get the name of instruction #%u", a); - uint32_t b = InstInternal::stringToInstId(0, aName.data(), aName.size()); + uint32_t b = InstInternal::stringToInstId(Arch::kX86, aName.data(), aName.size()); StringTmp<128> bName; - InstInternal::instIdToString(0, b, bName); + InstInternal::instIdToString(Arch::kX86, b, bName); EXPECT(a == b, "Instructions do not match \"%s\" (#%u) != \"%s\" (#%u)", aName.data(), a, bName.data(), b); diff --git a/src/asmjit/x86/x86instapi_p.h b/src/asmjit/x86/x86instapi_p.h index 83b3f77..0a4b10a 100644 --- a/src/asmjit/x86/x86instapi_p.h +++ b/src/asmjit/x86/x86instapi_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86INSTAPI_P_H_INCLUDED #define ASMJIT_X86_X86INSTAPI_P_H_INCLUDED @@ -36,17 +18,17 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace InstInternal { #ifndef ASMJIT_NO_TEXT -Error instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept; -uint32_t stringToInstId(uint32_t arch, const char* s, size_t len) noexcept; +Error instIdToString(Arch arch, InstId instId, String& output) noexcept; +InstId stringToInstId(Arch arch, const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -Error validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags) noexcept; +Error validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION -Error queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; -Error queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept; +Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; +Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; #endif // !ASMJIT_NO_INTROSPECTION } // {InstInternal} diff --git a/src/asmjit/x86/x86instdb.cpp b/src/asmjit/x86/x86instdb.cpp index 374d878..3bf5d23 100644 --- a/src/asmjit/x86/x86instdb.cpp +++ b/src/asmjit/x86/x86instdb.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib // ---------------------------------------------------------------------------- // IMPORTANT: AsmJit now uses an external instruction database to populate @@ -45,28 +27,24 @@ #include "../core/cpuinfo.h" #include "../core/misc_p.h" #include "../core/support.h" -#include "../x86/x86features.h" #include "../x86/x86instdb_p.h" #include "../x86/x86opcode_p.h" #include "../x86/x86operand.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::InstDB - InstInfo] -// ============================================================================ +// x86::InstDB - InstInfo +// ====================== // Instruction opcode definitions: // - `O` encodes X86|MMX|SSE instructions. // - `V` encodes VEX|XOP|EVEX instructions. // - `E` encodes EVEX instructions only. -#define O_ENCODE(VEX, PREFIX, OPCODE, O, L, W, EvexW, N, TT) \ - ((PREFIX) | (OPCODE) | (O) | (L) | (W) | (EvexW) | (N) | (TT) | \ - (VEX && ((PREFIX) & Opcode::kMM_Mask) != Opcode::kMM_0F ? int(Opcode::kMM_ForceVex3) : 0)) +#define O_ENCODE(PREFIX, OPCODE, O, L, W, EvexW, N, TT) ((PREFIX) | (OPCODE) | (O) | (L) | (W) | (EvexW) | (N) | (TT)) -#define O(PREFIX, OPCODE, ModO, LL, W, EvexW, N, ModRM) (O_ENCODE(0, Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kModRM_##ModRM)) -#define V(PREFIX, OPCODE, ModO, LL, W, EvexW, N, TT) (O_ENCODE(1, Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kCDTT_##TT)) -#define E(PREFIX, OPCODE, ModO, LL, W, EvexW, N, TT) (O_ENCODE(1, Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kCDTT_##TT) | Opcode::kMM_ForceEvex) +#define O(PREFIX, OPCODE, ModO, LL, W, EvexW, N, ModRM) (O_ENCODE(Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kModRM_##ModRM)) +#define V(PREFIX, OPCODE, ModO, LL, W, EvexW, N, TT) (O_ENCODE(Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kCDTT_##TT)) +#define E(PREFIX, OPCODE, ModO, LL, W, EvexW, N, TT) (O_ENCODE(Opcode::k##PREFIX, 0x##OPCODE, Opcode::kModO_##ModO, Opcode::kLL_##LL, Opcode::kW_##W, Opcode::kEvex_W_##EvexW, Opcode::kCDSHL_##N, Opcode::kCDTT_##TT) | Opcode::kMM_ForceEvex) #define O_FPU(PREFIX, OPCODE, ModO) (Opcode::kFPU_##PREFIX | (0x##OPCODE & 0xFFu) | ((0x##OPCODE >> 8) << Opcode::kFPU_2B_Shift) | Opcode::kModO_##ModO) // Don't store `_nameDataIndex` if instruction names are disabled. Since some @@ -78,10 +56,10 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) #endif // Defines an X86 instruction. -#define INST(id, encoding, opcode0, opcode1, mainOpcodeIndex, altOpcodeIndex, nameDataIndex, commomInfoIndexA, commomInfoIndexB) { \ +#define INST(id, encoding, opcode0, opcode1, mainOpcodeIndex, altOpcodeIndex, nameDataIndex, commomInfoIndex, additionalInfoIndex) { \ uint32_t(NAME_DATA_INDEX(nameDataIndex)), \ - uint32_t(commomInfoIndexA), \ - uint32_t(commomInfoIndexB), \ + uint32_t(commomInfoIndex), \ + uint32_t(additionalInfoIndex), \ uint8_t(InstDB::kEncoding##encoding), \ uint8_t((opcode0) & 0xFFu), \ uint8_t(mainOpcodeIndex), \ @@ -102,25 +80,25 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { INST(Adc , X86Arith , O(000000,10,2,_,x,_,_,_ ), 0 , 1 , 0 , 17 , 3 , 2 ), // #5 INST(Adcx , X86Rm , O(660F38,F6,_,_,x,_,_,_ ), 0 , 2 , 0 , 21 , 4 , 3 ), // #6 INST(Add , X86Arith , O(000000,00,0,_,x,_,_,_ ), 0 , 0 , 0 , 3146 , 3 , 1 ), // #7 - INST(Addpd , ExtRm , O(660F00,58,_,_,_,_,_,_ ), 0 , 3 , 0 , 5106 , 5 , 4 ), // #8 - INST(Addps , ExtRm , O(000F00,58,_,_,_,_,_,_ ), 0 , 4 , 0 , 5118 , 5 , 5 ), // #9 - INST(Addsd , ExtRm , O(F20F00,58,_,_,_,_,_,_ ), 0 , 5 , 0 , 5340 , 6 , 4 ), // #10 + INST(Addpd , ExtRm , O(660F00,58,_,_,_,_,_,_ ), 0 , 3 , 0 , 5788 , 5 , 4 ), // #8 + INST(Addps , ExtRm , O(000F00,58,_,_,_,_,_,_ ), 0 , 4 , 0 , 5800 , 5 , 5 ), // #9 + INST(Addsd , ExtRm , O(F20F00,58,_,_,_,_,_,_ ), 0 , 5 , 0 , 6118 , 6 , 4 ), // #10 INST(Addss , ExtRm , O(F30F00,58,_,_,_,_,_,_ ), 0 , 6 , 0 , 3283 , 7 , 5 ), // #11 - INST(Addsubpd , ExtRm , O(660F00,D0,_,_,_,_,_,_ ), 0 , 3 , 0 , 4845 , 5 , 6 ), // #12 - INST(Addsubps , ExtRm , O(F20F00,D0,_,_,_,_,_,_ ), 0 , 5 , 0 , 4857 , 5 , 6 ), // #13 + INST(Addsubpd , ExtRm , O(660F00,D0,_,_,_,_,_,_ ), 0 , 3 , 0 , 5410 , 5 , 6 ), // #12 + INST(Addsubps , ExtRm , O(F20F00,D0,_,_,_,_,_,_ ), 0 , 5 , 0 , 5422 , 5 , 6 ), // #13 INST(Adox , X86Rm , O(F30F38,F6,_,_,x,_,_,_ ), 0 , 7 , 0 , 26 , 4 , 7 ), // #14 - INST(Aesdec , ExtRm , O(660F38,DE,_,_,_,_,_,_ ), 0 , 2 , 0 , 3338 , 5 , 8 ), // #15 - INST(Aesdeclast , ExtRm , O(660F38,DF,_,_,_,_,_,_ ), 0 , 2 , 0 , 3346 , 5 , 8 ), // #16 - INST(Aesenc , ExtRm , O(660F38,DC,_,_,_,_,_,_ ), 0 , 2 , 0 , 3358 , 5 , 8 ), // #17 - INST(Aesenclast , ExtRm , O(660F38,DD,_,_,_,_,_,_ ), 0 , 2 , 0 , 3366 , 5 , 8 ), // #18 - INST(Aesimc , ExtRm , O(660F38,DB,_,_,_,_,_,_ ), 0 , 2 , 0 , 3378 , 5 , 8 ), // #19 - INST(Aeskeygenassist , ExtRmi , O(660F3A,DF,_,_,_,_,_,_ ), 0 , 8 , 0 , 3386 , 8 , 8 ), // #20 + INST(Aesdec , ExtRm , O(660F38,DE,_,_,_,_,_,_ ), 0 , 2 , 0 , 3352 , 5 , 8 ), // #15 + INST(Aesdeclast , ExtRm , O(660F38,DF,_,_,_,_,_,_ ), 0 , 2 , 0 , 3360 , 5 , 8 ), // #16 + INST(Aesenc , ExtRm , O(660F38,DC,_,_,_,_,_,_ ), 0 , 2 , 0 , 3372 , 5 , 8 ), // #17 + INST(Aesenclast , ExtRm , O(660F38,DD,_,_,_,_,_,_ ), 0 , 2 , 0 , 3380 , 5 , 8 ), // #18 + INST(Aesimc , ExtRm , O(660F38,DB,_,_,_,_,_,_ ), 0 , 2 , 0 , 3392 , 5 , 8 ), // #19 + INST(Aeskeygenassist , ExtRmi , O(660F3A,DF,_,_,_,_,_,_ ), 0 , 8 , 0 , 3400 , 8 , 8 ), // #20 INST(And , X86Arith , O(000000,20,4,_,x,_,_,_ ), 0 , 9 , 0 , 2525 , 9 , 1 ), // #21 - INST(Andn , VexRvm_Wx , V(000F38,F2,_,0,x,_,_,_ ), 0 , 10 , 0 , 6814 , 10 , 9 ), // #22 - INST(Andnpd , ExtRm , O(660F00,55,_,_,_,_,_,_ ), 0 , 3 , 0 , 3419 , 5 , 4 ), // #23 - INST(Andnps , ExtRm , O(000F00,55,_,_,_,_,_,_ ), 0 , 4 , 0 , 3427 , 5 , 5 ), // #24 - INST(Andpd , ExtRm , O(660F00,54,_,_,_,_,_,_ ), 0 , 3 , 0 , 4359 , 11 , 4 ), // #25 - INST(Andps , ExtRm , O(000F00,54,_,_,_,_,_,_ ), 0 , 4 , 0 , 4369 , 11 , 5 ), // #26 + INST(Andn , VexRvm_Wx , V(000F38,F2,_,0,x,_,_,_ ), 0 , 10 , 0 , 7789 , 10 , 9 ), // #22 + INST(Andnpd , ExtRm , O(660F00,55,_,_,_,_,_,_ ), 0 , 3 , 0 , 3433 , 5 , 4 ), // #23 + INST(Andnps , ExtRm , O(000F00,55,_,_,_,_,_,_ ), 0 , 4 , 0 , 3441 , 5 , 5 ), // #24 + INST(Andpd , ExtRm , O(660F00,54,_,_,_,_,_,_ ), 0 , 3 , 0 , 4745 , 11 , 4 ), // #25 + INST(Andps , ExtRm , O(000F00,54,_,_,_,_,_,_ ), 0 , 4 , 0 , 4755 , 11 , 5 ), // #26 INST(Arpl , X86Mr_NoSize , O(000000,63,_,_,_,_,_,_ ), 0 , 0 , 0 , 31 , 12 , 10 ), // #27 INST(Bextr , VexRmv_Wx , V(000F38,F7,_,0,x,_,_,_ ), 0 , 10 , 0 , 36 , 13 , 9 ), // #28 INST(Blcfill , VexVm_Wx , V(XOP_M9,01,1,0,x,_,_,_ ), 0 , 11 , 0 , 42 , 14 , 11 ), // #29 @@ -128,10 +106,10 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { INST(Blcic , VexVm_Wx , V(XOP_M9,01,5,0,x,_,_,_ ), 0 , 13 , 0 , 55 , 14 , 11 ), // #31 INST(Blcmsk , VexVm_Wx , V(XOP_M9,02,1,0,x,_,_,_ ), 0 , 11 , 0 , 61 , 14 , 11 ), // #32 INST(Blcs , VexVm_Wx , V(XOP_M9,01,3,0,x,_,_,_ ), 0 , 14 , 0 , 68 , 14 , 11 ), // #33 - INST(Blendpd , ExtRmi , O(660F3A,0D,_,_,_,_,_,_ ), 0 , 8 , 0 , 3469 , 8 , 12 ), // #34 - INST(Blendps , ExtRmi , O(660F3A,0C,_,_,_,_,_,_ ), 0 , 8 , 0 , 3478 , 8 , 12 ), // #35 - INST(Blendvpd , ExtRm_XMM0 , O(660F38,15,_,_,_,_,_,_ ), 0 , 2 , 0 , 3487 , 15 , 12 ), // #36 - INST(Blendvps , ExtRm_XMM0 , O(660F38,14,_,_,_,_,_,_ ), 0 , 2 , 0 , 3497 , 15 , 12 ), // #37 + INST(Blendpd , ExtRmi , O(660F3A,0D,_,_,_,_,_,_ ), 0 , 8 , 0 , 3483 , 8 , 12 ), // #34 + INST(Blendps , ExtRmi , O(660F3A,0C,_,_,_,_,_,_ ), 0 , 8 , 0 , 3492 , 8 , 12 ), // #35 + INST(Blendvpd , ExtRm_XMM0 , O(660F38,15,_,_,_,_,_,_ ), 0 , 2 , 0 , 3501 , 15 , 12 ), // #36 + INST(Blendvps , ExtRm_XMM0 , O(660F38,14,_,_,_,_,_,_ ), 0 , 2 , 0 , 3511 , 15 , 12 ), // #37 INST(Blsfill , VexVm_Wx , V(XOP_M9,01,2,0,x,_,_,_ ), 0 , 15 , 0 , 73 , 14 , 11 ), // #38 INST(Blsi , VexVm_Wx , V(000F38,F3,3,0,x,_,_,_ ), 0 , 16 , 0 , 81 , 14 , 9 ), // #39 INST(Blsic , VexVm_Wx , V(XOP_M9,01,6,0,x,_,_,_ ), 0 , 12 , 0 , 86 , 14 , 11 ), // #40 @@ -202,61 +180,61 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { INST(Cmovs , X86Rm , O(000F00,48,_,_,x,_,_,_ ), 0 , 4 , 0 , 438 , 22 , 36 ), // #105 INST(Cmovz , X86Rm , O(000F00,44,_,_,x,_,_,_ ), 0 , 4 , 0 , 444 , 22 , 31 ), // #106 INST(Cmp , X86Arith , O(000000,38,7,_,x,_,_,_ ), 0 , 27 , 0 , 450 , 35 , 1 ), // #107 - INST(Cmppd , ExtRmi , O(660F00,C2,_,_,_,_,_,_ ), 0 , 3 , 0 , 3723 , 8 , 4 ), // #108 - INST(Cmpps , ExtRmi , O(000F00,C2,_,_,_,_,_,_ ), 0 , 4 , 0 , 3730 , 8 , 5 ), // #109 + INST(Cmppd , ExtRmi , O(660F00,C2,_,_,_,_,_,_ ), 0 , 3 , 0 , 3737 , 8 , 4 ), // #108 + INST(Cmpps , ExtRmi , O(000F00,C2,_,_,_,_,_,_ ), 0 , 4 , 0 , 3751 , 8 , 5 ), // #109 INST(Cmps , X86StrMm , O(000000,A6,_,_,_,_,_,_ ), 0 , 0 , 0 , 454 , 36 , 37 ), // #110 - INST(Cmpsd , ExtRmi , O(F20F00,C2,_,_,_,_,_,_ ), 0 , 5 , 0 , 3737 , 37 , 4 ), // #111 - INST(Cmpss , ExtRmi , O(F30F00,C2,_,_,_,_,_,_ ), 0 , 6 , 0 , 3744 , 38 , 5 ), // #112 + INST(Cmpsd , ExtRmi , O(F20F00,C2,_,_,_,_,_,_ ), 0 , 5 , 0 , 3758 , 37 , 4 ), // #111 + INST(Cmpss , ExtRmi , O(F30F00,C2,_,_,_,_,_,_ ), 0 , 6 , 0 , 3772 , 38 , 5 ), // #112 INST(Cmpxchg , X86Cmpxchg , O(000F00,B0,_,_,x,_,_,_ ), 0 , 4 , 0 , 459 , 39 , 38 ), // #113 INST(Cmpxchg16b , X86Cmpxchg8b_16b , O(000F00,C7,1,_,1,_,_,_ ), 0 , 28 , 0 , 467 , 40 , 39 ), // #114 INST(Cmpxchg8b , X86Cmpxchg8b_16b , O(000F00,C7,1,_,_,_,_,_ ), 0 , 29 , 0 , 478 , 41 , 40 ), // #115 - INST(Comisd , ExtRm , O(660F00,2F,_,_,_,_,_,_ ), 0 , 3 , 0 , 10290, 6 , 41 ), // #116 - INST(Comiss , ExtRm , O(000F00,2F,_,_,_,_,_,_ ), 0 , 4 , 0 , 10299, 7 , 42 ), // #117 + INST(Comisd , ExtRm , O(660F00,2F,_,_,_,_,_,_ ), 0 , 3 , 0 , 11391, 6 , 41 ), // #116 + INST(Comiss , ExtRm , O(000F00,2F,_,_,_,_,_,_ ), 0 , 4 , 0 , 11409, 7 , 42 ), // #117 INST(Cpuid , X86Op , O(000F00,A2,_,_,_,_,_,_ ), 0 , 4 , 0 , 488 , 42 , 43 ), // #118 INST(Cqo , X86Op_xDX_xAX , O(000000,99,_,_,1,_,_,_ ), 0 , 20 , 0 , 494 , 43 , 0 ), // #119 INST(Crc32 , X86Crc , O(F20F38,F0,_,_,x,_,_,_ ), 0 , 30 , 0 , 498 , 44 , 44 ), // #120 - INST(Cvtdq2pd , ExtRm , O(F30F00,E6,_,_,_,_,_,_ ), 0 , 6 , 0 , 3791 , 6 , 4 ), // #121 - INST(Cvtdq2ps , ExtRm , O(000F00,5B,_,_,_,_,_,_ ), 0 , 4 , 0 , 3801 , 5 , 4 ), // #122 - INST(Cvtpd2dq , ExtRm , O(F20F00,E6,_,_,_,_,_,_ ), 0 , 5 , 0 , 3840 , 5 , 4 ), // #123 + INST(Cvtdq2pd , ExtRm , O(F30F00,E6,_,_,_,_,_,_ ), 0 , 6 , 0 , 3827 , 6 , 4 ), // #121 + INST(Cvtdq2ps , ExtRm , O(000F00,5B,_,_,_,_,_,_ ), 0 , 4 , 0 , 3847 , 5 , 4 ), // #122 + INST(Cvtpd2dq , ExtRm , O(F20F00,E6,_,_,_,_,_,_ ), 0 , 5 , 0 , 3886 , 5 , 4 ), // #123 INST(Cvtpd2pi , ExtRm , O(660F00,2D,_,_,_,_,_,_ ), 0 , 3 , 0 , 504 , 45 , 4 ), // #124 - INST(Cvtpd2ps , ExtRm , O(660F00,5A,_,_,_,_,_,_ ), 0 , 3 , 0 , 3850 , 5 , 4 ), // #125 + INST(Cvtpd2ps , ExtRm , O(660F00,5A,_,_,_,_,_,_ ), 0 , 3 , 0 , 3906 , 5 , 4 ), // #125 INST(Cvtpi2pd , ExtRm , O(660F00,2A,_,_,_,_,_,_ ), 0 , 3 , 0 , 513 , 46 , 4 ), // #126 INST(Cvtpi2ps , ExtRm , O(000F00,2A,_,_,_,_,_,_ ), 0 , 4 , 0 , 522 , 46 , 5 ), // #127 - INST(Cvtps2dq , ExtRm , O(660F00,5B,_,_,_,_,_,_ ), 0 , 3 , 0 , 3902 , 5 , 4 ), // #128 - INST(Cvtps2pd , ExtRm , O(000F00,5A,_,_,_,_,_,_ ), 0 , 4 , 0 , 3912 , 6 , 4 ), // #129 + INST(Cvtps2dq , ExtRm , O(660F00,5B,_,_,_,_,_,_ ), 0 , 3 , 0 , 4040 , 5 , 4 ), // #128 + INST(Cvtps2pd , ExtRm , O(000F00,5A,_,_,_,_,_,_ ), 0 , 4 , 0 , 4050 , 6 , 4 ), // #129 INST(Cvtps2pi , ExtRm , O(000F00,2D,_,_,_,_,_,_ ), 0 , 4 , 0 , 531 , 47 , 5 ), // #130 - INST(Cvtsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2D,_,_,x,_,_,_ ), 0 , 5 , 0 , 3984 , 48 , 4 ), // #131 - INST(Cvtsd2ss , ExtRm , O(F20F00,5A,_,_,_,_,_,_ ), 0 , 5 , 0 , 3994 , 6 , 4 ), // #132 - INST(Cvtsi2sd , ExtRm_Wx , O(F20F00,2A,_,_,x,_,_,_ ), 0 , 5 , 0 , 4015 , 49 , 4 ), // #133 - INST(Cvtsi2ss , ExtRm_Wx , O(F30F00,2A,_,_,x,_,_,_ ), 0 , 6 , 0 , 4025 , 49 , 5 ), // #134 - INST(Cvtss2sd , ExtRm , O(F30F00,5A,_,_,_,_,_,_ ), 0 , 6 , 0 , 4035 , 7 , 4 ), // #135 - INST(Cvtss2si , ExtRm_Wx_GpqOnly , O(F30F00,2D,_,_,x,_,_,_ ), 0 , 6 , 0 , 4045 , 50 , 5 ), // #136 - INST(Cvttpd2dq , ExtRm , O(660F00,E6,_,_,_,_,_,_ ), 0 , 3 , 0 , 4066 , 5 , 4 ), // #137 + INST(Cvtsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2D,_,_,x,_,_,_ ), 0 , 5 , 0 , 4153 , 48 , 4 ), // #131 + INST(Cvtsd2ss , ExtRm , O(F20F00,5A,_,_,_,_,_,_ ), 0 , 5 , 0 , 4163 , 6 , 4 ), // #132 + INST(Cvtsi2sd , ExtRm_Wx , O(F20F00,2A,_,_,x,_,_,_ ), 0 , 5 , 0 , 4225 , 49 , 4 ), // #133 + INST(Cvtsi2ss , ExtRm_Wx , O(F30F00,2A,_,_,x,_,_,_ ), 0 , 6 , 0 , 4245 , 49 , 5 ), // #134 + INST(Cvtss2sd , ExtRm , O(F30F00,5A,_,_,_,_,_,_ ), 0 , 6 , 0 , 4255 , 7 , 4 ), // #135 + INST(Cvtss2si , ExtRm_Wx_GpqOnly , O(F30F00,2D,_,_,x,_,_,_ ), 0 , 6 , 0 , 4275 , 50 , 5 ), // #136 + INST(Cvttpd2dq , ExtRm , O(660F00,E6,_,_,_,_,_,_ ), 0 , 3 , 0 , 4296 , 5 , 4 ), // #137 INST(Cvttpd2pi , ExtRm , O(660F00,2C,_,_,_,_,_,_ ), 0 , 3 , 0 , 540 , 45 , 4 ), // #138 - INST(Cvttps2dq , ExtRm , O(F30F00,5B,_,_,_,_,_,_ ), 0 , 6 , 0 , 4112 , 5 , 4 ), // #139 + INST(Cvttps2dq , ExtRm , O(F30F00,5B,_,_,_,_,_,_ ), 0 , 6 , 0 , 4409 , 5 , 4 ), // #139 INST(Cvttps2pi , ExtRm , O(000F00,2C,_,_,_,_,_,_ ), 0 , 4 , 0 , 550 , 47 , 5 ), // #140 - INST(Cvttsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2C,_,_,x,_,_,_ ), 0 , 5 , 0 , 4158 , 48 , 4 ), // #141 - INST(Cvttss2si , ExtRm_Wx_GpqOnly , O(F30F00,2C,_,_,x,_,_,_ ), 0 , 6 , 0 , 4181 , 50 , 5 ), // #142 + INST(Cvttsd2si , ExtRm_Wx_GpqOnly , O(F20F00,2C,_,_,x,_,_,_ ), 0 , 5 , 0 , 4455 , 48 , 4 ), // #141 + INST(Cvttss2si , ExtRm_Wx_GpqOnly , O(F30F00,2C,_,_,x,_,_,_ ), 0 , 6 , 0 , 4501 , 50 , 5 ), // #142 INST(Cwd , X86Op_xDX_xAX , O(660000,99,_,_,_,_,_,_ ), 0 , 19 , 0 , 560 , 51 , 0 ), // #143 INST(Cwde , X86Op_xAX , O(000000,98,_,_,_,_,_,_ ), 0 , 0 , 0 , 564 , 52 , 0 ), // #144 INST(Daa , X86Op , O(000000,27,_,_,_,_,_,_ ), 0 , 0 , 0 , 569 , 1 , 1 ), // #145 INST(Das , X86Op , O(000000,2F,_,_,_,_,_,_ ), 0 , 0 , 0 , 573 , 1 , 1 ), // #146 - INST(Dec , X86IncDec , O(000000,FE,1,_,x,_,_,_ ), O(000000,48,_,_,x,_,_,_ ), 31 , 6 , 3341 , 53 , 45 ), // #147 + INST(Dec , X86IncDec , O(000000,FE,1,_,x,_,_,_ ), O(000000,48,_,_,x,_,_,_ ), 31 , 6 , 3355 , 53 , 45 ), // #147 INST(Div , X86M_GPB_MulDiv , O(000000,F6,6,_,x,_,_,_ ), 0 , 32 , 0 , 810 , 54 , 1 ), // #148 - INST(Divpd , ExtRm , O(660F00,5E,_,_,_,_,_,_ ), 0 , 3 , 0 , 4280 , 5 , 4 ), // #149 - INST(Divps , ExtRm , O(000F00,5E,_,_,_,_,_,_ ), 0 , 4 , 0 , 4287 , 5 , 5 ), // #150 - INST(Divsd , ExtRm , O(F20F00,5E,_,_,_,_,_,_ ), 0 , 5 , 0 , 4294 , 6 , 4 ), // #151 - INST(Divss , ExtRm , O(F30F00,5E,_,_,_,_,_,_ ), 0 , 6 , 0 , 4301 , 7 , 5 ), // #152 - INST(Dppd , ExtRmi , O(660F3A,41,_,_,_,_,_,_ ), 0 , 8 , 0 , 4318 , 8 , 12 ), // #153 - INST(Dpps , ExtRmi , O(660F3A,40,_,_,_,_,_,_ ), 0 , 8 , 0 , 4324 , 8 , 12 ), // #154 + INST(Divpd , ExtRm , O(660F00,5E,_,_,_,_,_,_ ), 0 , 3 , 0 , 4652 , 5 , 4 ), // #149 + INST(Divps , ExtRm , O(000F00,5E,_,_,_,_,_,_ ), 0 , 4 , 0 , 4666 , 5 , 5 ), // #150 + INST(Divsd , ExtRm , O(F20F00,5E,_,_,_,_,_,_ ), 0 , 5 , 0 , 4673 , 6 , 4 ), // #151 + INST(Divss , ExtRm , O(F30F00,5E,_,_,_,_,_,_ ), 0 , 6 , 0 , 4687 , 7 , 5 ), // #152 + INST(Dppd , ExtRmi , O(660F3A,41,_,_,_,_,_,_ ), 0 , 8 , 0 , 4704 , 8 , 12 ), // #153 + INST(Dpps , ExtRmi , O(660F3A,40,_,_,_,_,_,_ ), 0 , 8 , 0 , 4710 , 8 , 12 ), // #154 INST(Emms , X86Op , O(000F00,77,_,_,_,_,_,_ ), 0 , 4 , 0 , 778 , 55 , 46 ), // #155 INST(Endbr32 , X86Op_Mod11RM , O(F30F00,1E,7,_,_,_,_,3 ), 0 , 33 , 0 , 577 , 30 , 47 ), // #156 INST(Endbr64 , X86Op_Mod11RM , O(F30F00,1E,7,_,_,_,_,2 ), 0 , 34 , 0 , 585 , 30 , 47 ), // #157 INST(Enqcmd , X86EnqcmdMovdir64b , O(F20F38,F8,_,_,_,_,_,_ ), 0 , 30 , 0 , 593 , 56 , 48 ), // #158 INST(Enqcmds , X86EnqcmdMovdir64b , O(F30F38,F8,_,_,_,_,_,_ ), 0 , 7 , 0 , 600 , 56 , 48 ), // #159 INST(Enter , X86Enter , O(000000,C8,_,_,_,_,_,_ ), 0 , 0 , 0 , 3046 , 57 , 0 ), // #160 - INST(Extractps , ExtExtract , O(660F3A,17,_,_,_,_,_,_ ), 0 , 8 , 0 , 4514 , 58 , 12 ), // #161 - INST(Extrq , ExtExtrq , O(660F00,79,_,_,_,_,_,_ ), O(660F00,78,0,_,_,_,_,_ ), 3 , 7 , 7650 , 59 , 49 ), // #162 + INST(Extractps , ExtExtract , O(660F3A,17,_,_,_,_,_,_ ), 0 , 8 , 0 , 4900 , 58 , 12 ), // #161 + INST(Extrq , ExtExtrq , O(660F00,79,_,_,_,_,_,_ ), O(660F00,78,0,_,_,_,_,_ ), 3 , 7 , 8625 , 59 , 49 ), // #162 INST(F2xm1 , FpuOp , O_FPU(00,D9F0,_) , 0 , 35 , 0 , 608 , 30 , 0 ), // #163 INST(Fabs , FpuOp , O_FPU(00,D9E1,_) , 0 , 35 , 0 , 614 , 30 , 0 ), // #164 INST(Fadd , FpuArith , O_FPU(00,C0C0,0) , 0 , 36 , 0 , 2121 , 60 , 0 ), // #165 @@ -345,39 +323,39 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { INST(Fucomip , FpuR , O_FPU(00,DFE8,_) , 0 , 44 , 0 , 1124 , 63 , 50 ), // #248 INST(Fucomp , FpuRDef , O_FPU(00,DDE8,_) , 0 , 48 , 0 , 1132 , 61 , 0 ), // #249 INST(Fucompp , FpuOp , O_FPU(00,DAE9,_) , 0 , 41 , 0 , 1139 , 30 , 0 ), // #250 - INST(Fwait , X86Op , O_FPU(00,009B,_) , 0 , 60 , 0 , 1147 , 30 , 0 ), // #251 + INST(Fwait , X86Op , O_FPU(00,009B,_) , 0 , 49 , 0 , 1147 , 30 , 0 ), // #251 INST(Fxam , FpuOp , O_FPU(00,D9E5,_) , 0 , 35 , 0 , 1153 , 30 , 0 ), // #252 INST(Fxch , FpuR , O_FPU(00,D9C8,_) , 0 , 35 , 0 , 1158 , 61 , 0 ), // #253 INST(Fxrstor , X86M_Only , O(000F00,AE,1,_,_,_,_,_ ), 0 , 29 , 0 , 1163 , 69 , 52 ), // #254 INST(Fxrstor64 , X86M_Only , O(000F00,AE,1,_,1,_,_,_ ), 0 , 28 , 0 , 1171 , 72 , 52 ), // #255 INST(Fxsave , X86M_Only , O(000F00,AE,0,_,_,_,_,_ ), 0 , 4 , 0 , 1181 , 69 , 52 ), // #256 - INST(Fxsave64 , X86M_Only , O(000F00,AE,0,_,1,_,_,_ ), 0 , 61 , 0 , 1188 , 72 , 52 ), // #257 + INST(Fxsave64 , X86M_Only , O(000F00,AE,0,_,1,_,_,_ ), 0 , 60 , 0 , 1188 , 72 , 52 ), // #257 INST(Fxtract , FpuOp , O_FPU(00,D9F4,_) , 0 , 35 , 0 , 1197 , 30 , 0 ), // #258 INST(Fyl2x , FpuOp , O_FPU(00,D9F1,_) , 0 , 35 , 0 , 1205 , 30 , 0 ), // #259 INST(Fyl2xp1 , FpuOp , O_FPU(00,D9F9,_) , 0 , 35 , 0 , 1211 , 30 , 0 ), // #260 INST(Getsec , X86Op , O(000F00,37,_,_,_,_,_,_ ), 0 , 4 , 0 , 1219 , 30 , 53 ), // #261 - INST(Gf2p8affineinvqb , ExtRmi , O(660F3A,CF,_,_,_,_,_,_ ), 0 , 8 , 0 , 5869 , 8 , 54 ), // #262 - INST(Gf2p8affineqb , ExtRmi , O(660F3A,CE,_,_,_,_,_,_ ), 0 , 8 , 0 , 5887 , 8 , 54 ), // #263 - INST(Gf2p8mulb , ExtRm , O(660F38,CF,_,_,_,_,_,_ ), 0 , 2 , 0 , 5902 , 5 , 54 ), // #264 - INST(Haddpd , ExtRm , O(660F00,7C,_,_,_,_,_,_ ), 0 , 3 , 0 , 5913 , 5 , 6 ), // #265 - INST(Haddps , ExtRm , O(F20F00,7C,_,_,_,_,_,_ ), 0 , 5 , 0 , 5921 , 5 , 6 ), // #266 + INST(Gf2p8affineinvqb , ExtRmi , O(660F3A,CF,_,_,_,_,_,_ ), 0 , 8 , 0 , 6789 , 8 , 54 ), // #262 + INST(Gf2p8affineqb , ExtRmi , O(660F3A,CE,_,_,_,_,_,_ ), 0 , 8 , 0 , 6807 , 8 , 54 ), // #263 + INST(Gf2p8mulb , ExtRm , O(660F38,CF,_,_,_,_,_,_ ), 0 , 2 , 0 , 6822 , 5 , 54 ), // #264 + INST(Haddpd , ExtRm , O(660F00,7C,_,_,_,_,_,_ ), 0 , 3 , 0 , 6833 , 5 , 6 ), // #265 + INST(Haddps , ExtRm , O(F20F00,7C,_,_,_,_,_,_ ), 0 , 5 , 0 , 6841 , 5 , 6 ), // #266 INST(Hlt , X86Op , O(000000,F4,_,_,_,_,_,_ ), 0 , 0 , 0 , 1226 , 30 , 0 ), // #267 - INST(Hreset , X86Op_Mod11RM_I8 , O(F30F3A,F0,0,_,_,_,_,_ ), 0 , 62 , 0 , 1230 , 73 , 55 ), // #268 - INST(Hsubpd , ExtRm , O(660F00,7D,_,_,_,_,_,_ ), 0 , 3 , 0 , 5929 , 5 , 6 ), // #269 - INST(Hsubps , ExtRm , O(F20F00,7D,_,_,_,_,_,_ ), 0 , 5 , 0 , 5937 , 5 , 6 ), // #270 + INST(Hreset , X86Op_Mod11RM_I8 , O(F30F3A,F0,0,_,_,_,_,_ ), 0 , 61 , 0 , 1230 , 73 , 55 ), // #268 + INST(Hsubpd , ExtRm , O(660F00,7D,_,_,_,_,_,_ ), 0 , 3 , 0 , 6849 , 5 , 6 ), // #269 + INST(Hsubps , ExtRm , O(F20F00,7D,_,_,_,_,_,_ ), 0 , 5 , 0 , 6857 , 5 , 6 ), // #270 INST(Idiv , X86M_GPB_MulDiv , O(000000,F6,7,_,x,_,_,_ ), 0 , 27 , 0 , 809 , 54 , 1 ), // #271 - INST(Imul , X86Imul , O(000000,F6,5,_,x,_,_,_ ), 0 , 63 , 0 , 827 , 74 , 1 ), // #272 - INST(In , X86In , O(000000,EC,_,_,_,_,_,_ ), O(000000,E4,_,_,_,_,_,_ ), 0 , 15 , 10462, 75 , 0 ), // #273 + INST(Imul , X86Imul , O(000000,F6,5,_,x,_,_,_ ), 0 , 62 , 0 , 827 , 74 , 1 ), // #272 + INST(In , X86In , O(000000,EC,_,_,_,_,_,_ ), O(000000,E4,_,_,_,_,_,_ ), 0 , 15 , 11572, 75 , 0 ), // #273 INST(Inc , X86IncDec , O(000000,FE,0,_,x,_,_,_ ), O(000000,40,_,_,x,_,_,_ ), 0 , 16 , 1237 , 53 , 45 ), // #274 - INST(Incsspd , X86M , O(F30F00,AE,5,_,0,_,_,_ ), 0 , 64 , 0 , 1241 , 76 , 56 ), // #275 - INST(Incsspq , X86M , O(F30F00,AE,5,_,1,_,_,_ ), 0 , 65 , 0 , 1249 , 77 , 56 ), // #276 + INST(Incsspd , X86M , O(F30F00,AE,5,_,0,_,_,_ ), 0 , 63 , 0 , 1241 , 76 , 56 ), // #275 + INST(Incsspq , X86M , O(F30F00,AE,5,_,1,_,_,_ ), 0 , 64 , 0 , 1249 , 77 , 56 ), // #276 INST(Ins , X86Ins , O(000000,6C,_,_,_,_,_,_ ), 0 , 0 , 0 , 1916 , 78 , 0 ), // #277 - INST(Insertps , ExtRmi , O(660F3A,21,_,_,_,_,_,_ ), 0 , 8 , 0 , 6073 , 38 , 12 ), // #278 + INST(Insertps , ExtRmi , O(660F3A,21,_,_,_,_,_,_ ), 0 , 8 , 0 , 6993 , 38 , 12 ), // #278 INST(Insertq , ExtInsertq , O(F20F00,79,_,_,_,_,_,_ ), O(F20F00,78,_,_,_,_,_,_ ), 5 , 17 , 1257 , 79 , 49 ), // #279 INST(Int , X86Int , O(000000,CD,_,_,_,_,_,_ ), 0 , 0 , 0 , 1022 , 80 , 0 ), // #280 INST(Int3 , X86Op , O(000000,CC,_,_,_,_,_,_ ), 0 , 0 , 0 , 1265 , 30 , 0 ), // #281 INST(Into , X86Op , O(000000,CE,_,_,_,_,_,_ ), 0 , 0 , 0 , 1270 , 81 , 57 ), // #282 - INST(Invd , X86Op , O(000F00,08,_,_,_,_,_,_ ), 0 , 4 , 0 , 10391, 30 , 43 ), // #283 + INST(Invd , X86Op , O(000F00,08,_,_,_,_,_,_ ), 0 , 4 , 0 , 11501, 30 , 43 ), // #283 INST(Invept , X86Rm_NoSize , O(660F38,80,_,_,_,_,_,_ ), 0 , 2 , 0 , 1275 , 82 , 58 ), // #284 INST(Invlpg , X86M_Only , O(000F00,01,7,_,_,_,_,_ ), 0 , 22 , 0 , 1282 , 69 , 43 ), // #285 INST(Invlpga , X86Op_xAddr , O(000F01,DF,_,_,_,_,_,_ ), 0 , 21 , 0 , 1289 , 83 , 22 ), // #286 @@ -418,370 +396,370 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { INST(Jpo , X86Jcc , O(000F00,8B,_,_,_,_,_,_ ), O(000000,7B,_,_,_,_,_,_ ), 4 , 31 , 1435 , 86 , 64 ), // #321 INST(Js , X86Jcc , O(000F00,88,_,_,_,_,_,_ ), O(000000,78,_,_,_,_,_,_ ), 4 , 35 , 1439 , 86 , 65 ), // #322 INST(Jz , X86Jcc , O(000F00,84,_,_,_,_,_,_ ), O(000000,74,_,_,_,_,_,_ ), 4 , 22 , 1442 , 86 , 61 ), // #323 - INST(Kaddb , VexRvm , V(660F00,4A,_,1,0,_,_,_ ), 0 , 66 , 0 , 1445 , 89 , 66 ), // #324 - INST(Kaddd , VexRvm , V(660F00,4A,_,1,1,_,_,_ ), 0 , 67 , 0 , 1451 , 89 , 67 ), // #325 - INST(Kaddq , VexRvm , V(000F00,4A,_,1,1,_,_,_ ), 0 , 68 , 0 , 1457 , 89 , 67 ), // #326 - INST(Kaddw , VexRvm , V(000F00,4A,_,1,0,_,_,_ ), 0 , 69 , 0 , 1463 , 89 , 66 ), // #327 - INST(Kandb , VexRvm , V(660F00,41,_,1,0,_,_,_ ), 0 , 66 , 0 , 1469 , 89 , 66 ), // #328 - INST(Kandd , VexRvm , V(660F00,41,_,1,1,_,_,_ ), 0 , 67 , 0 , 1475 , 89 , 67 ), // #329 - INST(Kandnb , VexRvm , V(660F00,42,_,1,0,_,_,_ ), 0 , 66 , 0 , 1481 , 89 , 66 ), // #330 - INST(Kandnd , VexRvm , V(660F00,42,_,1,1,_,_,_ ), 0 , 67 , 0 , 1488 , 89 , 67 ), // #331 - INST(Kandnq , VexRvm , V(000F00,42,_,1,1,_,_,_ ), 0 , 68 , 0 , 1495 , 89 , 67 ), // #332 - INST(Kandnw , VexRvm , V(000F00,42,_,1,0,_,_,_ ), 0 , 69 , 0 , 1502 , 89 , 68 ), // #333 - INST(Kandq , VexRvm , V(000F00,41,_,1,1,_,_,_ ), 0 , 68 , 0 , 1509 , 89 , 67 ), // #334 - INST(Kandw , VexRvm , V(000F00,41,_,1,0,_,_,_ ), 0 , 69 , 0 , 1515 , 89 , 68 ), // #335 - INST(Kmovb , VexKmov , V(660F00,90,_,0,0,_,_,_ ), V(660F00,92,_,0,0,_,_,_ ), 70 , 36 , 1521 , 90 , 66 ), // #336 - INST(Kmovd , VexKmov , V(660F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,0,_,_,_ ), 71 , 37 , 8130 , 91 , 67 ), // #337 - INST(Kmovq , VexKmov , V(000F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,1,_,_,_ ), 72 , 38 , 8141 , 92 , 67 ), // #338 - INST(Kmovw , VexKmov , V(000F00,90,_,0,0,_,_,_ ), V(000F00,92,_,0,0,_,_,_ ), 73 , 39 , 1527 , 93 , 68 ), // #339 - INST(Knotb , VexRm , V(660F00,44,_,0,0,_,_,_ ), 0 , 70 , 0 , 1533 , 94 , 66 ), // #340 - INST(Knotd , VexRm , V(660F00,44,_,0,1,_,_,_ ), 0 , 71 , 0 , 1539 , 94 , 67 ), // #341 - INST(Knotq , VexRm , V(000F00,44,_,0,1,_,_,_ ), 0 , 72 , 0 , 1545 , 94 , 67 ), // #342 - INST(Knotw , VexRm , V(000F00,44,_,0,0,_,_,_ ), 0 , 73 , 0 , 1551 , 94 , 68 ), // #343 - INST(Korb , VexRvm , V(660F00,45,_,1,0,_,_,_ ), 0 , 66 , 0 , 1557 , 89 , 66 ), // #344 - INST(Kord , VexRvm , V(660F00,45,_,1,1,_,_,_ ), 0 , 67 , 0 , 1562 , 89 , 67 ), // #345 - INST(Korq , VexRvm , V(000F00,45,_,1,1,_,_,_ ), 0 , 68 , 0 , 1567 , 89 , 67 ), // #346 - INST(Kortestb , VexRm , V(660F00,98,_,0,0,_,_,_ ), 0 , 70 , 0 , 1572 , 94 , 69 ), // #347 - INST(Kortestd , VexRm , V(660F00,98,_,0,1,_,_,_ ), 0 , 71 , 0 , 1581 , 94 , 70 ), // #348 - INST(Kortestq , VexRm , V(000F00,98,_,0,1,_,_,_ ), 0 , 72 , 0 , 1590 , 94 , 70 ), // #349 - INST(Kortestw , VexRm , V(000F00,98,_,0,0,_,_,_ ), 0 , 73 , 0 , 1599 , 94 , 71 ), // #350 - INST(Korw , VexRvm , V(000F00,45,_,1,0,_,_,_ ), 0 , 69 , 0 , 1608 , 89 , 68 ), // #351 - INST(Kshiftlb , VexRmi , V(660F3A,32,_,0,0,_,_,_ ), 0 , 74 , 0 , 1613 , 95 , 66 ), // #352 - INST(Kshiftld , VexRmi , V(660F3A,33,_,0,0,_,_,_ ), 0 , 74 , 0 , 1622 , 95 , 67 ), // #353 - INST(Kshiftlq , VexRmi , V(660F3A,33,_,0,1,_,_,_ ), 0 , 75 , 0 , 1631 , 95 , 67 ), // #354 - INST(Kshiftlw , VexRmi , V(660F3A,32,_,0,1,_,_,_ ), 0 , 75 , 0 , 1640 , 95 , 68 ), // #355 - INST(Kshiftrb , VexRmi , V(660F3A,30,_,0,0,_,_,_ ), 0 , 74 , 0 , 1649 , 95 , 66 ), // #356 - INST(Kshiftrd , VexRmi , V(660F3A,31,_,0,0,_,_,_ ), 0 , 74 , 0 , 1658 , 95 , 67 ), // #357 - INST(Kshiftrq , VexRmi , V(660F3A,31,_,0,1,_,_,_ ), 0 , 75 , 0 , 1667 , 95 , 67 ), // #358 - INST(Kshiftrw , VexRmi , V(660F3A,30,_,0,1,_,_,_ ), 0 , 75 , 0 , 1676 , 95 , 68 ), // #359 - INST(Ktestb , VexRm , V(660F00,99,_,0,0,_,_,_ ), 0 , 70 , 0 , 1685 , 94 , 69 ), // #360 - INST(Ktestd , VexRm , V(660F00,99,_,0,1,_,_,_ ), 0 , 71 , 0 , 1692 , 94 , 70 ), // #361 - INST(Ktestq , VexRm , V(000F00,99,_,0,1,_,_,_ ), 0 , 72 , 0 , 1699 , 94 , 70 ), // #362 - INST(Ktestw , VexRm , V(000F00,99,_,0,0,_,_,_ ), 0 , 73 , 0 , 1706 , 94 , 69 ), // #363 - INST(Kunpckbw , VexRvm , V(660F00,4B,_,1,0,_,_,_ ), 0 , 66 , 0 , 1713 , 89 , 68 ), // #364 - INST(Kunpckdq , VexRvm , V(000F00,4B,_,1,1,_,_,_ ), 0 , 68 , 0 , 1722 , 89 , 67 ), // #365 - INST(Kunpckwd , VexRvm , V(000F00,4B,_,1,0,_,_,_ ), 0 , 69 , 0 , 1731 , 89 , 67 ), // #366 - INST(Kxnorb , VexRvm , V(660F00,46,_,1,0,_,_,_ ), 0 , 66 , 0 , 1740 , 96 , 66 ), // #367 - INST(Kxnord , VexRvm , V(660F00,46,_,1,1,_,_,_ ), 0 , 67 , 0 , 1747 , 96 , 67 ), // #368 - INST(Kxnorq , VexRvm , V(000F00,46,_,1,1,_,_,_ ), 0 , 68 , 0 , 1754 , 96 , 67 ), // #369 - INST(Kxnorw , VexRvm , V(000F00,46,_,1,0,_,_,_ ), 0 , 69 , 0 , 1761 , 96 , 68 ), // #370 - INST(Kxorb , VexRvm , V(660F00,47,_,1,0,_,_,_ ), 0 , 66 , 0 , 1768 , 96 , 66 ), // #371 - INST(Kxord , VexRvm , V(660F00,47,_,1,1,_,_,_ ), 0 , 67 , 0 , 1774 , 96 , 67 ), // #372 - INST(Kxorq , VexRvm , V(000F00,47,_,1,1,_,_,_ ), 0 , 68 , 0 , 1780 , 96 , 67 ), // #373 - INST(Kxorw , VexRvm , V(000F00,47,_,1,0,_,_,_ ), 0 , 69 , 0 , 1786 , 96 , 68 ), // #374 + INST(Kaddb , VexRvm , V(660F00,4A,_,1,0,_,_,_ ), 0 , 65 , 0 , 1445 , 89 , 66 ), // #324 + INST(Kaddd , VexRvm , V(660F00,4A,_,1,1,_,_,_ ), 0 , 66 , 0 , 1451 , 89 , 67 ), // #325 + INST(Kaddq , VexRvm , V(000F00,4A,_,1,1,_,_,_ ), 0 , 67 , 0 , 1457 , 89 , 67 ), // #326 + INST(Kaddw , VexRvm , V(000F00,4A,_,1,0,_,_,_ ), 0 , 68 , 0 , 1463 , 89 , 66 ), // #327 + INST(Kandb , VexRvm , V(660F00,41,_,1,0,_,_,_ ), 0 , 65 , 0 , 1469 , 89 , 66 ), // #328 + INST(Kandd , VexRvm , V(660F00,41,_,1,1,_,_,_ ), 0 , 66 , 0 , 1475 , 89 , 67 ), // #329 + INST(Kandnb , VexRvm , V(660F00,42,_,1,0,_,_,_ ), 0 , 65 , 0 , 1481 , 89 , 66 ), // #330 + INST(Kandnd , VexRvm , V(660F00,42,_,1,1,_,_,_ ), 0 , 66 , 0 , 1488 , 89 , 67 ), // #331 + INST(Kandnq , VexRvm , V(000F00,42,_,1,1,_,_,_ ), 0 , 67 , 0 , 1495 , 89 , 67 ), // #332 + INST(Kandnw , VexRvm , V(000F00,42,_,1,0,_,_,_ ), 0 , 68 , 0 , 1502 , 89 , 68 ), // #333 + INST(Kandq , VexRvm , V(000F00,41,_,1,1,_,_,_ ), 0 , 67 , 0 , 1509 , 89 , 67 ), // #334 + INST(Kandw , VexRvm , V(000F00,41,_,1,0,_,_,_ ), 0 , 68 , 0 , 1515 , 89 , 68 ), // #335 + INST(Kmovb , VexKmov , V(660F00,90,_,0,0,_,_,_ ), V(660F00,92,_,0,0,_,_,_ ), 69 , 36 , 1521 , 90 , 66 ), // #336 + INST(Kmovd , VexKmov , V(660F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,0,_,_,_ ), 70 , 37 , 9105 , 91 , 67 ), // #337 + INST(Kmovq , VexKmov , V(000F00,90,_,0,1,_,_,_ ), V(F20F00,92,_,0,1,_,_,_ ), 71 , 38 , 9116 , 92 , 67 ), // #338 + INST(Kmovw , VexKmov , V(000F00,90,_,0,0,_,_,_ ), V(000F00,92,_,0,0,_,_,_ ), 72 , 39 , 1527 , 93 , 68 ), // #339 + INST(Knotb , VexRm , V(660F00,44,_,0,0,_,_,_ ), 0 , 69 , 0 , 1533 , 94 , 66 ), // #340 + INST(Knotd , VexRm , V(660F00,44,_,0,1,_,_,_ ), 0 , 70 , 0 , 1539 , 94 , 67 ), // #341 + INST(Knotq , VexRm , V(000F00,44,_,0,1,_,_,_ ), 0 , 71 , 0 , 1545 , 94 , 67 ), // #342 + INST(Knotw , VexRm , V(000F00,44,_,0,0,_,_,_ ), 0 , 72 , 0 , 1551 , 94 , 68 ), // #343 + INST(Korb , VexRvm , V(660F00,45,_,1,0,_,_,_ ), 0 , 65 , 0 , 1557 , 89 , 66 ), // #344 + INST(Kord , VexRvm , V(660F00,45,_,1,1,_,_,_ ), 0 , 66 , 0 , 1562 , 89 , 67 ), // #345 + INST(Korq , VexRvm , V(000F00,45,_,1,1,_,_,_ ), 0 , 67 , 0 , 1567 , 89 , 67 ), // #346 + INST(Kortestb , VexRm , V(660F00,98,_,0,0,_,_,_ ), 0 , 69 , 0 , 1572 , 94 , 69 ), // #347 + INST(Kortestd , VexRm , V(660F00,98,_,0,1,_,_,_ ), 0 , 70 , 0 , 1581 , 94 , 70 ), // #348 + INST(Kortestq , VexRm , V(000F00,98,_,0,1,_,_,_ ), 0 , 71 , 0 , 1590 , 94 , 70 ), // #349 + INST(Kortestw , VexRm , V(000F00,98,_,0,0,_,_,_ ), 0 , 72 , 0 , 1599 , 94 , 71 ), // #350 + INST(Korw , VexRvm , V(000F00,45,_,1,0,_,_,_ ), 0 , 68 , 0 , 1608 , 89 , 68 ), // #351 + INST(Kshiftlb , VexRmi , V(660F3A,32,_,0,0,_,_,_ ), 0 , 73 , 0 , 1613 , 95 , 66 ), // #352 + INST(Kshiftld , VexRmi , V(660F3A,33,_,0,0,_,_,_ ), 0 , 73 , 0 , 1622 , 95 , 67 ), // #353 + INST(Kshiftlq , VexRmi , V(660F3A,33,_,0,1,_,_,_ ), 0 , 74 , 0 , 1631 , 95 , 67 ), // #354 + INST(Kshiftlw , VexRmi , V(660F3A,32,_,0,1,_,_,_ ), 0 , 74 , 0 , 1640 , 95 , 68 ), // #355 + INST(Kshiftrb , VexRmi , V(660F3A,30,_,0,0,_,_,_ ), 0 , 73 , 0 , 1649 , 95 , 66 ), // #356 + INST(Kshiftrd , VexRmi , V(660F3A,31,_,0,0,_,_,_ ), 0 , 73 , 0 , 1658 , 95 , 67 ), // #357 + INST(Kshiftrq , VexRmi , V(660F3A,31,_,0,1,_,_,_ ), 0 , 74 , 0 , 1667 , 95 , 67 ), // #358 + INST(Kshiftrw , VexRmi , V(660F3A,30,_,0,1,_,_,_ ), 0 , 74 , 0 , 1676 , 95 , 68 ), // #359 + INST(Ktestb , VexRm , V(660F00,99,_,0,0,_,_,_ ), 0 , 69 , 0 , 1685 , 94 , 69 ), // #360 + INST(Ktestd , VexRm , V(660F00,99,_,0,1,_,_,_ ), 0 , 70 , 0 , 1692 , 94 , 70 ), // #361 + INST(Ktestq , VexRm , V(000F00,99,_,0,1,_,_,_ ), 0 , 71 , 0 , 1699 , 94 , 70 ), // #362 + INST(Ktestw , VexRm , V(000F00,99,_,0,0,_,_,_ ), 0 , 72 , 0 , 1706 , 94 , 69 ), // #363 + INST(Kunpckbw , VexRvm , V(660F00,4B,_,1,0,_,_,_ ), 0 , 65 , 0 , 1713 , 89 , 68 ), // #364 + INST(Kunpckdq , VexRvm , V(000F00,4B,_,1,1,_,_,_ ), 0 , 67 , 0 , 1722 , 89 , 67 ), // #365 + INST(Kunpckwd , VexRvm , V(000F00,4B,_,1,0,_,_,_ ), 0 , 68 , 0 , 1731 , 89 , 67 ), // #366 + INST(Kxnorb , VexRvm , V(660F00,46,_,1,0,_,_,_ ), 0 , 65 , 0 , 1740 , 96 , 66 ), // #367 + INST(Kxnord , VexRvm , V(660F00,46,_,1,1,_,_,_ ), 0 , 66 , 0 , 1747 , 96 , 67 ), // #368 + INST(Kxnorq , VexRvm , V(000F00,46,_,1,1,_,_,_ ), 0 , 67 , 0 , 1754 , 96 , 67 ), // #369 + INST(Kxnorw , VexRvm , V(000F00,46,_,1,0,_,_,_ ), 0 , 68 , 0 , 1761 , 96 , 68 ), // #370 + INST(Kxorb , VexRvm , V(660F00,47,_,1,0,_,_,_ ), 0 , 65 , 0 , 1768 , 96 , 66 ), // #371 + INST(Kxord , VexRvm , V(660F00,47,_,1,1,_,_,_ ), 0 , 66 , 0 , 1774 , 96 , 67 ), // #372 + INST(Kxorq , VexRvm , V(000F00,47,_,1,1,_,_,_ ), 0 , 67 , 0 , 1780 , 96 , 67 ), // #373 + INST(Kxorw , VexRvm , V(000F00,47,_,1,0,_,_,_ ), 0 , 68 , 0 , 1786 , 96 , 68 ), // #374 INST(Lahf , X86Op , O(000000,9F,_,_,_,_,_,_ ), 0 , 0 , 0 , 1792 , 97 , 72 ), // #375 INST(Lar , X86Rm , O(000F00,02,_,_,_,_,_,_ ), 0 , 4 , 0 , 1797 , 98 , 10 ), // #376 - INST(Lcall , X86LcallLjmp , O(000000,FF,3,_,_,_,_,_ ), O(000000,9A,_,_,_,_,_,_ ), 76 , 40 , 1801 , 99 , 1 ), // #377 - INST(Lddqu , ExtRm , O(F20F00,F0,_,_,_,_,_,_ ), 0 , 5 , 0 , 6083 , 100, 6 ), // #378 - INST(Ldmxcsr , X86M_Only , O(000F00,AE,2,_,_,_,_,_ ), 0 , 77 , 0 , 6090 , 101, 5 ), // #379 + INST(Lcall , X86LcallLjmp , O(000000,FF,3,_,_,_,_,_ ), O(000000,9A,_,_,_,_,_,_ ), 75 , 40 , 1801 , 99 , 1 ), // #377 + INST(Lddqu , ExtRm , O(F20F00,F0,_,_,_,_,_,_ ), 0 , 5 , 0 , 7003 , 100, 6 ), // #378 + INST(Ldmxcsr , X86M_Only , O(000F00,AE,2,_,_,_,_,_ ), 0 , 76 , 0 , 7010 , 101, 5 ), // #379 INST(Lds , X86Rm , O(000000,C5,_,_,_,_,_,_ ), 0 , 0 , 0 , 1807 , 102, 0 ), // #380 INST(Ldtilecfg , AmxCfg , V(000F38,49,_,0,0,_,_,_ ), 0 , 10 , 0 , 1811 , 103, 73 ), // #381 INST(Lea , X86Lea , O(000000,8D,_,_,x,_,_,_ ), 0 , 0 , 0 , 1821 , 104, 0 ), // #382 INST(Leave , X86Op , O(000000,C9,_,_,_,_,_,_ ), 0 , 0 , 0 , 1825 , 30 , 0 ), // #383 INST(Les , X86Rm , O(000000,C4,_,_,_,_,_,_ ), 0 , 0 , 0 , 1831 , 102, 0 ), // #384 - INST(Lfence , X86Fence , O(000F00,AE,5,_,_,_,_,_ ), 0 , 78 , 0 , 1835 , 30 , 4 ), // #385 + INST(Lfence , X86Fence , O(000F00,AE,5,_,_,_,_,_ ), 0 , 77 , 0 , 1835 , 30 , 4 ), // #385 INST(Lfs , X86Rm , O(000F00,B4,_,_,_,_,_,_ ), 0 , 4 , 0 , 1842 , 105, 0 ), // #386 - INST(Lgdt , X86M_Only , O(000F00,01,2,_,_,_,_,_ ), 0 , 77 , 0 , 1846 , 69 , 0 ), // #387 + INST(Lgdt , X86M_Only , O(000F00,01,2,_,_,_,_,_ ), 0 , 76 , 0 , 1846 , 69 , 0 ), // #387 INST(Lgs , X86Rm , O(000F00,B5,_,_,_,_,_,_ ), 0 , 4 , 0 , 1851 , 105, 0 ), // #388 - INST(Lidt , X86M_Only , O(000F00,01,3,_,_,_,_,_ ), 0 , 79 , 0 , 1855 , 69 , 0 ), // #389 - INST(Ljmp , X86LcallLjmp , O(000000,FF,5,_,_,_,_,_ ), O(000000,EA,_,_,_,_,_,_ ), 63 , 41 , 1860 , 106, 0 ), // #390 - INST(Lldt , X86M_NoSize , O(000F00,00,2,_,_,_,_,_ ), 0 , 77 , 0 , 1865 , 107, 0 ), // #391 - INST(Llwpcb , VexR_Wx , V(XOP_M9,12,0,0,x,_,_,_ ), 0 , 80 , 0 , 1870 , 108, 74 ), // #392 - INST(Lmsw , X86M_NoSize , O(000F00,01,6,_,_,_,_,_ ), 0 , 81 , 0 , 1877 , 107, 0 ), // #393 + INST(Lidt , X86M_Only , O(000F00,01,3,_,_,_,_,_ ), 0 , 78 , 0 , 1855 , 69 , 0 ), // #389 + INST(Ljmp , X86LcallLjmp , O(000000,FF,5,_,_,_,_,_ ), O(000000,EA,_,_,_,_,_,_ ), 62 , 41 , 1860 , 106, 0 ), // #390 + INST(Lldt , X86M_NoSize , O(000F00,00,2,_,_,_,_,_ ), 0 , 76 , 0 , 1865 , 107, 0 ), // #391 + INST(Llwpcb , VexR_Wx , V(XOP_M9,12,0,0,x,_,_,_ ), 0 , 79 , 0 , 1870 , 108, 74 ), // #392 + INST(Lmsw , X86M_NoSize , O(000F00,01,6,_,_,_,_,_ ), 0 , 80 , 0 , 1877 , 107, 0 ), // #393 INST(Lods , X86StrRm , O(000000,AC,_,_,_,_,_,_ ), 0 , 0 , 0 , 1882 , 109, 75 ), // #394 INST(Loop , X86JecxzLoop , 0 , O(000000,E2,_,_,_,_,_,_ ), 0 , 42 , 1887 , 110, 0 ), // #395 INST(Loope , X86JecxzLoop , 0 , O(000000,E1,_,_,_,_,_,_ ), 0 , 43 , 1892 , 110, 61 ), // #396 INST(Loopne , X86JecxzLoop , 0 , O(000000,E0,_,_,_,_,_,_ ), 0 , 44 , 1898 , 110, 61 ), // #397 INST(Lsl , X86Rm , O(000F00,03,_,_,_,_,_,_ ), 0 , 4 , 0 , 1905 , 111, 10 ), // #398 - INST(Lss , X86Rm , O(000F00,B2,_,_,_,_,_,_ ), 0 , 4 , 0 , 6581 , 105, 0 ), // #399 - INST(Ltr , X86M_NoSize , O(000F00,00,3,_,_,_,_,_ ), 0 , 79 , 0 , 1909 , 107, 0 ), // #400 - INST(Lwpins , VexVmi4_Wx , V(XOP_MA,12,0,0,x,_,_,_ ), 0 , 82 , 0 , 1913 , 112, 74 ), // #401 - INST(Lwpval , VexVmi4_Wx , V(XOP_MA,12,1,0,x,_,_,_ ), 0 , 83 , 0 , 1920 , 112, 74 ), // #402 + INST(Lss , X86Rm , O(000F00,B2,_,_,_,_,_,_ ), 0 , 4 , 0 , 7556 , 105, 0 ), // #399 + INST(Ltr , X86M_NoSize , O(000F00,00,3,_,_,_,_,_ ), 0 , 78 , 0 , 1909 , 107, 0 ), // #400 + INST(Lwpins , VexVmi4_Wx , V(XOP_MA,12,0,0,x,_,_,_ ), 0 , 81 , 0 , 1913 , 112, 74 ), // #401 + INST(Lwpval , VexVmi4_Wx , V(XOP_MA,12,1,0,x,_,_,_ ), 0 , 82 , 0 , 1920 , 112, 74 ), // #402 INST(Lzcnt , X86Rm_Raw66H , O(F30F00,BD,_,_,x,_,_,_ ), 0 , 6 , 0 , 1927 , 22 , 76 ), // #403 - INST(Maskmovdqu , ExtRm_ZDI , O(660F00,F7,_,_,_,_,_,_ ), 0 , 3 , 0 , 6099 , 113, 4 ), // #404 - INST(Maskmovq , ExtRm_ZDI , O(000F00,F7,_,_,_,_,_,_ ), 0 , 4 , 0 , 8138 , 114, 77 ), // #405 - INST(Maxpd , ExtRm , O(660F00,5F,_,_,_,_,_,_ ), 0 , 3 , 0 , 6133 , 5 , 4 ), // #406 - INST(Maxps , ExtRm , O(000F00,5F,_,_,_,_,_,_ ), 0 , 4 , 0 , 6140 , 5 , 5 ), // #407 - INST(Maxsd , ExtRm , O(F20F00,5F,_,_,_,_,_,_ ), 0 , 5 , 0 , 8157 , 6 , 4 ), // #408 - INST(Maxss , ExtRm , O(F30F00,5F,_,_,_,_,_,_ ), 0 , 6 , 0 , 6154 , 7 , 5 ), // #409 + INST(Maskmovdqu , ExtRm_ZDI , O(660F00,F7,_,_,_,_,_,_ ), 0 , 3 , 0 , 7019 , 113, 4 ), // #404 + INST(Maskmovq , ExtRm_ZDI , O(000F00,F7,_,_,_,_,_,_ ), 0 , 4 , 0 , 9113 , 114, 77 ), // #405 + INST(Maxpd , ExtRm , O(660F00,5F,_,_,_,_,_,_ ), 0 , 3 , 0 , 7053 , 5 , 4 ), // #406 + INST(Maxps , ExtRm , O(000F00,5F,_,_,_,_,_,_ ), 0 , 4 , 0 , 7067 , 5 , 5 ), // #407 + INST(Maxsd , ExtRm , O(F20F00,5F,_,_,_,_,_,_ ), 0 , 5 , 0 , 9132 , 6 , 4 ), // #408 + INST(Maxss , ExtRm , O(F30F00,5F,_,_,_,_,_,_ ), 0 , 6 , 0 , 7088 , 7 , 5 ), // #409 INST(Mcommit , X86Op , O(F30F01,FA,_,_,_,_,_,_ ), 0 , 25 , 0 , 1933 , 30 , 78 ), // #410 - INST(Mfence , X86Fence , O(000F00,AE,6,_,_,_,_,_ ), 0 , 81 , 0 , 1941 , 30 , 4 ), // #411 - INST(Minpd , ExtRm , O(660F00,5D,_,_,_,_,_,_ ), 0 , 3 , 0 , 6183 , 5 , 4 ), // #412 - INST(Minps , ExtRm , O(000F00,5D,_,_,_,_,_,_ ), 0 , 4 , 0 , 6190 , 5 , 5 ), // #413 - INST(Minsd , ExtRm , O(F20F00,5D,_,_,_,_,_,_ ), 0 , 5 , 0 , 8221 , 6 , 4 ), // #414 - INST(Minss , ExtRm , O(F30F00,5D,_,_,_,_,_,_ ), 0 , 6 , 0 , 6204 , 7 , 5 ), // #415 + INST(Mfence , X86Fence , O(000F00,AE,6,_,_,_,_,_ ), 0 , 80 , 0 , 1941 , 30 , 4 ), // #411 + INST(Minpd , ExtRm , O(660F00,5D,_,_,_,_,_,_ ), 0 , 3 , 0 , 7117 , 5 , 4 ), // #412 + INST(Minps , ExtRm , O(000F00,5D,_,_,_,_,_,_ ), 0 , 4 , 0 , 7131 , 5 , 5 ), // #413 + INST(Minsd , ExtRm , O(F20F00,5D,_,_,_,_,_,_ ), 0 , 5 , 0 , 9196 , 6 , 4 ), // #414 + INST(Minss , ExtRm , O(F30F00,5D,_,_,_,_,_,_ ), 0 , 6 , 0 , 7152 , 7 , 5 ), // #415 INST(Monitor , X86Op , O(000F01,C8,_,_,_,_,_,_ ), 0 , 21 , 0 , 3232 , 115, 79 ), // #416 INST(Monitorx , X86Op , O(000F01,FA,_,_,_,_,_,_ ), 0 , 21 , 0 , 1948 , 115, 80 ), // #417 INST(Mov , X86Mov , 0 , 0 , 0 , 0 , 138 , 116, 0 ), // #418 INST(Movabs , X86Movabs , 0 , 0 , 0 , 0 , 1957 , 117, 0 ), // #419 - INST(Movapd , ExtMov , O(660F00,28,_,_,_,_,_,_ ), O(660F00,29,_,_,_,_,_,_ ), 3 , 45 , 6235 , 118, 4 ), // #420 - INST(Movaps , ExtMov , O(000F00,28,_,_,_,_,_,_ ), O(000F00,29,_,_,_,_,_,_ ), 4 , 46 , 6243 , 118, 5 ), // #421 - INST(Movbe , ExtMovbe , O(000F38,F0,_,_,x,_,_,_ ), O(000F38,F1,_,_,x,_,_,_ ), 84 , 47 , 656 , 119, 81 ), // #422 - INST(Movd , ExtMovd , O(000F00,6E,_,_,_,_,_,_ ), O(000F00,7E,_,_,_,_,_,_ ), 4 , 48 , 8131 , 120, 82 ), // #423 - INST(Movddup , ExtMov , O(F20F00,12,_,_,_,_,_,_ ), 0 , 5 , 0 , 6257 , 6 , 6 ), // #424 + INST(Movapd , ExtMov , O(660F00,28,_,_,_,_,_,_ ), O(660F00,29,_,_,_,_,_,_ ), 3 , 45 , 7183 , 118, 4 ), // #420 + INST(Movaps , ExtMov , O(000F00,28,_,_,_,_,_,_ ), O(000F00,29,_,_,_,_,_,_ ), 4 , 46 , 7191 , 118, 5 ), // #421 + INST(Movbe , ExtMovbe , O(000F38,F0,_,_,x,_,_,_ ), O(000F38,F1,_,_,x,_,_,_ ), 83 , 47 , 656 , 119, 81 ), // #422 + INST(Movd , ExtMovd , O(000F00,6E,_,_,_,_,_,_ ), O(000F00,7E,_,_,_,_,_,_ ), 4 , 48 , 9106 , 120, 82 ), // #423 + INST(Movddup , ExtMov , O(F20F00,12,_,_,_,_,_,_ ), 0 , 5 , 0 , 7205 , 6 , 6 ), // #424 INST(Movdir64b , X86EnqcmdMovdir64b , O(660F38,F8,_,_,_,_,_,_ ), 0 , 2 , 0 , 1964 , 121, 83 ), // #425 - INST(Movdiri , X86MovntiMovdiri , O(000F38,F9,_,_,_,_,_,_ ), 0 , 84 , 0 , 1974 , 122, 84 ), // #426 + INST(Movdiri , X86MovntiMovdiri , O(000F38,F9,_,_,_,_,_,_ ), 0 , 83 , 0 , 1974 , 122, 84 ), // #426 INST(Movdq2q , ExtMov , O(F20F00,D6,_,_,_,_,_,_ ), 0 , 5 , 0 , 1982 , 123, 4 ), // #427 - INST(Movdqa , ExtMov , O(660F00,6F,_,_,_,_,_,_ ), O(660F00,7F,_,_,_,_,_,_ ), 3 , 49 , 6266 , 118, 4 ), // #428 - INST(Movdqu , ExtMov , O(F30F00,6F,_,_,_,_,_,_ ), O(F30F00,7F,_,_,_,_,_,_ ), 6 , 50 , 6103 , 118, 4 ), // #429 - INST(Movhlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), 0 , 4 , 0 , 6341 , 124, 5 ), // #430 - INST(Movhpd , ExtMov , O(660F00,16,_,_,_,_,_,_ ), O(660F00,17,_,_,_,_,_,_ ), 3 , 51 , 6350 , 125, 4 ), // #431 - INST(Movhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), O(000F00,17,_,_,_,_,_,_ ), 4 , 52 , 6358 , 125, 5 ), // #432 - INST(Movlhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), 0 , 4 , 0 , 6366 , 124, 5 ), // #433 - INST(Movlpd , ExtMov , O(660F00,12,_,_,_,_,_,_ ), O(660F00,13,_,_,_,_,_,_ ), 3 , 53 , 6375 , 125, 4 ), // #434 - INST(Movlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), O(000F00,13,_,_,_,_,_,_ ), 4 , 54 , 6383 , 125, 5 ), // #435 - INST(Movmskpd , ExtMov , O(660F00,50,_,_,_,_,_,_ ), 0 , 3 , 0 , 6391 , 126, 4 ), // #436 - INST(Movmskps , ExtMov , O(000F00,50,_,_,_,_,_,_ ), 0 , 4 , 0 , 6401 , 126, 5 ), // #437 - INST(Movntdq , ExtMov , 0 , O(660F00,E7,_,_,_,_,_,_ ), 0 , 55 , 6411 , 127, 4 ), // #438 - INST(Movntdqa , ExtMov , O(660F38,2A,_,_,_,_,_,_ ), 0 , 2 , 0 , 6420 , 100, 12 ), // #439 + INST(Movdqa , ExtMov , O(660F00,6F,_,_,_,_,_,_ ), O(660F00,7F,_,_,_,_,_,_ ), 3 , 49 , 7214 , 118, 4 ), // #428 + INST(Movdqu , ExtMov , O(F30F00,6F,_,_,_,_,_,_ ), O(F30F00,7F,_,_,_,_,_,_ ), 6 , 50 , 7023 , 118, 4 ), // #429 + INST(Movhlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), 0 , 4 , 0 , 7289 , 124, 5 ), // #430 + INST(Movhpd , ExtMov , O(660F00,16,_,_,_,_,_,_ ), O(660F00,17,_,_,_,_,_,_ ), 3 , 51 , 7298 , 125, 4 ), // #431 + INST(Movhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), O(000F00,17,_,_,_,_,_,_ ), 4 , 52 , 7306 , 125, 5 ), // #432 + INST(Movlhps , ExtMov , O(000F00,16,_,_,_,_,_,_ ), 0 , 4 , 0 , 7314 , 124, 5 ), // #433 + INST(Movlpd , ExtMov , O(660F00,12,_,_,_,_,_,_ ), O(660F00,13,_,_,_,_,_,_ ), 3 , 53 , 7323 , 125, 4 ), // #434 + INST(Movlps , ExtMov , O(000F00,12,_,_,_,_,_,_ ), O(000F00,13,_,_,_,_,_,_ ), 4 , 54 , 7331 , 125, 5 ), // #435 + INST(Movmskpd , ExtMov , O(660F00,50,_,_,_,_,_,_ ), 0 , 3 , 0 , 7339 , 126, 4 ), // #436 + INST(Movmskps , ExtMov , O(000F00,50,_,_,_,_,_,_ ), 0 , 4 , 0 , 7349 , 126, 5 ), // #437 + INST(Movntdq , ExtMov , 0 , O(660F00,E7,_,_,_,_,_,_ ), 0 , 55 , 7359 , 127, 4 ), // #438 + INST(Movntdqa , ExtMov , O(660F38,2A,_,_,_,_,_,_ ), 0 , 2 , 0 , 7368 , 100, 12 ), // #439 INST(Movnti , X86MovntiMovdiri , O(000F00,C3,_,_,x,_,_,_ ), 0 , 4 , 0 , 1990 , 122, 4 ), // #440 - INST(Movntpd , ExtMov , 0 , O(660F00,2B,_,_,_,_,_,_ ), 0 , 56 , 6430 , 127, 4 ), // #441 - INST(Movntps , ExtMov , 0 , O(000F00,2B,_,_,_,_,_,_ ), 0 , 57 , 6439 , 127, 5 ), // #442 + INST(Movntpd , ExtMov , 0 , O(660F00,2B,_,_,_,_,_,_ ), 0 , 56 , 7378 , 127, 4 ), // #441 + INST(Movntps , ExtMov , 0 , O(000F00,2B,_,_,_,_,_,_ ), 0 , 57 , 7387 , 127, 5 ), // #442 INST(Movntq , ExtMov , 0 , O(000F00,E7,_,_,_,_,_,_ ), 0 , 58 , 1997 , 128, 77 ), // #443 INST(Movntsd , ExtMov , 0 , O(F20F00,2B,_,_,_,_,_,_ ), 0 , 59 , 2004 , 129, 49 ), // #444 INST(Movntss , ExtMov , 0 , O(F30F00,2B,_,_,_,_,_,_ ), 0 , 60 , 2012 , 130, 49 ), // #445 - INST(Movq , ExtMovq , O(000F00,6E,_,_,x,_,_,_ ), O(000F00,7E,_,_,x,_,_,_ ), 4 , 61 , 8142 , 131, 82 ), // #446 + INST(Movq , ExtMovq , O(000F00,6E,_,_,x,_,_,_ ), O(000F00,7E,_,_,x,_,_,_ ), 4 , 48 , 9117 , 131, 82 ), // #446 INST(Movq2dq , ExtRm , O(F30F00,D6,_,_,_,_,_,_ ), 0 , 6 , 0 , 2020 , 132, 4 ), // #447 INST(Movs , X86StrMm , O(000000,A4,_,_,_,_,_,_ ), 0 , 0 , 0 , 439 , 133, 75 ), // #448 - INST(Movsd , ExtMov , O(F20F00,10,_,_,_,_,_,_ ), O(F20F00,11,_,_,_,_,_,_ ), 5 , 62 , 6454 , 134, 4 ), // #449 - INST(Movshdup , ExtRm , O(F30F00,16,_,_,_,_,_,_ ), 0 , 6 , 0 , 6461 , 5 , 6 ), // #450 - INST(Movsldup , ExtRm , O(F30F00,12,_,_,_,_,_,_ ), 0 , 6 , 0 , 6471 , 5 , 6 ), // #451 - INST(Movss , ExtMov , O(F30F00,10,_,_,_,_,_,_ ), O(F30F00,11,_,_,_,_,_,_ ), 6 , 63 , 6481 , 135, 5 ), // #452 + INST(Movsd , ExtMov , O(F20F00,10,_,_,_,_,_,_ ), O(F20F00,11,_,_,_,_,_,_ ), 5 , 61 , 7402 , 134, 4 ), // #449 + INST(Movshdup , ExtRm , O(F30F00,16,_,_,_,_,_,_ ), 0 , 6 , 0 , 7416 , 5 , 6 ), // #450 + INST(Movsldup , ExtRm , O(F30F00,12,_,_,_,_,_,_ ), 0 , 6 , 0 , 7426 , 5 , 6 ), // #451 + INST(Movss , ExtMov , O(F30F00,10,_,_,_,_,_,_ ), O(F30F00,11,_,_,_,_,_,_ ), 6 , 62 , 7436 , 135, 5 ), // #452 INST(Movsx , X86MovsxMovzx , O(000F00,BE,_,_,x,_,_,_ ), 0 , 4 , 0 , 2028 , 136, 0 ), // #453 INST(Movsxd , X86Rm , O(000000,63,_,_,x,_,_,_ ), 0 , 0 , 0 , 2034 , 137, 0 ), // #454 - INST(Movupd , ExtMov , O(660F00,10,_,_,_,_,_,_ ), O(660F00,11,_,_,_,_,_,_ ), 3 , 64 , 6488 , 118, 4 ), // #455 - INST(Movups , ExtMov , O(000F00,10,_,_,_,_,_,_ ), O(000F00,11,_,_,_,_,_,_ ), 4 , 65 , 6496 , 118, 5 ), // #456 + INST(Movupd , ExtMov , O(660F00,10,_,_,_,_,_,_ ), O(660F00,11,_,_,_,_,_,_ ), 3 , 63 , 7443 , 118, 4 ), // #455 + INST(Movups , ExtMov , O(000F00,10,_,_,_,_,_,_ ), O(000F00,11,_,_,_,_,_,_ ), 4 , 64 , 7451 , 118, 5 ), // #456 INST(Movzx , X86MovsxMovzx , O(000F00,B6,_,_,x,_,_,_ ), 0 , 4 , 0 , 2041 , 136, 0 ), // #457 - INST(Mpsadbw , ExtRmi , O(660F3A,42,_,_,_,_,_,_ ), 0 , 8 , 0 , 6504 , 8 , 12 ), // #458 + INST(Mpsadbw , ExtRmi , O(660F3A,42,_,_,_,_,_,_ ), 0 , 8 , 0 , 7465 , 8 , 12 ), // #458 INST(Mul , X86M_GPB_MulDiv , O(000000,F6,4,_,x,_,_,_ ), 0 , 9 , 0 , 828 , 54 , 1 ), // #459 - INST(Mulpd , ExtRm , O(660F00,59,_,_,_,_,_,_ ), 0 , 3 , 0 , 6558 , 5 , 4 ), // #460 - INST(Mulps , ExtRm , O(000F00,59,_,_,_,_,_,_ ), 0 , 4 , 0 , 6565 , 5 , 5 ), // #461 - INST(Mulsd , ExtRm , O(F20F00,59,_,_,_,_,_,_ ), 0 , 5 , 0 , 6572 , 6 , 4 ), // #462 - INST(Mulss , ExtRm , O(F30F00,59,_,_,_,_,_,_ ), 0 , 6 , 0 , 6579 , 7 , 5 ), // #463 - INST(Mulx , VexRvm_ZDX_Wx , V(F20F38,F6,_,0,x,_,_,_ ), 0 , 85 , 0 , 2047 , 138, 85 ), // #464 + INST(Mulpd , ExtRm , O(660F00,59,_,_,_,_,_,_ ), 0 , 3 , 0 , 7519 , 5 , 4 ), // #460 + INST(Mulps , ExtRm , O(000F00,59,_,_,_,_,_,_ ), 0 , 4 , 0 , 7533 , 5 , 5 ), // #461 + INST(Mulsd , ExtRm , O(F20F00,59,_,_,_,_,_,_ ), 0 , 5 , 0 , 7540 , 6 , 4 ), // #462 + INST(Mulss , ExtRm , O(F30F00,59,_,_,_,_,_,_ ), 0 , 6 , 0 , 7554 , 7 , 5 ), // #463 + INST(Mulx , VexRvm_ZDX_Wx , V(F20F38,F6,_,0,x,_,_,_ ), 0 , 84 , 0 , 2047 , 138, 85 ), // #464 INST(Mwait , X86Op , O(000F01,C9,_,_,_,_,_,_ ), 0 , 21 , 0 , 3241 , 139, 79 ), // #465 INST(Mwaitx , X86Op , O(000F01,FB,_,_,_,_,_,_ ), 0 , 21 , 0 , 2052 , 140, 80 ), // #466 - INST(Neg , X86M_GPB , O(000000,F6,3,_,x,_,_,_ ), 0 , 76 , 0 , 2059 , 141, 1 ), // #467 + INST(Neg , X86M_GPB , O(000000,F6,3,_,x,_,_,_ ), 0 , 75 , 0 , 2059 , 141, 1 ), // #467 INST(Nop , X86M_Nop , O(000000,90,_,_,_,_,_,_ ), 0 , 0 , 0 , 959 , 142, 0 ), // #468 INST(Not , X86M_GPB , O(000000,F6,2,_,x,_,_,_ ), 0 , 1 , 0 , 2063 , 141, 0 ), // #469 INST(Or , X86Arith , O(000000,08,1,_,x,_,_,_ ), 0 , 31 , 0 , 3237 , 143, 1 ), // #470 - INST(Orpd , ExtRm , O(660F00,56,_,_,_,_,_,_ ), 0 , 3 , 0 , 10348, 11 , 4 ), // #471 - INST(Orps , ExtRm , O(000F00,56,_,_,_,_,_,_ ), 0 , 4 , 0 , 10355, 11 , 5 ), // #472 - INST(Out , X86Out , O(000000,EE,_,_,_,_,_,_ ), O(000000,E6,_,_,_,_,_,_ ), 0 , 66 , 2067 , 144, 0 ), // #473 + INST(Orpd , ExtRm , O(660F00,56,_,_,_,_,_,_ ), 0 , 3 , 0 , 11458, 11 , 4 ), // #471 + INST(Orps , ExtRm , O(000F00,56,_,_,_,_,_,_ ), 0 , 4 , 0 , 11465, 11 , 5 ), // #472 + INST(Out , X86Out , O(000000,EE,_,_,_,_,_,_ ), O(000000,E6,_,_,_,_,_,_ ), 0 , 65 , 2067 , 144, 0 ), // #473 INST(Outs , X86Outs , O(000000,6E,_,_,_,_,_,_ ), 0 , 0 , 0 , 2071 , 145, 0 ), // #474 - INST(Pabsb , ExtRm_P , O(000F38,1C,_,_,_,_,_,_ ), 0 , 84 , 0 , 6661 , 146, 86 ), // #475 - INST(Pabsd , ExtRm_P , O(000F38,1E,_,_,_,_,_,_ ), 0 , 84 , 0 , 6668 , 146, 86 ), // #476 - INST(Pabsw , ExtRm_P , O(000F38,1D,_,_,_,_,_,_ ), 0 , 84 , 0 , 6682 , 146, 86 ), // #477 - INST(Packssdw , ExtRm_P , O(000F00,6B,_,_,_,_,_,_ ), 0 , 4 , 0 , 6689 , 146, 82 ), // #478 - INST(Packsswb , ExtRm_P , O(000F00,63,_,_,_,_,_,_ ), 0 , 4 , 0 , 6699 , 146, 82 ), // #479 - INST(Packusdw , ExtRm , O(660F38,2B,_,_,_,_,_,_ ), 0 , 2 , 0 , 6709 , 5 , 12 ), // #480 - INST(Packuswb , ExtRm_P , O(000F00,67,_,_,_,_,_,_ ), 0 , 4 , 0 , 6719 , 146, 82 ), // #481 - INST(Paddb , ExtRm_P , O(000F00,FC,_,_,_,_,_,_ ), 0 , 4 , 0 , 6729 , 146, 82 ), // #482 - INST(Paddd , ExtRm_P , O(000F00,FE,_,_,_,_,_,_ ), 0 , 4 , 0 , 6736 , 146, 82 ), // #483 - INST(Paddq , ExtRm_P , O(000F00,D4,_,_,_,_,_,_ ), 0 , 4 , 0 , 6743 , 146, 4 ), // #484 - INST(Paddsb , ExtRm_P , O(000F00,EC,_,_,_,_,_,_ ), 0 , 4 , 0 , 6750 , 146, 82 ), // #485 - INST(Paddsw , ExtRm_P , O(000F00,ED,_,_,_,_,_,_ ), 0 , 4 , 0 , 6758 , 146, 82 ), // #486 - INST(Paddusb , ExtRm_P , O(000F00,DC,_,_,_,_,_,_ ), 0 , 4 , 0 , 6766 , 146, 82 ), // #487 - INST(Paddusw , ExtRm_P , O(000F00,DD,_,_,_,_,_,_ ), 0 , 4 , 0 , 6775 , 146, 82 ), // #488 - INST(Paddw , ExtRm_P , O(000F00,FD,_,_,_,_,_,_ ), 0 , 4 , 0 , 6784 , 146, 82 ), // #489 - INST(Palignr , ExtRmi_P , O(000F3A,0F,_,_,_,_,_,_ ), 0 , 86 , 0 , 6791 , 147, 6 ), // #490 - INST(Pand , ExtRm_P , O(000F00,DB,_,_,_,_,_,_ ), 0 , 4 , 0 , 6800 , 148, 82 ), // #491 - INST(Pandn , ExtRm_P , O(000F00,DF,_,_,_,_,_,_ ), 0 , 4 , 0 , 6813 , 149, 82 ), // #492 - INST(Pause , X86Op , O(F30000,90,_,_,_,_,_,_ ), 0 , 87 , 0 , 3195 , 30 , 0 ), // #493 - INST(Pavgb , ExtRm_P , O(000F00,E0,_,_,_,_,_,_ ), 0 , 4 , 0 , 6843 , 146, 87 ), // #494 - INST(Pavgusb , Ext3dNow , O(000F0F,BF,_,_,_,_,_,_ ), 0 , 88 , 0 , 2076 , 150, 51 ), // #495 - INST(Pavgw , ExtRm_P , O(000F00,E3,_,_,_,_,_,_ ), 0 , 4 , 0 , 6850 , 146, 87 ), // #496 - INST(Pblendvb , ExtRm_XMM0 , O(660F38,10,_,_,_,_,_,_ ), 0 , 2 , 0 , 6906 , 15 , 12 ), // #497 - INST(Pblendw , ExtRmi , O(660F3A,0E,_,_,_,_,_,_ ), 0 , 8 , 0 , 6916 , 8 , 12 ), // #498 - INST(Pclmulqdq , ExtRmi , O(660F3A,44,_,_,_,_,_,_ ), 0 , 8 , 0 , 7009 , 8 , 88 ), // #499 - INST(Pcmpeqb , ExtRm_P , O(000F00,74,_,_,_,_,_,_ ), 0 , 4 , 0 , 7041 , 149, 82 ), // #500 - INST(Pcmpeqd , ExtRm_P , O(000F00,76,_,_,_,_,_,_ ), 0 , 4 , 0 , 7050 , 149, 82 ), // #501 - INST(Pcmpeqq , ExtRm , O(660F38,29,_,_,_,_,_,_ ), 0 , 2 , 0 , 7059 , 151, 12 ), // #502 - INST(Pcmpeqw , ExtRm_P , O(000F00,75,_,_,_,_,_,_ ), 0 , 4 , 0 , 7068 , 149, 82 ), // #503 - INST(Pcmpestri , ExtRmi , O(660F3A,61,_,_,_,_,_,_ ), 0 , 8 , 0 , 7077 , 152, 89 ), // #504 - INST(Pcmpestrm , ExtRmi , O(660F3A,60,_,_,_,_,_,_ ), 0 , 8 , 0 , 7088 , 153, 89 ), // #505 - INST(Pcmpgtb , ExtRm_P , O(000F00,64,_,_,_,_,_,_ ), 0 , 4 , 0 , 7099 , 149, 82 ), // #506 - INST(Pcmpgtd , ExtRm_P , O(000F00,66,_,_,_,_,_,_ ), 0 , 4 , 0 , 7108 , 149, 82 ), // #507 - INST(Pcmpgtq , ExtRm , O(660F38,37,_,_,_,_,_,_ ), 0 , 2 , 0 , 7117 , 151, 44 ), // #508 - INST(Pcmpgtw , ExtRm_P , O(000F00,65,_,_,_,_,_,_ ), 0 , 4 , 0 , 7126 , 149, 82 ), // #509 - INST(Pcmpistri , ExtRmi , O(660F3A,63,_,_,_,_,_,_ ), 0 , 8 , 0 , 7135 , 154, 89 ), // #510 - INST(Pcmpistrm , ExtRmi , O(660F3A,62,_,_,_,_,_,_ ), 0 , 8 , 0 , 7146 , 155, 89 ), // #511 + INST(Pabsb , ExtRm_P , O(000F38,1C,_,_,_,_,_,_ ), 0 , 83 , 0 , 7636 , 146, 86 ), // #475 + INST(Pabsd , ExtRm_P , O(000F38,1E,_,_,_,_,_,_ ), 0 , 83 , 0 , 7643 , 146, 86 ), // #476 + INST(Pabsw , ExtRm_P , O(000F38,1D,_,_,_,_,_,_ ), 0 , 83 , 0 , 7657 , 146, 86 ), // #477 + INST(Packssdw , ExtRm_P , O(000F00,6B,_,_,_,_,_,_ ), 0 , 4 , 0 , 7664 , 146, 82 ), // #478 + INST(Packsswb , ExtRm_P , O(000F00,63,_,_,_,_,_,_ ), 0 , 4 , 0 , 7674 , 146, 82 ), // #479 + INST(Packusdw , ExtRm , O(660F38,2B,_,_,_,_,_,_ ), 0 , 2 , 0 , 7684 , 5 , 12 ), // #480 + INST(Packuswb , ExtRm_P , O(000F00,67,_,_,_,_,_,_ ), 0 , 4 , 0 , 7694 , 146, 82 ), // #481 + INST(Paddb , ExtRm_P , O(000F00,FC,_,_,_,_,_,_ ), 0 , 4 , 0 , 7704 , 146, 82 ), // #482 + INST(Paddd , ExtRm_P , O(000F00,FE,_,_,_,_,_,_ ), 0 , 4 , 0 , 7711 , 146, 82 ), // #483 + INST(Paddq , ExtRm_P , O(000F00,D4,_,_,_,_,_,_ ), 0 , 4 , 0 , 7718 , 146, 4 ), // #484 + INST(Paddsb , ExtRm_P , O(000F00,EC,_,_,_,_,_,_ ), 0 , 4 , 0 , 7725 , 146, 82 ), // #485 + INST(Paddsw , ExtRm_P , O(000F00,ED,_,_,_,_,_,_ ), 0 , 4 , 0 , 7733 , 146, 82 ), // #486 + INST(Paddusb , ExtRm_P , O(000F00,DC,_,_,_,_,_,_ ), 0 , 4 , 0 , 7741 , 146, 82 ), // #487 + INST(Paddusw , ExtRm_P , O(000F00,DD,_,_,_,_,_,_ ), 0 , 4 , 0 , 7750 , 146, 82 ), // #488 + INST(Paddw , ExtRm_P , O(000F00,FD,_,_,_,_,_,_ ), 0 , 4 , 0 , 7759 , 146, 82 ), // #489 + INST(Palignr , ExtRmi_P , O(000F3A,0F,_,_,_,_,_,_ ), 0 , 85 , 0 , 7766 , 147, 6 ), // #490 + INST(Pand , ExtRm_P , O(000F00,DB,_,_,_,_,_,_ ), 0 , 4 , 0 , 7775 , 148, 82 ), // #491 + INST(Pandn , ExtRm_P , O(000F00,DF,_,_,_,_,_,_ ), 0 , 4 , 0 , 7788 , 149, 82 ), // #492 + INST(Pause , X86Op , O(F30000,90,_,_,_,_,_,_ ), 0 , 86 , 0 , 3195 , 30 , 0 ), // #493 + INST(Pavgb , ExtRm_P , O(000F00,E0,_,_,_,_,_,_ ), 0 , 4 , 0 , 7818 , 146, 87 ), // #494 + INST(Pavgusb , Ext3dNow , O(000F0F,BF,_,_,_,_,_,_ ), 0 , 87 , 0 , 2076 , 150, 51 ), // #495 + INST(Pavgw , ExtRm_P , O(000F00,E3,_,_,_,_,_,_ ), 0 , 4 , 0 , 7825 , 146, 87 ), // #496 + INST(Pblendvb , ExtRm_XMM0 , O(660F38,10,_,_,_,_,_,_ ), 0 , 2 , 0 , 7881 , 15 , 12 ), // #497 + INST(Pblendw , ExtRmi , O(660F3A,0E,_,_,_,_,_,_ ), 0 , 8 , 0 , 7891 , 8 , 12 ), // #498 + INST(Pclmulqdq , ExtRmi , O(660F3A,44,_,_,_,_,_,_ ), 0 , 8 , 0 , 7984 , 8 , 88 ), // #499 + INST(Pcmpeqb , ExtRm_P , O(000F00,74,_,_,_,_,_,_ ), 0 , 4 , 0 , 8016 , 149, 82 ), // #500 + INST(Pcmpeqd , ExtRm_P , O(000F00,76,_,_,_,_,_,_ ), 0 , 4 , 0 , 8025 , 149, 82 ), // #501 + INST(Pcmpeqq , ExtRm , O(660F38,29,_,_,_,_,_,_ ), 0 , 2 , 0 , 8034 , 151, 12 ), // #502 + INST(Pcmpeqw , ExtRm_P , O(000F00,75,_,_,_,_,_,_ ), 0 , 4 , 0 , 8043 , 149, 82 ), // #503 + INST(Pcmpestri , ExtRmi , O(660F3A,61,_,_,_,_,_,_ ), 0 , 8 , 0 , 8052 , 152, 89 ), // #504 + INST(Pcmpestrm , ExtRmi , O(660F3A,60,_,_,_,_,_,_ ), 0 , 8 , 0 , 8063 , 153, 89 ), // #505 + INST(Pcmpgtb , ExtRm_P , O(000F00,64,_,_,_,_,_,_ ), 0 , 4 , 0 , 8074 , 149, 82 ), // #506 + INST(Pcmpgtd , ExtRm_P , O(000F00,66,_,_,_,_,_,_ ), 0 , 4 , 0 , 8083 , 149, 82 ), // #507 + INST(Pcmpgtq , ExtRm , O(660F38,37,_,_,_,_,_,_ ), 0 , 2 , 0 , 8092 , 151, 44 ), // #508 + INST(Pcmpgtw , ExtRm_P , O(000F00,65,_,_,_,_,_,_ ), 0 , 4 , 0 , 8101 , 149, 82 ), // #509 + INST(Pcmpistri , ExtRmi , O(660F3A,63,_,_,_,_,_,_ ), 0 , 8 , 0 , 8110 , 154, 89 ), // #510 + INST(Pcmpistrm , ExtRmi , O(660F3A,62,_,_,_,_,_,_ ), 0 , 8 , 0 , 8121 , 155, 89 ), // #511 INST(Pconfig , X86Op , O(000F01,C5,_,_,_,_,_,_ ), 0 , 21 , 0 , 2084 , 30 , 90 ), // #512 - INST(Pdep , VexRvm_Wx , V(F20F38,F5,_,0,x,_,_,_ ), 0 , 85 , 0 , 2092 , 10 , 85 ), // #513 - INST(Pext , VexRvm_Wx , V(F30F38,F5,_,0,x,_,_,_ ), 0 , 89 , 0 , 2097 , 10 , 85 ), // #514 - INST(Pextrb , ExtExtract , O(000F3A,14,_,_,_,_,_,_ ), 0 , 86 , 0 , 7633 , 156, 12 ), // #515 - INST(Pextrd , ExtExtract , O(000F3A,16,_,_,_,_,_,_ ), 0 , 86 , 0 , 7641 , 58 , 12 ), // #516 - INST(Pextrq , ExtExtract , O(000F3A,16,_,_,1,_,_,_ ), 0 , 90 , 0 , 7649 , 157, 12 ), // #517 - INST(Pextrw , ExtPextrw , O(000F00,C5,_,_,_,_,_,_ ), O(000F3A,15,_,_,_,_,_,_ ), 4 , 67 , 7657 , 158, 91 ), // #518 - INST(Pf2id , Ext3dNow , O(000F0F,1D,_,_,_,_,_,_ ), 0 , 88 , 0 , 2102 , 150, 51 ), // #519 - INST(Pf2iw , Ext3dNow , O(000F0F,1C,_,_,_,_,_,_ ), 0 , 88 , 0 , 2108 , 150, 92 ), // #520 - INST(Pfacc , Ext3dNow , O(000F0F,AE,_,_,_,_,_,_ ), 0 , 88 , 0 , 2114 , 150, 51 ), // #521 - INST(Pfadd , Ext3dNow , O(000F0F,9E,_,_,_,_,_,_ ), 0 , 88 , 0 , 2120 , 150, 51 ), // #522 - INST(Pfcmpeq , Ext3dNow , O(000F0F,B0,_,_,_,_,_,_ ), 0 , 88 , 0 , 2126 , 150, 51 ), // #523 - INST(Pfcmpge , Ext3dNow , O(000F0F,90,_,_,_,_,_,_ ), 0 , 88 , 0 , 2134 , 150, 51 ), // #524 - INST(Pfcmpgt , Ext3dNow , O(000F0F,A0,_,_,_,_,_,_ ), 0 , 88 , 0 , 2142 , 150, 51 ), // #525 - INST(Pfmax , Ext3dNow , O(000F0F,A4,_,_,_,_,_,_ ), 0 , 88 , 0 , 2150 , 150, 51 ), // #526 - INST(Pfmin , Ext3dNow , O(000F0F,94,_,_,_,_,_,_ ), 0 , 88 , 0 , 2156 , 150, 51 ), // #527 - INST(Pfmul , Ext3dNow , O(000F0F,B4,_,_,_,_,_,_ ), 0 , 88 , 0 , 2162 , 150, 51 ), // #528 - INST(Pfnacc , Ext3dNow , O(000F0F,8A,_,_,_,_,_,_ ), 0 , 88 , 0 , 2168 , 150, 92 ), // #529 - INST(Pfpnacc , Ext3dNow , O(000F0F,8E,_,_,_,_,_,_ ), 0 , 88 , 0 , 2175 , 150, 92 ), // #530 - INST(Pfrcp , Ext3dNow , O(000F0F,96,_,_,_,_,_,_ ), 0 , 88 , 0 , 2183 , 150, 51 ), // #531 - INST(Pfrcpit1 , Ext3dNow , O(000F0F,A6,_,_,_,_,_,_ ), 0 , 88 , 0 , 2189 , 150, 51 ), // #532 - INST(Pfrcpit2 , Ext3dNow , O(000F0F,B6,_,_,_,_,_,_ ), 0 , 88 , 0 , 2198 , 150, 51 ), // #533 - INST(Pfrcpv , Ext3dNow , O(000F0F,86,_,_,_,_,_,_ ), 0 , 88 , 0 , 2207 , 150, 93 ), // #534 - INST(Pfrsqit1 , Ext3dNow , O(000F0F,A7,_,_,_,_,_,_ ), 0 , 88 , 0 , 2214 , 150, 51 ), // #535 - INST(Pfrsqrt , Ext3dNow , O(000F0F,97,_,_,_,_,_,_ ), 0 , 88 , 0 , 2223 , 150, 51 ), // #536 - INST(Pfrsqrtv , Ext3dNow , O(000F0F,87,_,_,_,_,_,_ ), 0 , 88 , 0 , 2231 , 150, 93 ), // #537 - INST(Pfsub , Ext3dNow , O(000F0F,9A,_,_,_,_,_,_ ), 0 , 88 , 0 , 2240 , 150, 51 ), // #538 - INST(Pfsubr , Ext3dNow , O(000F0F,AA,_,_,_,_,_,_ ), 0 , 88 , 0 , 2246 , 150, 51 ), // #539 - INST(Phaddd , ExtRm_P , O(000F38,02,_,_,_,_,_,_ ), 0 , 84 , 0 , 7736 , 146, 86 ), // #540 - INST(Phaddsw , ExtRm_P , O(000F38,03,_,_,_,_,_,_ ), 0 , 84 , 0 , 7753 , 146, 86 ), // #541 - INST(Phaddw , ExtRm_P , O(000F38,01,_,_,_,_,_,_ ), 0 , 84 , 0 , 7822 , 146, 86 ), // #542 - INST(Phminposuw , ExtRm , O(660F38,41,_,_,_,_,_,_ ), 0 , 2 , 0 , 7848 , 5 , 12 ), // #543 - INST(Phsubd , ExtRm_P , O(000F38,06,_,_,_,_,_,_ ), 0 , 84 , 0 , 7869 , 146, 86 ), // #544 - INST(Phsubsw , ExtRm_P , O(000F38,07,_,_,_,_,_,_ ), 0 , 84 , 0 , 7886 , 146, 86 ), // #545 - INST(Phsubw , ExtRm_P , O(000F38,05,_,_,_,_,_,_ ), 0 , 84 , 0 , 7895 , 146, 86 ), // #546 - INST(Pi2fd , Ext3dNow , O(000F0F,0D,_,_,_,_,_,_ ), 0 , 88 , 0 , 2253 , 150, 51 ), // #547 - INST(Pi2fw , Ext3dNow , O(000F0F,0C,_,_,_,_,_,_ ), 0 , 88 , 0 , 2259 , 150, 92 ), // #548 - INST(Pinsrb , ExtRmi , O(660F3A,20,_,_,_,_,_,_ ), 0 , 8 , 0 , 7912 , 159, 12 ), // #549 - INST(Pinsrd , ExtRmi , O(660F3A,22,_,_,_,_,_,_ ), 0 , 8 , 0 , 7920 , 160, 12 ), // #550 - INST(Pinsrq , ExtRmi , O(660F3A,22,_,_,1,_,_,_ ), 0 , 91 , 0 , 7928 , 161, 12 ), // #551 - INST(Pinsrw , ExtRmi_P , O(000F00,C4,_,_,_,_,_,_ ), 0 , 4 , 0 , 7936 , 162, 87 ), // #552 - INST(Pmaddubsw , ExtRm_P , O(000F38,04,_,_,_,_,_,_ ), 0 , 84 , 0 , 8106 , 146, 86 ), // #553 - INST(Pmaddwd , ExtRm_P , O(000F00,F5,_,_,_,_,_,_ ), 0 , 4 , 0 , 8117 , 146, 82 ), // #554 - INST(Pmaxsb , ExtRm , O(660F38,3C,_,_,_,_,_,_ ), 0 , 2 , 0 , 8148 , 11 , 12 ), // #555 - INST(Pmaxsd , ExtRm , O(660F38,3D,_,_,_,_,_,_ ), 0 , 2 , 0 , 8156 , 11 , 12 ), // #556 - INST(Pmaxsw , ExtRm_P , O(000F00,EE,_,_,_,_,_,_ ), 0 , 4 , 0 , 8172 , 148, 87 ), // #557 - INST(Pmaxub , ExtRm_P , O(000F00,DE,_,_,_,_,_,_ ), 0 , 4 , 0 , 8180 , 148, 87 ), // #558 - INST(Pmaxud , ExtRm , O(660F38,3F,_,_,_,_,_,_ ), 0 , 2 , 0 , 8188 , 11 , 12 ), // #559 - INST(Pmaxuw , ExtRm , O(660F38,3E,_,_,_,_,_,_ ), 0 , 2 , 0 , 8204 , 11 , 12 ), // #560 - INST(Pminsb , ExtRm , O(660F38,38,_,_,_,_,_,_ ), 0 , 2 , 0 , 8212 , 11 , 12 ), // #561 - INST(Pminsd , ExtRm , O(660F38,39,_,_,_,_,_,_ ), 0 , 2 , 0 , 8220 , 11 , 12 ), // #562 - INST(Pminsw , ExtRm_P , O(000F00,EA,_,_,_,_,_,_ ), 0 , 4 , 0 , 8236 , 148, 87 ), // #563 - INST(Pminub , ExtRm_P , O(000F00,DA,_,_,_,_,_,_ ), 0 , 4 , 0 , 8244 , 148, 87 ), // #564 - INST(Pminud , ExtRm , O(660F38,3B,_,_,_,_,_,_ ), 0 , 2 , 0 , 8252 , 11 , 12 ), // #565 - INST(Pminuw , ExtRm , O(660F38,3A,_,_,_,_,_,_ ), 0 , 2 , 0 , 8268 , 11 , 12 ), // #566 - INST(Pmovmskb , ExtRm_P , O(000F00,D7,_,_,_,_,_,_ ), 0 , 4 , 0 , 8346 , 163, 87 ), // #567 - INST(Pmovsxbd , ExtRm , O(660F38,21,_,_,_,_,_,_ ), 0 , 2 , 0 , 8443 , 7 , 12 ), // #568 - INST(Pmovsxbq , ExtRm , O(660F38,22,_,_,_,_,_,_ ), 0 , 2 , 0 , 8453 , 164, 12 ), // #569 - INST(Pmovsxbw , ExtRm , O(660F38,20,_,_,_,_,_,_ ), 0 , 2 , 0 , 8463 , 6 , 12 ), // #570 - INST(Pmovsxdq , ExtRm , O(660F38,25,_,_,_,_,_,_ ), 0 , 2 , 0 , 8473 , 6 , 12 ), // #571 - INST(Pmovsxwd , ExtRm , O(660F38,23,_,_,_,_,_,_ ), 0 , 2 , 0 , 8483 , 6 , 12 ), // #572 - INST(Pmovsxwq , ExtRm , O(660F38,24,_,_,_,_,_,_ ), 0 , 2 , 0 , 8493 , 7 , 12 ), // #573 - INST(Pmovzxbd , ExtRm , O(660F38,31,_,_,_,_,_,_ ), 0 , 2 , 0 , 8580 , 7 , 12 ), // #574 - INST(Pmovzxbq , ExtRm , O(660F38,32,_,_,_,_,_,_ ), 0 , 2 , 0 , 8590 , 164, 12 ), // #575 - INST(Pmovzxbw , ExtRm , O(660F38,30,_,_,_,_,_,_ ), 0 , 2 , 0 , 8600 , 6 , 12 ), // #576 - INST(Pmovzxdq , ExtRm , O(660F38,35,_,_,_,_,_,_ ), 0 , 2 , 0 , 8610 , 6 , 12 ), // #577 - INST(Pmovzxwd , ExtRm , O(660F38,33,_,_,_,_,_,_ ), 0 , 2 , 0 , 8620 , 6 , 12 ), // #578 - INST(Pmovzxwq , ExtRm , O(660F38,34,_,_,_,_,_,_ ), 0 , 2 , 0 , 8630 , 7 , 12 ), // #579 - INST(Pmuldq , ExtRm , O(660F38,28,_,_,_,_,_,_ ), 0 , 2 , 0 , 8640 , 5 , 12 ), // #580 - INST(Pmulhrsw , ExtRm_P , O(000F38,0B,_,_,_,_,_,_ ), 0 , 84 , 0 , 8648 , 146, 86 ), // #581 - INST(Pmulhrw , Ext3dNow , O(000F0F,B7,_,_,_,_,_,_ ), 0 , 88 , 0 , 2265 , 150, 51 ), // #582 - INST(Pmulhuw , ExtRm_P , O(000F00,E4,_,_,_,_,_,_ ), 0 , 4 , 0 , 8658 , 146, 87 ), // #583 - INST(Pmulhw , ExtRm_P , O(000F00,E5,_,_,_,_,_,_ ), 0 , 4 , 0 , 8667 , 146, 82 ), // #584 - INST(Pmulld , ExtRm , O(660F38,40,_,_,_,_,_,_ ), 0 , 2 , 0 , 8675 , 5 , 12 ), // #585 - INST(Pmullw , ExtRm_P , O(000F00,D5,_,_,_,_,_,_ ), 0 , 4 , 0 , 8691 , 146, 82 ), // #586 - INST(Pmuludq , ExtRm_P , O(000F00,F4,_,_,_,_,_,_ ), 0 , 4 , 0 , 8714 , 146, 4 ), // #587 - INST(Pop , X86Pop , O(000000,8F,0,_,_,_,_,_ ), O(000000,58,_,_,_,_,_,_ ), 0 , 68 , 2273 , 165, 0 ), // #588 + INST(Pdep , VexRvm_Wx , V(F20F38,F5,_,0,x,_,_,_ ), 0 , 84 , 0 , 2092 , 10 , 85 ), // #513 + INST(Pext , VexRvm_Wx , V(F30F38,F5,_,0,x,_,_,_ ), 0 , 88 , 0 , 2097 , 10 , 85 ), // #514 + INST(Pextrb , ExtExtract , O(000F3A,14,_,_,_,_,_,_ ), 0 , 85 , 0 , 8608 , 156, 12 ), // #515 + INST(Pextrd , ExtExtract , O(000F3A,16,_,_,_,_,_,_ ), 0 , 85 , 0 , 8616 , 58 , 12 ), // #516 + INST(Pextrq , ExtExtract , O(000F3A,16,_,_,1,_,_,_ ), 0 , 89 , 0 , 8624 , 157, 12 ), // #517 + INST(Pextrw , ExtPextrw , O(000F00,C5,_,_,_,_,_,_ ), O(000F3A,15,_,_,_,_,_,_ ), 4 , 66 , 8632 , 158, 91 ), // #518 + INST(Pf2id , Ext3dNow , O(000F0F,1D,_,_,_,_,_,_ ), 0 , 87 , 0 , 2102 , 150, 51 ), // #519 + INST(Pf2iw , Ext3dNow , O(000F0F,1C,_,_,_,_,_,_ ), 0 , 87 , 0 , 2108 , 150, 92 ), // #520 + INST(Pfacc , Ext3dNow , O(000F0F,AE,_,_,_,_,_,_ ), 0 , 87 , 0 , 2114 , 150, 51 ), // #521 + INST(Pfadd , Ext3dNow , O(000F0F,9E,_,_,_,_,_,_ ), 0 , 87 , 0 , 2120 , 150, 51 ), // #522 + INST(Pfcmpeq , Ext3dNow , O(000F0F,B0,_,_,_,_,_,_ ), 0 , 87 , 0 , 2126 , 150, 51 ), // #523 + INST(Pfcmpge , Ext3dNow , O(000F0F,90,_,_,_,_,_,_ ), 0 , 87 , 0 , 2134 , 150, 51 ), // #524 + INST(Pfcmpgt , Ext3dNow , O(000F0F,A0,_,_,_,_,_,_ ), 0 , 87 , 0 , 2142 , 150, 51 ), // #525 + INST(Pfmax , Ext3dNow , O(000F0F,A4,_,_,_,_,_,_ ), 0 , 87 , 0 , 2150 , 150, 51 ), // #526 + INST(Pfmin , Ext3dNow , O(000F0F,94,_,_,_,_,_,_ ), 0 , 87 , 0 , 2156 , 150, 51 ), // #527 + INST(Pfmul , Ext3dNow , O(000F0F,B4,_,_,_,_,_,_ ), 0 , 87 , 0 , 2162 , 150, 51 ), // #528 + INST(Pfnacc , Ext3dNow , O(000F0F,8A,_,_,_,_,_,_ ), 0 , 87 , 0 , 2168 , 150, 92 ), // #529 + INST(Pfpnacc , Ext3dNow , O(000F0F,8E,_,_,_,_,_,_ ), 0 , 87 , 0 , 2175 , 150, 92 ), // #530 + INST(Pfrcp , Ext3dNow , O(000F0F,96,_,_,_,_,_,_ ), 0 , 87 , 0 , 2183 , 150, 51 ), // #531 + INST(Pfrcpit1 , Ext3dNow , O(000F0F,A6,_,_,_,_,_,_ ), 0 , 87 , 0 , 2189 , 150, 51 ), // #532 + INST(Pfrcpit2 , Ext3dNow , O(000F0F,B6,_,_,_,_,_,_ ), 0 , 87 , 0 , 2198 , 150, 51 ), // #533 + INST(Pfrcpv , Ext3dNow , O(000F0F,86,_,_,_,_,_,_ ), 0 , 87 , 0 , 2207 , 150, 93 ), // #534 + INST(Pfrsqit1 , Ext3dNow , O(000F0F,A7,_,_,_,_,_,_ ), 0 , 87 , 0 , 2214 , 150, 51 ), // #535 + INST(Pfrsqrt , Ext3dNow , O(000F0F,97,_,_,_,_,_,_ ), 0 , 87 , 0 , 2223 , 150, 51 ), // #536 + INST(Pfrsqrtv , Ext3dNow , O(000F0F,87,_,_,_,_,_,_ ), 0 , 87 , 0 , 2231 , 150, 93 ), // #537 + INST(Pfsub , Ext3dNow , O(000F0F,9A,_,_,_,_,_,_ ), 0 , 87 , 0 , 2240 , 150, 51 ), // #538 + INST(Pfsubr , Ext3dNow , O(000F0F,AA,_,_,_,_,_,_ ), 0 , 87 , 0 , 2246 , 150, 51 ), // #539 + INST(Phaddd , ExtRm_P , O(000F38,02,_,_,_,_,_,_ ), 0 , 83 , 0 , 8711 , 146, 86 ), // #540 + INST(Phaddsw , ExtRm_P , O(000F38,03,_,_,_,_,_,_ ), 0 , 83 , 0 , 8728 , 146, 86 ), // #541 + INST(Phaddw , ExtRm_P , O(000F38,01,_,_,_,_,_,_ ), 0 , 83 , 0 , 8797 , 146, 86 ), // #542 + INST(Phminposuw , ExtRm , O(660F38,41,_,_,_,_,_,_ ), 0 , 2 , 0 , 8823 , 5 , 12 ), // #543 + INST(Phsubd , ExtRm_P , O(000F38,06,_,_,_,_,_,_ ), 0 , 83 , 0 , 8844 , 146, 86 ), // #544 + INST(Phsubsw , ExtRm_P , O(000F38,07,_,_,_,_,_,_ ), 0 , 83 , 0 , 8861 , 146, 86 ), // #545 + INST(Phsubw , ExtRm_P , O(000F38,05,_,_,_,_,_,_ ), 0 , 83 , 0 , 8870 , 146, 86 ), // #546 + INST(Pi2fd , Ext3dNow , O(000F0F,0D,_,_,_,_,_,_ ), 0 , 87 , 0 , 2253 , 150, 51 ), // #547 + INST(Pi2fw , Ext3dNow , O(000F0F,0C,_,_,_,_,_,_ ), 0 , 87 , 0 , 2259 , 150, 92 ), // #548 + INST(Pinsrb , ExtRmi , O(660F3A,20,_,_,_,_,_,_ ), 0 , 8 , 0 , 8887 , 159, 12 ), // #549 + INST(Pinsrd , ExtRmi , O(660F3A,22,_,_,_,_,_,_ ), 0 , 8 , 0 , 8895 , 160, 12 ), // #550 + INST(Pinsrq , ExtRmi , O(660F3A,22,_,_,1,_,_,_ ), 0 , 90 , 0 , 8903 , 161, 12 ), // #551 + INST(Pinsrw , ExtRmi_P , O(000F00,C4,_,_,_,_,_,_ ), 0 , 4 , 0 , 8911 , 162, 87 ), // #552 + INST(Pmaddubsw , ExtRm_P , O(000F38,04,_,_,_,_,_,_ ), 0 , 83 , 0 , 9081 , 146, 86 ), // #553 + INST(Pmaddwd , ExtRm_P , O(000F00,F5,_,_,_,_,_,_ ), 0 , 4 , 0 , 9092 , 146, 82 ), // #554 + INST(Pmaxsb , ExtRm , O(660F38,3C,_,_,_,_,_,_ ), 0 , 2 , 0 , 9123 , 11 , 12 ), // #555 + INST(Pmaxsd , ExtRm , O(660F38,3D,_,_,_,_,_,_ ), 0 , 2 , 0 , 9131 , 11 , 12 ), // #556 + INST(Pmaxsw , ExtRm_P , O(000F00,EE,_,_,_,_,_,_ ), 0 , 4 , 0 , 9147 , 148, 87 ), // #557 + INST(Pmaxub , ExtRm_P , O(000F00,DE,_,_,_,_,_,_ ), 0 , 4 , 0 , 9155 , 148, 87 ), // #558 + INST(Pmaxud , ExtRm , O(660F38,3F,_,_,_,_,_,_ ), 0 , 2 , 0 , 9163 , 11 , 12 ), // #559 + INST(Pmaxuw , ExtRm , O(660F38,3E,_,_,_,_,_,_ ), 0 , 2 , 0 , 9179 , 11 , 12 ), // #560 + INST(Pminsb , ExtRm , O(660F38,38,_,_,_,_,_,_ ), 0 , 2 , 0 , 9187 , 11 , 12 ), // #561 + INST(Pminsd , ExtRm , O(660F38,39,_,_,_,_,_,_ ), 0 , 2 , 0 , 9195 , 11 , 12 ), // #562 + INST(Pminsw , ExtRm_P , O(000F00,EA,_,_,_,_,_,_ ), 0 , 4 , 0 , 9211 , 148, 87 ), // #563 + INST(Pminub , ExtRm_P , O(000F00,DA,_,_,_,_,_,_ ), 0 , 4 , 0 , 9219 , 148, 87 ), // #564 + INST(Pminud , ExtRm , O(660F38,3B,_,_,_,_,_,_ ), 0 , 2 , 0 , 9227 , 11 , 12 ), // #565 + INST(Pminuw , ExtRm , O(660F38,3A,_,_,_,_,_,_ ), 0 , 2 , 0 , 9243 , 11 , 12 ), // #566 + INST(Pmovmskb , ExtRm_P , O(000F00,D7,_,_,_,_,_,_ ), 0 , 4 , 0 , 9321 , 163, 87 ), // #567 + INST(Pmovsxbd , ExtRm , O(660F38,21,_,_,_,_,_,_ ), 0 , 2 , 0 , 9418 , 7 , 12 ), // #568 + INST(Pmovsxbq , ExtRm , O(660F38,22,_,_,_,_,_,_ ), 0 , 2 , 0 , 9428 , 164, 12 ), // #569 + INST(Pmovsxbw , ExtRm , O(660F38,20,_,_,_,_,_,_ ), 0 , 2 , 0 , 9438 , 6 , 12 ), // #570 + INST(Pmovsxdq , ExtRm , O(660F38,25,_,_,_,_,_,_ ), 0 , 2 , 0 , 9448 , 6 , 12 ), // #571 + INST(Pmovsxwd , ExtRm , O(660F38,23,_,_,_,_,_,_ ), 0 , 2 , 0 , 9458 , 6 , 12 ), // #572 + INST(Pmovsxwq , ExtRm , O(660F38,24,_,_,_,_,_,_ ), 0 , 2 , 0 , 9468 , 7 , 12 ), // #573 + INST(Pmovzxbd , ExtRm , O(660F38,31,_,_,_,_,_,_ ), 0 , 2 , 0 , 9555 , 7 , 12 ), // #574 + INST(Pmovzxbq , ExtRm , O(660F38,32,_,_,_,_,_,_ ), 0 , 2 , 0 , 9565 , 164, 12 ), // #575 + INST(Pmovzxbw , ExtRm , O(660F38,30,_,_,_,_,_,_ ), 0 , 2 , 0 , 9575 , 6 , 12 ), // #576 + INST(Pmovzxdq , ExtRm , O(660F38,35,_,_,_,_,_,_ ), 0 , 2 , 0 , 9585 , 6 , 12 ), // #577 + INST(Pmovzxwd , ExtRm , O(660F38,33,_,_,_,_,_,_ ), 0 , 2 , 0 , 9595 , 6 , 12 ), // #578 + INST(Pmovzxwq , ExtRm , O(660F38,34,_,_,_,_,_,_ ), 0 , 2 , 0 , 9605 , 7 , 12 ), // #579 + INST(Pmuldq , ExtRm , O(660F38,28,_,_,_,_,_,_ ), 0 , 2 , 0 , 9615 , 5 , 12 ), // #580 + INST(Pmulhrsw , ExtRm_P , O(000F38,0B,_,_,_,_,_,_ ), 0 , 83 , 0 , 9623 , 146, 86 ), // #581 + INST(Pmulhrw , Ext3dNow , O(000F0F,B7,_,_,_,_,_,_ ), 0 , 87 , 0 , 2265 , 150, 51 ), // #582 + INST(Pmulhuw , ExtRm_P , O(000F00,E4,_,_,_,_,_,_ ), 0 , 4 , 0 , 9633 , 146, 87 ), // #583 + INST(Pmulhw , ExtRm_P , O(000F00,E5,_,_,_,_,_,_ ), 0 , 4 , 0 , 9642 , 146, 82 ), // #584 + INST(Pmulld , ExtRm , O(660F38,40,_,_,_,_,_,_ ), 0 , 2 , 0 , 9650 , 5 , 12 ), // #585 + INST(Pmullw , ExtRm_P , O(000F00,D5,_,_,_,_,_,_ ), 0 , 4 , 0 , 9666 , 146, 82 ), // #586 + INST(Pmuludq , ExtRm_P , O(000F00,F4,_,_,_,_,_,_ ), 0 , 4 , 0 , 9689 , 146, 4 ), // #587 + INST(Pop , X86Pop , O(000000,8F,0,_,_,_,_,_ ), O(000000,58,_,_,_,_,_,_ ), 0 , 67 , 2273 , 165, 0 ), // #588 INST(Popa , X86Op , O(660000,61,_,_,_,_,_,_ ), 0 , 19 , 0 , 2277 , 81 , 0 ), // #589 INST(Popad , X86Op , O(000000,61,_,_,_,_,_,_ ), 0 , 0 , 0 , 2282 , 81 , 0 ), // #590 INST(Popcnt , X86Rm_Raw66H , O(F30F00,B8,_,_,x,_,_,_ ), 0 , 6 , 0 , 2288 , 22 , 94 ), // #591 INST(Popf , X86Op , O(660000,9D,_,_,_,_,_,_ ), 0 , 19 , 0 , 2295 , 30 , 95 ), // #592 INST(Popfd , X86Op , O(000000,9D,_,_,_,_,_,_ ), 0 , 0 , 0 , 2300 , 81 , 95 ), // #593 INST(Popfq , X86Op , O(000000,9D,_,_,_,_,_,_ ), 0 , 0 , 0 , 2306 , 33 , 95 ), // #594 - INST(Por , ExtRm_P , O(000F00,EB,_,_,_,_,_,_ ), 0 , 4 , 0 , 8759 , 148, 82 ), // #595 + INST(Por , ExtRm_P , O(000F00,EB,_,_,_,_,_,_ ), 0 , 4 , 0 , 9734 , 148, 82 ), // #595 INST(Prefetch , X86M_Only , O(000F00,0D,0,_,_,_,_,_ ), 0 , 4 , 0 , 2312 , 31 , 51 ), // #596 INST(Prefetchnta , X86M_Only , O(000F00,18,0,_,_,_,_,_ ), 0 , 4 , 0 , 2321 , 31 , 77 ), // #597 INST(Prefetcht0 , X86M_Only , O(000F00,18,1,_,_,_,_,_ ), 0 , 29 , 0 , 2333 , 31 , 77 ), // #598 - INST(Prefetcht1 , X86M_Only , O(000F00,18,2,_,_,_,_,_ ), 0 , 77 , 0 , 2344 , 31 , 77 ), // #599 - INST(Prefetcht2 , X86M_Only , O(000F00,18,3,_,_,_,_,_ ), 0 , 79 , 0 , 2355 , 31 , 77 ), // #600 + INST(Prefetcht1 , X86M_Only , O(000F00,18,2,_,_,_,_,_ ), 0 , 76 , 0 , 2344 , 31 , 77 ), // #599 + INST(Prefetcht2 , X86M_Only , O(000F00,18,3,_,_,_,_,_ ), 0 , 78 , 0 , 2355 , 31 , 77 ), // #600 INST(Prefetchw , X86M_Only , O(000F00,0D,1,_,_,_,_,_ ), 0 , 29 , 0 , 2366 , 31 , 96 ), // #601 - INST(Prefetchwt1 , X86M_Only , O(000F00,0D,2,_,_,_,_,_ ), 0 , 77 , 0 , 2376 , 31 , 97 ), // #602 - INST(Psadbw , ExtRm_P , O(000F00,F6,_,_,_,_,_,_ ), 0 , 4 , 0 , 4272 , 146, 87 ), // #603 - INST(Pshufb , ExtRm_P , O(000F38,00,_,_,_,_,_,_ ), 0 , 84 , 0 , 9085 , 146, 86 ), // #604 - INST(Pshufd , ExtRmi , O(660F00,70,_,_,_,_,_,_ ), 0 , 3 , 0 , 9106 , 8 , 4 ), // #605 - INST(Pshufhw , ExtRmi , O(F30F00,70,_,_,_,_,_,_ ), 0 , 6 , 0 , 9114 , 8 , 4 ), // #606 - INST(Pshuflw , ExtRmi , O(F20F00,70,_,_,_,_,_,_ ), 0 , 5 , 0 , 9123 , 8 , 4 ), // #607 + INST(Prefetchwt1 , X86M_Only , O(000F00,0D,2,_,_,_,_,_ ), 0 , 76 , 0 , 2376 , 31 , 97 ), // #602 + INST(Psadbw , ExtRm_P , O(000F00,F6,_,_,_,_,_,_ ), 0 , 4 , 0 , 4644 , 146, 87 ), // #603 + INST(Pshufb , ExtRm_P , O(000F38,00,_,_,_,_,_,_ ), 0 , 83 , 0 , 10060, 146, 86 ), // #604 + INST(Pshufd , ExtRmi , O(660F00,70,_,_,_,_,_,_ ), 0 , 3 , 0 , 10081, 8 , 4 ), // #605 + INST(Pshufhw , ExtRmi , O(F30F00,70,_,_,_,_,_,_ ), 0 , 6 , 0 , 10089, 8 , 4 ), // #606 + INST(Pshuflw , ExtRmi , O(F20F00,70,_,_,_,_,_,_ ), 0 , 5 , 0 , 10098, 8 , 4 ), // #607 INST(Pshufw , ExtRmi_P , O(000F00,70,_,_,_,_,_,_ ), 0 , 4 , 0 , 2388 , 166, 77 ), // #608 - INST(Psignb , ExtRm_P , O(000F38,08,_,_,_,_,_,_ ), 0 , 84 , 0 , 9132 , 146, 86 ), // #609 - INST(Psignd , ExtRm_P , O(000F38,0A,_,_,_,_,_,_ ), 0 , 84 , 0 , 9140 , 146, 86 ), // #610 - INST(Psignw , ExtRm_P , O(000F38,09,_,_,_,_,_,_ ), 0 , 84 , 0 , 9148 , 146, 86 ), // #611 - INST(Pslld , ExtRmRi_P , O(000F00,F2,_,_,_,_,_,_ ), O(000F00,72,6,_,_,_,_,_ ), 4 , 69 , 9156 , 167, 82 ), // #612 - INST(Pslldq , ExtRmRi , 0 , O(660F00,73,7,_,_,_,_,_ ), 0 , 70 , 9163 , 168, 4 ), // #613 - INST(Psllq , ExtRmRi_P , O(000F00,F3,_,_,_,_,_,_ ), O(000F00,73,6,_,_,_,_,_ ), 4 , 71 , 9171 , 167, 82 ), // #614 - INST(Psllw , ExtRmRi_P , O(000F00,F1,_,_,_,_,_,_ ), O(000F00,71,6,_,_,_,_,_ ), 4 , 72 , 9202 , 167, 82 ), // #615 + INST(Psignb , ExtRm_P , O(000F38,08,_,_,_,_,_,_ ), 0 , 83 , 0 , 10107, 146, 86 ), // #609 + INST(Psignd , ExtRm_P , O(000F38,0A,_,_,_,_,_,_ ), 0 , 83 , 0 , 10115, 146, 86 ), // #610 + INST(Psignw , ExtRm_P , O(000F38,09,_,_,_,_,_,_ ), 0 , 83 , 0 , 10123, 146, 86 ), // #611 + INST(Pslld , ExtRmRi_P , O(000F00,F2,_,_,_,_,_,_ ), O(000F00,72,6,_,_,_,_,_ ), 4 , 68 , 10131, 167, 82 ), // #612 + INST(Pslldq , ExtRmRi , 0 , O(660F00,73,7,_,_,_,_,_ ), 0 , 69 , 10138, 168, 4 ), // #613 + INST(Psllq , ExtRmRi_P , O(000F00,F3,_,_,_,_,_,_ ), O(000F00,73,6,_,_,_,_,_ ), 4 , 70 , 10146, 167, 82 ), // #614 + INST(Psllw , ExtRmRi_P , O(000F00,F1,_,_,_,_,_,_ ), O(000F00,71,6,_,_,_,_,_ ), 4 , 71 , 10177, 167, 82 ), // #615 INST(Psmash , X86Op , O(F30F01,FF,_,_,_,_,_,_ ), 0 , 25 , 0 , 2395 , 33 , 98 ), // #616 - INST(Psrad , ExtRmRi_P , O(000F00,E2,_,_,_,_,_,_ ), O(000F00,72,4,_,_,_,_,_ ), 4 , 73 , 9209 , 167, 82 ), // #617 - INST(Psraw , ExtRmRi_P , O(000F00,E1,_,_,_,_,_,_ ), O(000F00,71,4,_,_,_,_,_ ), 4 , 74 , 9247 , 167, 82 ), // #618 - INST(Psrld , ExtRmRi_P , O(000F00,D2,_,_,_,_,_,_ ), O(000F00,72,2,_,_,_,_,_ ), 4 , 75 , 9254 , 167, 82 ), // #619 - INST(Psrldq , ExtRmRi , 0 , O(660F00,73,3,_,_,_,_,_ ), 0 , 76 , 9261 , 168, 4 ), // #620 - INST(Psrlq , ExtRmRi_P , O(000F00,D3,_,_,_,_,_,_ ), O(000F00,73,2,_,_,_,_,_ ), 4 , 77 , 9269 , 167, 82 ), // #621 - INST(Psrlw , ExtRmRi_P , O(000F00,D1,_,_,_,_,_,_ ), O(000F00,71,2,_,_,_,_,_ ), 4 , 78 , 9300 , 167, 82 ), // #622 - INST(Psubb , ExtRm_P , O(000F00,F8,_,_,_,_,_,_ ), 0 , 4 , 0 , 9307 , 149, 82 ), // #623 - INST(Psubd , ExtRm_P , O(000F00,FA,_,_,_,_,_,_ ), 0 , 4 , 0 , 9314 , 149, 82 ), // #624 - INST(Psubq , ExtRm_P , O(000F00,FB,_,_,_,_,_,_ ), 0 , 4 , 0 , 9321 , 149, 4 ), // #625 - INST(Psubsb , ExtRm_P , O(000F00,E8,_,_,_,_,_,_ ), 0 , 4 , 0 , 9328 , 149, 82 ), // #626 - INST(Psubsw , ExtRm_P , O(000F00,E9,_,_,_,_,_,_ ), 0 , 4 , 0 , 9336 , 149, 82 ), // #627 - INST(Psubusb , ExtRm_P , O(000F00,D8,_,_,_,_,_,_ ), 0 , 4 , 0 , 9344 , 149, 82 ), // #628 - INST(Psubusw , ExtRm_P , O(000F00,D9,_,_,_,_,_,_ ), 0 , 4 , 0 , 9353 , 149, 82 ), // #629 - INST(Psubw , ExtRm_P , O(000F00,F9,_,_,_,_,_,_ ), 0 , 4 , 0 , 9362 , 149, 82 ), // #630 - INST(Pswapd , Ext3dNow , O(000F0F,BB,_,_,_,_,_,_ ), 0 , 88 , 0 , 2402 , 150, 92 ), // #631 - INST(Ptest , ExtRm , O(660F38,17,_,_,_,_,_,_ ), 0 , 2 , 0 , 9391 , 5 , 99 ), // #632 - INST(Ptwrite , X86M , O(F30F00,AE,4,_,_,_,_,_ ), 0 , 92 , 0 , 2409 , 169, 100), // #633 - INST(Punpckhbw , ExtRm_P , O(000F00,68,_,_,_,_,_,_ ), 0 , 4 , 0 , 9474 , 146, 82 ), // #634 - INST(Punpckhdq , ExtRm_P , O(000F00,6A,_,_,_,_,_,_ ), 0 , 4 , 0 , 9485 , 146, 82 ), // #635 - INST(Punpckhqdq , ExtRm , O(660F00,6D,_,_,_,_,_,_ ), 0 , 3 , 0 , 9496 , 5 , 4 ), // #636 - INST(Punpckhwd , ExtRm_P , O(000F00,69,_,_,_,_,_,_ ), 0 , 4 , 0 , 9508 , 146, 82 ), // #637 - INST(Punpcklbw , ExtRm_P , O(000F00,60,_,_,_,_,_,_ ), 0 , 4 , 0 , 9519 , 170, 82 ), // #638 - INST(Punpckldq , ExtRm_P , O(000F00,62,_,_,_,_,_,_ ), 0 , 4 , 0 , 9530 , 170, 82 ), // #639 - INST(Punpcklqdq , ExtRm , O(660F00,6C,_,_,_,_,_,_ ), 0 , 3 , 0 , 9541 , 5 , 4 ), // #640 - INST(Punpcklwd , ExtRm_P , O(000F00,61,_,_,_,_,_,_ ), 0 , 4 , 0 , 9553 , 170, 82 ), // #641 - INST(Push , X86Push , O(000000,FF,6,_,_,_,_,_ ), O(000000,50,_,_,_,_,_,_ ), 32 , 79 , 2417 , 171, 0 ), // #642 + INST(Psrad , ExtRmRi_P , O(000F00,E2,_,_,_,_,_,_ ), O(000F00,72,4,_,_,_,_,_ ), 4 , 72 , 10184, 167, 82 ), // #617 + INST(Psraw , ExtRmRi_P , O(000F00,E1,_,_,_,_,_,_ ), O(000F00,71,4,_,_,_,_,_ ), 4 , 73 , 10222, 167, 82 ), // #618 + INST(Psrld , ExtRmRi_P , O(000F00,D2,_,_,_,_,_,_ ), O(000F00,72,2,_,_,_,_,_ ), 4 , 74 , 10229, 167, 82 ), // #619 + INST(Psrldq , ExtRmRi , 0 , O(660F00,73,3,_,_,_,_,_ ), 0 , 75 , 10236, 168, 4 ), // #620 + INST(Psrlq , ExtRmRi_P , O(000F00,D3,_,_,_,_,_,_ ), O(000F00,73,2,_,_,_,_,_ ), 4 , 76 , 10244, 167, 82 ), // #621 + INST(Psrlw , ExtRmRi_P , O(000F00,D1,_,_,_,_,_,_ ), O(000F00,71,2,_,_,_,_,_ ), 4 , 77 , 10275, 167, 82 ), // #622 + INST(Psubb , ExtRm_P , O(000F00,F8,_,_,_,_,_,_ ), 0 , 4 , 0 , 10282, 149, 82 ), // #623 + INST(Psubd , ExtRm_P , O(000F00,FA,_,_,_,_,_,_ ), 0 , 4 , 0 , 10289, 149, 82 ), // #624 + INST(Psubq , ExtRm_P , O(000F00,FB,_,_,_,_,_,_ ), 0 , 4 , 0 , 10296, 149, 4 ), // #625 + INST(Psubsb , ExtRm_P , O(000F00,E8,_,_,_,_,_,_ ), 0 , 4 , 0 , 10303, 149, 82 ), // #626 + INST(Psubsw , ExtRm_P , O(000F00,E9,_,_,_,_,_,_ ), 0 , 4 , 0 , 10311, 149, 82 ), // #627 + INST(Psubusb , ExtRm_P , O(000F00,D8,_,_,_,_,_,_ ), 0 , 4 , 0 , 10319, 149, 82 ), // #628 + INST(Psubusw , ExtRm_P , O(000F00,D9,_,_,_,_,_,_ ), 0 , 4 , 0 , 10328, 149, 82 ), // #629 + INST(Psubw , ExtRm_P , O(000F00,F9,_,_,_,_,_,_ ), 0 , 4 , 0 , 10337, 149, 82 ), // #630 + INST(Pswapd , Ext3dNow , O(000F0F,BB,_,_,_,_,_,_ ), 0 , 87 , 0 , 2402 , 150, 92 ), // #631 + INST(Ptest , ExtRm , O(660F38,17,_,_,_,_,_,_ ), 0 , 2 , 0 , 10366, 5 , 99 ), // #632 + INST(Ptwrite , X86M , O(F30F00,AE,4,_,_,_,_,_ ), 0 , 91 , 0 , 2409 , 169, 100), // #633 + INST(Punpckhbw , ExtRm_P , O(000F00,68,_,_,_,_,_,_ ), 0 , 4 , 0 , 10449, 146, 82 ), // #634 + INST(Punpckhdq , ExtRm_P , O(000F00,6A,_,_,_,_,_,_ ), 0 , 4 , 0 , 10460, 146, 82 ), // #635 + INST(Punpckhqdq , ExtRm , O(660F00,6D,_,_,_,_,_,_ ), 0 , 3 , 0 , 10471, 5 , 4 ), // #636 + INST(Punpckhwd , ExtRm_P , O(000F00,69,_,_,_,_,_,_ ), 0 , 4 , 0 , 10483, 146, 82 ), // #637 + INST(Punpcklbw , ExtRm_P , O(000F00,60,_,_,_,_,_,_ ), 0 , 4 , 0 , 10494, 170, 82 ), // #638 + INST(Punpckldq , ExtRm_P , O(000F00,62,_,_,_,_,_,_ ), 0 , 4 , 0 , 10505, 170, 82 ), // #639 + INST(Punpcklqdq , ExtRm , O(660F00,6C,_,_,_,_,_,_ ), 0 , 3 , 0 , 10516, 5 , 4 ), // #640 + INST(Punpcklwd , ExtRm_P , O(000F00,61,_,_,_,_,_,_ ), 0 , 4 , 0 , 10528, 170, 82 ), // #641 + INST(Push , X86Push , O(000000,FF,6,_,_,_,_,_ ), O(000000,50,_,_,_,_,_,_ ), 32 , 78 , 2417 , 171, 0 ), // #642 INST(Pusha , X86Op , O(660000,60,_,_,_,_,_,_ ), 0 , 19 , 0 , 2422 , 81 , 0 ), // #643 INST(Pushad , X86Op , O(000000,60,_,_,_,_,_,_ ), 0 , 0 , 0 , 2428 , 81 , 0 ), // #644 INST(Pushf , X86Op , O(660000,9C,_,_,_,_,_,_ ), 0 , 19 , 0 , 2435 , 30 , 101), // #645 INST(Pushfd , X86Op , O(000000,9C,_,_,_,_,_,_ ), 0 , 0 , 0 , 2441 , 81 , 101), // #646 INST(Pushfq , X86Op , O(000000,9C,_,_,_,_,_,_ ), 0 , 0 , 0 , 2448 , 33 , 101), // #647 - INST(Pvalidate , X86Op , O(F20F01,FF,_,_,_,_,_,_ ), 0 , 93 , 0 , 2455 , 30 , 102), // #648 - INST(Pxor , ExtRm_P , O(000F00,EF,_,_,_,_,_,_ ), 0 , 4 , 0 , 9564 , 149, 82 ), // #649 + INST(Pvalidate , X86Op , O(F20F01,FF,_,_,_,_,_,_ ), 0 , 92 , 0 , 2455 , 30 , 102), // #648 + INST(Pxor , ExtRm_P , O(000F00,EF,_,_,_,_,_,_ ), 0 , 4 , 0 , 10539, 149, 82 ), // #649 INST(Rcl , X86Rot , O(000000,D0,2,_,x,_,_,_ ), 0 , 1 , 0 , 2465 , 172, 103), // #650 - INST(Rcpps , ExtRm , O(000F00,53,_,_,_,_,_,_ ), 0 , 4 , 0 , 9692 , 5 , 5 ), // #651 - INST(Rcpss , ExtRm , O(F30F00,53,_,_,_,_,_,_ ), 0 , 6 , 0 , 9699 , 7 , 5 ), // #652 - INST(Rcr , X86Rot , O(000000,D0,3,_,x,_,_,_ ), 0 , 76 , 0 , 2469 , 172, 103), // #653 + INST(Rcpps , ExtRm , O(000F00,53,_,_,_,_,_,_ ), 0 , 4 , 0 , 10674, 5 , 5 ), // #651 + INST(Rcpss , ExtRm , O(F30F00,53,_,_,_,_,_,_ ), 0 , 6 , 0 , 10688, 7 , 5 ), // #652 + INST(Rcr , X86Rot , O(000000,D0,3,_,x,_,_,_ ), 0 , 75 , 0 , 2469 , 172, 103), // #653 INST(Rdfsbase , X86M , O(F30F00,AE,0,_,x,_,_,_ ), 0 , 6 , 0 , 2473 , 173, 104), // #654 - INST(Rdgsbase , X86M , O(F30F00,AE,1,_,x,_,_,_ ), 0 , 94 , 0 , 2482 , 173, 104), // #655 + INST(Rdgsbase , X86M , O(F30F00,AE,1,_,x,_,_,_ ), 0 , 93 , 0 , 2482 , 173, 104), // #655 INST(Rdmsr , X86Op , O(000F00,32,_,_,_,_,_,_ ), 0 , 4 , 0 , 2491 , 174, 105), // #656 - INST(Rdpid , X86R_Native , O(F30F00,C7,7,_,_,_,_,_ ), 0 , 95 , 0 , 2497 , 175, 106), // #657 + INST(Rdpid , X86R_Native , O(F30F00,C7,7,_,_,_,_,_ ), 0 , 94 , 0 , 2497 , 175, 106), // #657 INST(Rdpkru , X86Op , O(000F01,EE,_,_,_,_,_,_ ), 0 , 21 , 0 , 2503 , 174, 107), // #658 INST(Rdpmc , X86Op , O(000F00,33,_,_,_,_,_,_ ), 0 , 4 , 0 , 2510 , 174, 0 ), // #659 INST(Rdpru , X86Op , O(000F01,FD,_,_,_,_,_,_ ), 0 , 21 , 0 , 2516 , 174, 108), // #660 - INST(Rdrand , X86M , O(000F00,C7,6,_,x,_,_,_ ), 0 , 81 , 0 , 2522 , 23 , 109), // #661 + INST(Rdrand , X86M , O(000F00,C7,6,_,x,_,_,_ ), 0 , 80 , 0 , 2522 , 23 , 109), // #661 INST(Rdseed , X86M , O(000F00,C7,7,_,x,_,_,_ ), 0 , 22 , 0 , 2529 , 23 , 110), // #662 - INST(Rdsspd , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 94 , 0 , 2536 , 76 , 56 ), // #663 - INST(Rdsspq , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 94 , 0 , 2543 , 77 , 56 ), // #664 + INST(Rdsspd , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 93 , 0 , 2536 , 76 , 56 ), // #663 + INST(Rdsspq , X86M , O(F30F00,1E,1,_,_,_,_,_ ), 0 , 93 , 0 , 2543 , 77 , 56 ), // #664 INST(Rdtsc , X86Op , O(000F00,31,_,_,_,_,_,_ ), 0 , 4 , 0 , 2550 , 28 , 111), // #665 INST(Rdtscp , X86Op , O(000F01,F9,_,_,_,_,_,_ ), 0 , 21 , 0 , 2556 , 174, 112), // #666 INST(Ret , X86Ret , O(000000,C2,_,_,_,_,_,_ ), 0 , 0 , 0 , 3072 , 176, 0 ), // #667 INST(Retf , X86Ret , O(000000,CA,_,_,x,_,_,_ ), 0 , 0 , 0 , 2563 , 177, 0 ), // #668 INST(Rmpadjust , X86Op , O(F30F01,FE,_,_,_,_,_,_ ), 0 , 25 , 0 , 2568 , 33 , 98 ), // #669 - INST(Rmpupdate , X86Op , O(F20F01,FE,_,_,_,_,_,_ ), 0 , 93 , 0 , 2578 , 33 , 98 ), // #670 + INST(Rmpupdate , X86Op , O(F20F01,FE,_,_,_,_,_,_ ), 0 , 92 , 0 , 2578 , 33 , 98 ), // #670 INST(Rol , X86Rot , O(000000,D0,0,_,x,_,_,_ ), 0 , 0 , 0 , 2588 , 172, 113), // #671 INST(Ror , X86Rot , O(000000,D0,1,_,x,_,_,_ ), 0 , 31 , 0 , 2592 , 172, 113), // #672 - INST(Rorx , VexRmi_Wx , V(F20F3A,F0,_,0,x,_,_,_ ), 0 , 96 , 0 , 2596 , 178, 85 ), // #673 - INST(Roundpd , ExtRmi , O(660F3A,09,_,_,_,_,_,_ ), 0 , 8 , 0 , 9794 , 8 , 12 ), // #674 - INST(Roundps , ExtRmi , O(660F3A,08,_,_,_,_,_,_ ), 0 , 8 , 0 , 9803 , 8 , 12 ), // #675 - INST(Roundsd , ExtRmi , O(660F3A,0B,_,_,_,_,_,_ ), 0 , 8 , 0 , 9812 , 37 , 12 ), // #676 - INST(Roundss , ExtRmi , O(660F3A,0A,_,_,_,_,_,_ ), 0 , 8 , 0 , 9821 , 38 , 12 ), // #677 + INST(Rorx , VexRmi_Wx , V(F20F3A,F0,_,0,x,_,_,_ ), 0 , 95 , 0 , 2596 , 178, 85 ), // #673 + INST(Roundpd , ExtRmi , O(660F3A,09,_,_,_,_,_,_ ), 0 , 8 , 0 , 10827, 8 , 12 ), // #674 + INST(Roundps , ExtRmi , O(660F3A,08,_,_,_,_,_,_ ), 0 , 8 , 0 , 10836, 8 , 12 ), // #675 + INST(Roundsd , ExtRmi , O(660F3A,0B,_,_,_,_,_,_ ), 0 , 8 , 0 , 10845, 37 , 12 ), // #676 + INST(Roundss , ExtRmi , O(660F3A,0A,_,_,_,_,_,_ ), 0 , 8 , 0 , 10854, 38 , 12 ), // #677 INST(Rsm , X86Op , O(000F00,AA,_,_,_,_,_,_ ), 0 , 4 , 0 , 2601 , 81 , 1 ), // #678 - INST(Rsqrtps , ExtRm , O(000F00,52,_,_,_,_,_,_ ), 0 , 4 , 0 , 9918 , 5 , 5 ), // #679 - INST(Rsqrtss , ExtRm , O(F30F00,52,_,_,_,_,_,_ ), 0 , 6 , 0 , 9927 , 7 , 5 ), // #680 - INST(Rstorssp , X86M_Only , O(F30F00,01,5,_,_,_,_,_ ), 0 , 64 , 0 , 2605 , 32 , 24 ), // #681 + INST(Rsqrtps , ExtRm , O(000F00,52,_,_,_,_,_,_ ), 0 , 4 , 0 , 10960, 5 , 5 ), // #679 + INST(Rsqrtss , ExtRm , O(F30F00,52,_,_,_,_,_,_ ), 0 , 6 , 0 , 10978, 7 , 5 ), // #680 + INST(Rstorssp , X86M_Only , O(F30F00,01,5,_,_,_,_,_ ), 0 , 63 , 0 , 2605 , 32 , 24 ), // #681 INST(Sahf , X86Op , O(000000,9E,_,_,_,_,_,_ ), 0 , 0 , 0 , 2614 , 97 , 114), // #682 INST(Sal , X86Rot , O(000000,D0,4,_,x,_,_,_ ), 0 , 9 , 0 , 2619 , 172, 1 ), // #683 INST(Sar , X86Rot , O(000000,D0,7,_,x,_,_,_ ), 0 , 27 , 0 , 2623 , 172, 1 ), // #684 - INST(Sarx , VexRmv_Wx , V(F30F38,F7,_,0,x,_,_,_ ), 0 , 89 , 0 , 2627 , 13 , 85 ), // #685 + INST(Sarx , VexRmv_Wx , V(F30F38,F7,_,0,x,_,_,_ ), 0 , 88 , 0 , 2627 , 13 , 85 ), // #685 INST(Saveprevssp , X86Op , O(F30F01,EA,_,_,_,_,_,_ ), 0 , 25 , 0 , 2632 , 30 , 24 ), // #686 - INST(Sbb , X86Arith , O(000000,18,3,_,x,_,_,_ ), 0 , 76 , 0 , 2644 , 179, 2 ), // #687 + INST(Sbb , X86Arith , O(000000,18,3,_,x,_,_,_ ), 0 , 75 , 0 , 2644 , 179, 2 ), // #687 INST(Scas , X86StrRm , O(000000,AE,_,_,_,_,_,_ ), 0 , 0 , 0 , 2648 , 180, 37 ), // #688 INST(Senduipi , X86M_NoSize , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 24 , 0 , 2653 , 77 , 25 ), // #689 INST(Serialize , X86Op , O(000F01,E8,_,_,_,_,_,_ ), 0 , 21 , 0 , 2662 , 30 , 115), // #690 @@ -818,1086 +796,1199 @@ const InstDB::InstInfo InstDB::_instInfoTable[] = { INST(Setz , X86Set , O(000F00,94,_,_,_,_,_,_ ), 0 , 4 , 0 , 2850 , 181, 61 ), // #721 INST(Sfence , X86Fence , O(000F00,AE,7,_,_,_,_,_ ), 0 , 22 , 0 , 2855 , 30 , 77 ), // #722 INST(Sgdt , X86M_Only , O(000F00,01,0,_,_,_,_,_ ), 0 , 4 , 0 , 2862 , 69 , 0 ), // #723 - INST(Sha1msg1 , ExtRm , O(000F38,C9,_,_,_,_,_,_ ), 0 , 84 , 0 , 2867 , 5 , 116), // #724 - INST(Sha1msg2 , ExtRm , O(000F38,CA,_,_,_,_,_,_ ), 0 , 84 , 0 , 2876 , 5 , 116), // #725 - INST(Sha1nexte , ExtRm , O(000F38,C8,_,_,_,_,_,_ ), 0 , 84 , 0 , 2885 , 5 , 116), // #726 - INST(Sha1rnds4 , ExtRmi , O(000F3A,CC,_,_,_,_,_,_ ), 0 , 86 , 0 , 2895 , 8 , 116), // #727 - INST(Sha256msg1 , ExtRm , O(000F38,CC,_,_,_,_,_,_ ), 0 , 84 , 0 , 2905 , 5 , 116), // #728 - INST(Sha256msg2 , ExtRm , O(000F38,CD,_,_,_,_,_,_ ), 0 , 84 , 0 , 2916 , 5 , 116), // #729 - INST(Sha256rnds2 , ExtRm_XMM0 , O(000F38,CB,_,_,_,_,_,_ ), 0 , 84 , 0 , 2927 , 15 , 116), // #730 + INST(Sha1msg1 , ExtRm , O(000F38,C9,_,_,_,_,_,_ ), 0 , 83 , 0 , 2867 , 5 , 116), // #724 + INST(Sha1msg2 , ExtRm , O(000F38,CA,_,_,_,_,_,_ ), 0 , 83 , 0 , 2876 , 5 , 116), // #725 + INST(Sha1nexte , ExtRm , O(000F38,C8,_,_,_,_,_,_ ), 0 , 83 , 0 , 2885 , 5 , 116), // #726 + INST(Sha1rnds4 , ExtRmi , O(000F3A,CC,_,_,_,_,_,_ ), 0 , 85 , 0 , 2895 , 8 , 116), // #727 + INST(Sha256msg1 , ExtRm , O(000F38,CC,_,_,_,_,_,_ ), 0 , 83 , 0 , 2905 , 5 , 116), // #728 + INST(Sha256msg2 , ExtRm , O(000F38,CD,_,_,_,_,_,_ ), 0 , 83 , 0 , 2916 , 5 , 116), // #729 + INST(Sha256rnds2 , ExtRm_XMM0 , O(000F38,CB,_,_,_,_,_,_ ), 0 , 83 , 0 , 2927 , 15 , 116), // #730 INST(Shl , X86Rot , O(000000,D0,4,_,x,_,_,_ ), 0 , 9 , 0 , 2939 , 172, 1 ), // #731 - INST(Shld , X86ShldShrd , O(000F00,A4,_,_,x,_,_,_ ), 0 , 4 , 0 , 8963 , 182, 1 ), // #732 - INST(Shlx , VexRmv_Wx , V(660F38,F7,_,0,x,_,_,_ ), 0 , 97 , 0 , 2943 , 13 , 85 ), // #733 - INST(Shr , X86Rot , O(000000,D0,5,_,x,_,_,_ ), 0 , 63 , 0 , 2948 , 172, 1 ), // #734 + INST(Shld , X86ShldShrd , O(000F00,A4,_,_,x,_,_,_ ), 0 , 4 , 0 , 9938 , 182, 1 ), // #732 + INST(Shlx , VexRmv_Wx , V(660F38,F7,_,0,x,_,_,_ ), 0 , 96 , 0 , 2943 , 13 , 85 ), // #733 + INST(Shr , X86Rot , O(000000,D0,5,_,x,_,_,_ ), 0 , 62 , 0 , 2948 , 172, 1 ), // #734 INST(Shrd , X86ShldShrd , O(000F00,AC,_,_,x,_,_,_ ), 0 , 4 , 0 , 2952 , 182, 1 ), // #735 - INST(Shrx , VexRmv_Wx , V(F20F38,F7,_,0,x,_,_,_ ), 0 , 85 , 0 , 2957 , 13 , 85 ), // #736 - INST(Shufpd , ExtRmi , O(660F00,C6,_,_,_,_,_,_ ), 0 , 3 , 0 , 10188, 8 , 4 ), // #737 - INST(Shufps , ExtRmi , O(000F00,C6,_,_,_,_,_,_ ), 0 , 4 , 0 , 10196, 8 , 5 ), // #738 + INST(Shrx , VexRmv_Wx , V(F20F38,F7,_,0,x,_,_,_ ), 0 , 84 , 0 , 2957 , 13 , 85 ), // #736 + INST(Shufpd , ExtRmi , O(660F00,C6,_,_,_,_,_,_ ), 0 , 3 , 0 , 11259, 8 , 4 ), // #737 + INST(Shufps , ExtRmi , O(000F00,C6,_,_,_,_,_,_ ), 0 , 4 , 0 , 11267, 8 , 5 ), // #738 INST(Sidt , X86M_Only , O(000F00,01,1,_,_,_,_,_ ), 0 , 29 , 0 , 2962 , 69 , 0 ), // #739 INST(Skinit , X86Op_xAX , O(000F01,DE,_,_,_,_,_,_ ), 0 , 21 , 0 , 2967 , 52 , 117), // #740 INST(Sldt , X86M_NoMemSize , O(000F00,00,0,_,_,_,_,_ ), 0 , 4 , 0 , 2974 , 183, 0 ), // #741 INST(Slwpcb , VexR_Wx , V(XOP_M9,12,1,0,x,_,_,_ ), 0 , 11 , 0 , 2979 , 108, 74 ), // #742 - INST(Smsw , X86M_NoMemSize , O(000F00,01,4,_,_,_,_,_ ), 0 , 98 , 0 , 2986 , 183, 0 ), // #743 - INST(Sqrtpd , ExtRm , O(660F00,51,_,_,_,_,_,_ ), 0 , 3 , 0 , 10204, 5 , 4 ), // #744 - INST(Sqrtps , ExtRm , O(000F00,51,_,_,_,_,_,_ ), 0 , 4 , 0 , 9919 , 5 , 5 ), // #745 - INST(Sqrtsd , ExtRm , O(F20F00,51,_,_,_,_,_,_ ), 0 , 5 , 0 , 10220, 6 , 4 ), // #746 - INST(Sqrtss , ExtRm , O(F30F00,51,_,_,_,_,_,_ ), 0 , 6 , 0 , 9928 , 7 , 5 ), // #747 + INST(Smsw , X86M_NoMemSize , O(000F00,01,4,_,_,_,_,_ ), 0 , 97 , 0 , 2986 , 183, 0 ), // #743 + INST(Sqrtpd , ExtRm , O(660F00,51,_,_,_,_,_,_ ), 0 , 3 , 0 , 11275, 5 , 4 ), // #744 + INST(Sqrtps , ExtRm , O(000F00,51,_,_,_,_,_,_ ), 0 , 4 , 0 , 10961, 5 , 5 ), // #745 + INST(Sqrtsd , ExtRm , O(F20F00,51,_,_,_,_,_,_ ), 0 , 5 , 0 , 11299, 6 , 4 ), // #746 + INST(Sqrtss , ExtRm , O(F30F00,51,_,_,_,_,_,_ ), 0 , 6 , 0 , 10979, 7 , 5 ), // #747 INST(Stac , X86Op , O(000F01,CB,_,_,_,_,_,_ ), 0 , 21 , 0 , 2991 , 30 , 16 ), // #748 INST(Stc , X86Op , O(000000,F9,_,_,_,_,_,_ ), 0 , 0 , 0 , 2996 , 30 , 17 ), // #749 - INST(Std , X86Op , O(000000,FD,_,_,_,_,_,_ ), 0 , 0 , 0 , 6946 , 30 , 18 ), // #750 + INST(Std , X86Op , O(000000,FD,_,_,_,_,_,_ ), 0 , 0 , 0 , 7921 , 30 , 18 ), // #750 INST(Stgi , X86Op , O(000F01,DC,_,_,_,_,_,_ ), 0 , 21 , 0 , 3000 , 30 , 117), // #751 INST(Sti , X86Op , O(000000,FB,_,_,_,_,_,_ ), 0 , 0 , 0 , 3005 , 30 , 23 ), // #752 - INST(Stmxcsr , X86M_Only , O(000F00,AE,3,_,_,_,_,_ ), 0 , 79 , 0 , 10236, 101, 5 ), // #753 + INST(Stmxcsr , X86M_Only , O(000F00,AE,3,_,_,_,_,_ ), 0 , 78 , 0 , 11323, 101, 5 ), // #753 INST(Stos , X86StrMr , O(000000,AA,_,_,_,_,_,_ ), 0 , 0 , 0 , 3009 , 184, 75 ), // #754 INST(Str , X86M_NoMemSize , O(000F00,00,1,_,_,_,_,_ ), 0 , 29 , 0 , 3014 , 183, 0 ), // #755 - INST(Sttilecfg , AmxCfg , V(660F38,49,_,0,0,_,_,_ ), 0 , 97 , 0 , 3018 , 103, 73 ), // #756 + INST(Sttilecfg , AmxCfg , V(660F38,49,_,0,0,_,_,_ ), 0 , 96 , 0 , 3018 , 103, 73 ), // #756 INST(Stui , X86Op , O(F30F01,EF,_,_,_,_,_,_ ), 0 , 25 , 0 , 3135 , 33 , 25 ), // #757 - INST(Sub , X86Arith , O(000000,28,5,_,x,_,_,_ ), 0 , 63 , 0 , 866 , 179, 1 ), // #758 - INST(Subpd , ExtRm , O(660F00,5C,_,_,_,_,_,_ ), 0 , 3 , 0 , 4848 , 5 , 4 ), // #759 - INST(Subps , ExtRm , O(000F00,5C,_,_,_,_,_,_ ), 0 , 4 , 0 , 4860 , 5 , 5 ), // #760 - INST(Subsd , ExtRm , O(F20F00,5C,_,_,_,_,_,_ ), 0 , 5 , 0 , 5536 , 6 , 4 ), // #761 - INST(Subss , ExtRm , O(F30F00,5C,_,_,_,_,_,_ ), 0 , 6 , 0 , 5546 , 7 , 5 ), // #762 + INST(Sub , X86Arith , O(000000,28,5,_,x,_,_,_ ), 0 , 62 , 0 , 866 , 179, 1 ), // #758 + INST(Subpd , ExtRm , O(660F00,5C,_,_,_,_,_,_ ), 0 , 3 , 0 , 5413 , 5 , 4 ), // #759 + INST(Subps , ExtRm , O(000F00,5C,_,_,_,_,_,_ ), 0 , 4 , 0 , 5425 , 5 , 5 ), // #760 + INST(Subsd , ExtRm , O(F20F00,5C,_,_,_,_,_,_ ), 0 , 5 , 0 , 6392 , 6 , 4 ), // #761 + INST(Subss , ExtRm , O(F30F00,5C,_,_,_,_,_,_ ), 0 , 6 , 0 , 6402 , 7 , 5 ), // #762 INST(Swapgs , X86Op , O(000F01,F8,_,_,_,_,_,_ ), 0 , 21 , 0 , 3028 , 33 , 0 ), // #763 INST(Syscall , X86Op , O(000F00,05,_,_,_,_,_,_ ), 0 , 4 , 0 , 3035 , 33 , 0 ), // #764 INST(Sysenter , X86Op , O(000F00,34,_,_,_,_,_,_ ), 0 , 4 , 0 , 3043 , 30 , 0 ), // #765 INST(Sysexit , X86Op , O(000F00,35,_,_,_,_,_,_ ), 0 , 4 , 0 , 3052 , 30 , 0 ), // #766 - INST(Sysexitq , X86Op , O(000F00,35,_,_,1,_,_,_ ), 0 , 61 , 0 , 3060 , 30 , 0 ), // #767 + INST(Sysexitq , X86Op , O(000F00,35,_,_,1,_,_,_ ), 0 , 60 , 0 , 3060 , 30 , 0 ), // #767 INST(Sysret , X86Op , O(000F00,07,_,_,_,_,_,_ ), 0 , 4 , 0 , 3069 , 33 , 0 ), // #768 - INST(Sysretq , X86Op , O(000F00,07,_,_,1,_,_,_ ), 0 , 61 , 0 , 3076 , 33 , 0 ), // #769 - INST(T1mskc , VexVm_Wx , V(XOP_M9,01,7,0,x,_,_,_ ), 0 , 99 , 0 , 3084 , 14 , 11 ), // #770 - INST(Tdpbf16ps , AmxRmv , V(F30F38,5C,_,0,0,_,_,_ ), 0 , 89 , 0 , 3091 , 185, 118), // #771 - INST(Tdpbssd , AmxRmv , V(F20F38,5E,_,0,0,_,_,_ ), 0 , 85 , 0 , 3101 , 185, 119), // #772 - INST(Tdpbsud , AmxRmv , V(F30F38,5E,_,0,0,_,_,_ ), 0 , 89 , 0 , 3109 , 185, 119), // #773 - INST(Tdpbusd , AmxRmv , V(660F38,5E,_,0,0,_,_,_ ), 0 , 97 , 0 , 3117 , 185, 119), // #774 + INST(Sysretq , X86Op , O(000F00,07,_,_,1,_,_,_ ), 0 , 60 , 0 , 3076 , 33 , 0 ), // #769 + INST(T1mskc , VexVm_Wx , V(XOP_M9,01,7,0,x,_,_,_ ), 0 , 98 , 0 , 3084 , 14 , 11 ), // #770 + INST(Tdpbf16ps , AmxRmv , V(F30F38,5C,_,0,0,_,_,_ ), 0 , 88 , 0 , 3091 , 185, 118), // #771 + INST(Tdpbssd , AmxRmv , V(F20F38,5E,_,0,0,_,_,_ ), 0 , 84 , 0 , 3101 , 185, 119), // #772 + INST(Tdpbsud , AmxRmv , V(F30F38,5E,_,0,0,_,_,_ ), 0 , 88 , 0 , 3109 , 185, 119), // #773 + INST(Tdpbusd , AmxRmv , V(660F38,5E,_,0,0,_,_,_ ), 0 , 96 , 0 , 3117 , 185, 119), // #774 INST(Tdpbuud , AmxRmv , V(000F38,5E,_,0,0,_,_,_ ), 0 , 10 , 0 , 3125 , 185, 119), // #775 - INST(Test , X86Test , O(000000,84,_,_,x,_,_,_ ), O(000000,F6,_,_,x,_,_,_ ), 0 , 80 , 9392 , 186, 1 ), // #776 + INST(Test , X86Test , O(000000,84,_,_,x,_,_,_ ), O(000000,F6,_,_,x,_,_,_ ), 0 , 79 , 10367, 186, 1 ), // #776 INST(Testui , X86Op , O(F30F01,ED,_,_,_,_,_,_ ), 0 , 25 , 0 , 3133 , 33 , 120), // #777 - INST(Tileloadd , AmxRm , V(F20F38,4B,_,0,0,_,_,_ ), 0 , 85 , 0 , 3140 , 187, 73 ), // #778 - INST(Tileloaddt1 , AmxRm , V(660F38,4B,_,0,0,_,_,_ ), 0 , 97 , 0 , 3150 , 187, 73 ), // #779 + INST(Tileloadd , AmxRm , V(F20F38,4B,_,0,0,_,_,_ ), 0 , 84 , 0 , 3140 , 187, 73 ), // #778 + INST(Tileloaddt1 , AmxRm , V(660F38,4B,_,0,0,_,_,_ ), 0 , 96 , 0 , 3150 , 187, 73 ), // #779 INST(Tilerelease , VexOpMod , V(000F38,49,0,0,0,_,_,_ ), 0 , 10 , 0 , 3162 , 188, 73 ), // #780 - INST(Tilestored , AmxMr , V(F30F38,4B,_,0,0,_,_,_ ), 0 , 89 , 0 , 3174 , 189, 73 ), // #781 - INST(Tilezero , AmxR , V(F20F38,49,_,0,0,_,_,_ ), 0 , 85 , 0 , 3185 , 190, 73 ), // #782 + INST(Tilestored , AmxMr , V(F30F38,4B,_,0,0,_,_,_ ), 0 , 88 , 0 , 3174 , 189, 73 ), // #781 + INST(Tilezero , AmxR , V(F20F38,49,_,0,0,_,_,_ ), 0 , 84 , 0 , 3185 , 190, 73 ), // #782 INST(Tpause , X86R32_EDX_EAX , O(660F00,AE,6,_,_,_,_,_ ), 0 , 26 , 0 , 3194 , 191, 121), // #783 INST(Tzcnt , X86Rm_Raw66H , O(F30F00,BC,_,_,x,_,_,_ ), 0 , 6 , 0 , 3201 , 22 , 9 ), // #784 - INST(Tzmsk , VexVm_Wx , V(XOP_M9,01,4,0,x,_,_,_ ), 0 , 100, 0 , 3207 , 14 , 11 ), // #785 - INST(Ucomisd , ExtRm , O(660F00,2E,_,_,_,_,_,_ ), 0 , 3 , 0 , 10289, 6 , 41 ), // #786 - INST(Ucomiss , ExtRm , O(000F00,2E,_,_,_,_,_,_ ), 0 , 4 , 0 , 10298, 7 , 42 ), // #787 + INST(Tzmsk , VexVm_Wx , V(XOP_M9,01,4,0,x,_,_,_ ), 0 , 99 , 0 , 3207 , 14 , 11 ), // #785 + INST(Ucomisd , ExtRm , O(660F00,2E,_,_,_,_,_,_ ), 0 , 3 , 0 , 11390, 6 , 41 ), // #786 + INST(Ucomiss , ExtRm , O(000F00,2E,_,_,_,_,_,_ ), 0 , 4 , 0 , 11408, 7 , 42 ), // #787 INST(Ud0 , X86Rm , O(000F00,FF,_,_,_,_,_,_ ), 0 , 4 , 0 , 3213 , 192, 0 ), // #788 INST(Ud1 , X86Rm , O(000F00,B9,_,_,_,_,_,_ ), 0 , 4 , 0 , 3217 , 192, 0 ), // #789 INST(Ud2 , X86Op , O(000F00,0B,_,_,_,_,_,_ ), 0 , 4 , 0 , 3221 , 30 , 0 ), // #790 INST(Uiret , X86Op , O(F30F01,EC,_,_,_,_,_,_ ), 0 , 25 , 0 , 3225 , 33 , 25 ), // #791 INST(Umonitor , X86R_FromM , O(F30F00,AE,6,_,_,_,_,_ ), 0 , 24 , 0 , 3231 , 193, 122), // #792 - INST(Umwait , X86R32_EDX_EAX , O(F20F00,AE,6,_,_,_,_,_ ), 0 , 101, 0 , 3240 , 191, 121), // #793 - INST(Unpckhpd , ExtRm , O(660F00,15,_,_,_,_,_,_ ), 0 , 3 , 0 , 10307, 5 , 4 ), // #794 - INST(Unpckhps , ExtRm , O(000F00,15,_,_,_,_,_,_ ), 0 , 4 , 0 , 10317, 5 , 5 ), // #795 - INST(Unpcklpd , ExtRm , O(660F00,14,_,_,_,_,_,_ ), 0 , 3 , 0 , 10327, 5 , 4 ), // #796 - INST(Unpcklps , ExtRm , O(000F00,14,_,_,_,_,_,_ ), 0 , 4 , 0 , 10337, 5 , 5 ), // #797 - INST(V4fmaddps , VexRm_T1_4X , E(F20F38,9A,_,2,_,0,4,T4X), 0 , 102, 0 , 3247 , 194, 123), // #798 - INST(V4fmaddss , VexRm_T1_4X , E(F20F38,9B,_,0,_,0,4,T4X), 0 , 103, 0 , 3257 , 195, 123), // #799 - INST(V4fnmaddps , VexRm_T1_4X , E(F20F38,AA,_,2,_,0,4,T4X), 0 , 102, 0 , 3267 , 194, 123), // #800 - INST(V4fnmaddss , VexRm_T1_4X , E(F20F38,AB,_,0,_,0,4,T4X), 0 , 103, 0 , 3278 , 195, 123), // #801 - INST(Vaddpd , VexRvm_Lx , V(660F00,58,_,x,I,1,4,FV ), 0 , 104, 0 , 3289 , 196, 124), // #802 - INST(Vaddps , VexRvm_Lx , V(000F00,58,_,x,I,0,4,FV ), 0 , 105, 0 , 3296 , 197, 124), // #803 - INST(Vaddsd , VexRvm , V(F20F00,58,_,I,I,1,3,T1S), 0 , 106, 0 , 3303 , 198, 125), // #804 - INST(Vaddss , VexRvm , V(F30F00,58,_,I,I,0,2,T1S), 0 , 107, 0 , 3310 , 199, 125), // #805 - INST(Vaddsubpd , VexRvm_Lx , V(660F00,D0,_,x,I,_,_,_ ), 0 , 70 , 0 , 3317 , 200, 126), // #806 - INST(Vaddsubps , VexRvm_Lx , V(F20F00,D0,_,x,I,_,_,_ ), 0 , 108, 0 , 3327 , 200, 126), // #807 - INST(Vaesdec , VexRvm_Lx , V(660F38,DE,_,x,I,_,4,FVM), 0 , 109, 0 , 3337 , 201, 127), // #808 - INST(Vaesdeclast , VexRvm_Lx , V(660F38,DF,_,x,I,_,4,FVM), 0 , 109, 0 , 3345 , 201, 127), // #809 - INST(Vaesenc , VexRvm_Lx , V(660F38,DC,_,x,I,_,4,FVM), 0 , 109, 0 , 3357 , 201, 127), // #810 - INST(Vaesenclast , VexRvm_Lx , V(660F38,DD,_,x,I,_,4,FVM), 0 , 109, 0 , 3365 , 201, 127), // #811 - INST(Vaesimc , VexRm , V(660F38,DB,_,0,I,_,_,_ ), 0 , 97 , 0 , 3377 , 202, 128), // #812 - INST(Vaeskeygenassist , VexRmi , V(660F3A,DF,_,0,I,_,_,_ ), 0 , 74 , 0 , 3385 , 203, 128), // #813 - INST(Valignd , VexRvmi_Lx , E(660F3A,03,_,x,_,0,4,FV ), 0 , 110, 0 , 3402 , 204, 129), // #814 - INST(Valignq , VexRvmi_Lx , E(660F3A,03,_,x,_,1,4,FV ), 0 , 111, 0 , 3410 , 205, 129), // #815 - INST(Vandnpd , VexRvm_Lx , V(660F00,55,_,x,I,1,4,FV ), 0 , 104, 0 , 3418 , 206, 130), // #816 - INST(Vandnps , VexRvm_Lx , V(000F00,55,_,x,I,0,4,FV ), 0 , 105, 0 , 3426 , 207, 130), // #817 - INST(Vandpd , VexRvm_Lx , V(660F00,54,_,x,I,1,4,FV ), 0 , 104, 0 , 3434 , 208, 130), // #818 - INST(Vandps , VexRvm_Lx , V(000F00,54,_,x,I,0,4,FV ), 0 , 105, 0 , 3441 , 209, 130), // #819 - INST(Vblendmpd , VexRvm_Lx , E(660F38,65,_,x,_,1,4,FV ), 0 , 112, 0 , 3448 , 210, 129), // #820 - INST(Vblendmps , VexRvm_Lx , E(660F38,65,_,x,_,0,4,FV ), 0 , 113, 0 , 3458 , 211, 129), // #821 - INST(Vblendpd , VexRvmi_Lx , V(660F3A,0D,_,x,I,_,_,_ ), 0 , 74 , 0 , 3468 , 212, 126), // #822 - INST(Vblendps , VexRvmi_Lx , V(660F3A,0C,_,x,I,_,_,_ ), 0 , 74 , 0 , 3477 , 212, 126), // #823 - INST(Vblendvpd , VexRvmr_Lx , V(660F3A,4B,_,x,0,_,_,_ ), 0 , 74 , 0 , 3486 , 213, 126), // #824 - INST(Vblendvps , VexRvmr_Lx , V(660F3A,4A,_,x,0,_,_,_ ), 0 , 74 , 0 , 3496 , 213, 126), // #825 - INST(Vbroadcastf128 , VexRm , V(660F38,1A,_,1,0,_,_,_ ), 0 , 114, 0 , 3506 , 214, 126), // #826 - INST(Vbroadcastf32x2 , VexRm_Lx , E(660F38,19,_,x,_,0,3,T2 ), 0 , 115, 0 , 3521 , 215, 131), // #827 - INST(Vbroadcastf32x4 , VexRm_Lx , E(660F38,1A,_,x,_,0,4,T4 ), 0 , 116, 0 , 3537 , 216, 68 ), // #828 - INST(Vbroadcastf32x8 , VexRm , E(660F38,1B,_,2,_,0,5,T8 ), 0 , 117, 0 , 3553 , 217, 66 ), // #829 - INST(Vbroadcastf64x2 , VexRm_Lx , E(660F38,1A,_,x,_,1,4,T2 ), 0 , 118, 0 , 3569 , 216, 131), // #830 - INST(Vbroadcastf64x4 , VexRm , E(660F38,1B,_,2,_,1,5,T4 ), 0 , 119, 0 , 3585 , 217, 68 ), // #831 - INST(Vbroadcasti128 , VexRm , V(660F38,5A,_,1,0,_,_,_ ), 0 , 114, 0 , 3601 , 214, 132), // #832 - INST(Vbroadcasti32x2 , VexRm_Lx , E(660F38,59,_,x,_,0,3,T2 ), 0 , 115, 0 , 3616 , 218, 131), // #833 - INST(Vbroadcasti32x4 , VexRm_Lx , E(660F38,5A,_,x,_,0,4,T4 ), 0 , 116, 0 , 3632 , 216, 129), // #834 - INST(Vbroadcasti32x8 , VexRm , E(660F38,5B,_,2,_,0,5,T8 ), 0 , 117, 0 , 3648 , 217, 66 ), // #835 - INST(Vbroadcasti64x2 , VexRm_Lx , E(660F38,5A,_,x,_,1,4,T2 ), 0 , 118, 0 , 3664 , 216, 131), // #836 - INST(Vbroadcasti64x4 , VexRm , E(660F38,5B,_,2,_,1,5,T4 ), 0 , 119, 0 , 3680 , 217, 68 ), // #837 - INST(Vbroadcastsd , VexRm_Lx , V(660F38,19,_,x,0,1,3,T1S), 0 , 120, 0 , 3696 , 219, 133), // #838 - INST(Vbroadcastss , VexRm_Lx , V(660F38,18,_,x,0,0,2,T1S), 0 , 121, 0 , 3709 , 220, 133), // #839 - INST(Vcmppd , VexRvmi_Lx_KEvex , V(660F00,C2,_,x,I,1,4,FV ), 0 , 104, 0 , 3722 , 221, 124), // #840 - INST(Vcmpps , VexRvmi_Lx_KEvex , V(000F00,C2,_,x,I,0,4,FV ), 0 , 105, 0 , 3729 , 222, 124), // #841 - INST(Vcmpsd , VexRvmi_KEvex , V(F20F00,C2,_,I,I,1,3,T1S), 0 , 106, 0 , 3736 , 223, 125), // #842 - INST(Vcmpss , VexRvmi_KEvex , V(F30F00,C2,_,I,I,0,2,T1S), 0 , 107, 0 , 3743 , 224, 125), // #843 - INST(Vcomisd , VexRm , V(660F00,2F,_,I,I,1,3,T1S), 0 , 122, 0 , 3750 , 225, 134), // #844 - INST(Vcomiss , VexRm , V(000F00,2F,_,I,I,0,2,T1S), 0 , 123, 0 , 3758 , 226, 134), // #845 - INST(Vcompresspd , VexMr_Lx , E(660F38,8A,_,x,_,1,3,T1S), 0 , 124, 0 , 3766 , 227, 129), // #846 - INST(Vcompressps , VexMr_Lx , E(660F38,8A,_,x,_,0,2,T1S), 0 , 125, 0 , 3778 , 227, 129), // #847 - INST(Vcvtdq2pd , VexRm_Lx , V(F30F00,E6,_,x,I,0,3,HV ), 0 , 126, 0 , 3790 , 228, 124), // #848 - INST(Vcvtdq2ps , VexRm_Lx , V(000F00,5B,_,x,I,0,4,FV ), 0 , 105, 0 , 3800 , 229, 124), // #849 - INST(Vcvtne2ps2bf16 , VexRvm_Lx , E(F20F38,72,_,_,_,0,4,FV ), 0 , 127, 0 , 3810 , 211, 135), // #850 - INST(Vcvtneps2bf16 , VexRm_Lx_Narrow , E(F30F38,72,_,_,_,0,4,FV ), 0 , 128, 0 , 3825 , 230, 135), // #851 - INST(Vcvtpd2dq , VexRm_Lx_Narrow , V(F20F00,E6,_,x,I,1,4,FV ), 0 , 129, 0 , 3839 , 231, 124), // #852 - INST(Vcvtpd2ps , VexRm_Lx_Narrow , V(660F00,5A,_,x,I,1,4,FV ), 0 , 104, 0 , 3849 , 231, 124), // #853 - INST(Vcvtpd2qq , VexRm_Lx , E(660F00,7B,_,x,_,1,4,FV ), 0 , 130, 0 , 3859 , 232, 131), // #854 - INST(Vcvtpd2udq , VexRm_Lx_Narrow , E(000F00,79,_,x,_,1,4,FV ), 0 , 131, 0 , 3869 , 233, 129), // #855 - INST(Vcvtpd2uqq , VexRm_Lx , E(660F00,79,_,x,_,1,4,FV ), 0 , 130, 0 , 3880 , 232, 131), // #856 - INST(Vcvtph2ps , VexRm_Lx , V(660F38,13,_,x,0,0,3,HVM), 0 , 132, 0 , 3891 , 234, 136), // #857 - INST(Vcvtps2dq , VexRm_Lx , V(660F00,5B,_,x,I,0,4,FV ), 0 , 133, 0 , 3901 , 229, 124), // #858 - INST(Vcvtps2pd , VexRm_Lx , V(000F00,5A,_,x,I,0,3,HV ), 0 , 134, 0 , 3911 , 235, 124), // #859 - INST(Vcvtps2ph , VexMri_Lx , V(660F3A,1D,_,x,0,0,3,HVM), 0 , 135, 0 , 3921 , 236, 136), // #860 - INST(Vcvtps2qq , VexRm_Lx , E(660F00,7B,_,x,_,0,3,HV ), 0 , 136, 0 , 3931 , 237, 131), // #861 - INST(Vcvtps2udq , VexRm_Lx , E(000F00,79,_,x,_,0,4,FV ), 0 , 137, 0 , 3941 , 238, 129), // #862 - INST(Vcvtps2uqq , VexRm_Lx , E(660F00,79,_,x,_,0,3,HV ), 0 , 136, 0 , 3952 , 237, 131), // #863 - INST(Vcvtqq2pd , VexRm_Lx , E(F30F00,E6,_,x,_,1,4,FV ), 0 , 138, 0 , 3963 , 232, 131), // #864 - INST(Vcvtqq2ps , VexRm_Lx_Narrow , E(000F00,5B,_,x,_,1,4,FV ), 0 , 131, 0 , 3973 , 233, 131), // #865 - INST(Vcvtsd2si , VexRm_Wx , V(F20F00,2D,_,I,x,x,3,T1F), 0 , 139, 0 , 3983 , 239, 125), // #866 - INST(Vcvtsd2ss , VexRvm , V(F20F00,5A,_,I,I,1,3,T1S), 0 , 106, 0 , 3993 , 198, 125), // #867 - INST(Vcvtsd2usi , VexRm_Wx , E(F20F00,79,_,I,_,x,3,T1F), 0 , 140, 0 , 4003 , 240, 68 ), // #868 - INST(Vcvtsi2sd , VexRvm_Wx , V(F20F00,2A,_,I,x,x,2,T1W), 0 , 141, 0 , 4014 , 241, 125), // #869 - INST(Vcvtsi2ss , VexRvm_Wx , V(F30F00,2A,_,I,x,x,2,T1W), 0 , 142, 0 , 4024 , 241, 125), // #870 - INST(Vcvtss2sd , VexRvm , V(F30F00,5A,_,I,I,0,2,T1S), 0 , 107, 0 , 4034 , 242, 125), // #871 - INST(Vcvtss2si , VexRm_Wx , V(F30F00,2D,_,I,x,x,2,T1F), 0 , 143, 0 , 4044 , 243, 125), // #872 - INST(Vcvtss2usi , VexRm_Wx , E(F30F00,79,_,I,_,x,2,T1F), 0 , 144, 0 , 4054 , 244, 68 ), // #873 - INST(Vcvttpd2dq , VexRm_Lx_Narrow , V(660F00,E6,_,x,I,1,4,FV ), 0 , 104, 0 , 4065 , 245, 124), // #874 - INST(Vcvttpd2qq , VexRm_Lx , E(660F00,7A,_,x,_,1,4,FV ), 0 , 130, 0 , 4076 , 246, 129), // #875 - INST(Vcvttpd2udq , VexRm_Lx_Narrow , E(000F00,78,_,x,_,1,4,FV ), 0 , 131, 0 , 4087 , 247, 129), // #876 - INST(Vcvttpd2uqq , VexRm_Lx , E(660F00,78,_,x,_,1,4,FV ), 0 , 130, 0 , 4099 , 246, 131), // #877 - INST(Vcvttps2dq , VexRm_Lx , V(F30F00,5B,_,x,I,0,4,FV ), 0 , 145, 0 , 4111 , 248, 124), // #878 - INST(Vcvttps2qq , VexRm_Lx , E(660F00,7A,_,x,_,0,3,HV ), 0 , 136, 0 , 4122 , 249, 131), // #879 - INST(Vcvttps2udq , VexRm_Lx , E(000F00,78,_,x,_,0,4,FV ), 0 , 137, 0 , 4133 , 250, 129), // #880 - INST(Vcvttps2uqq , VexRm_Lx , E(660F00,78,_,x,_,0,3,HV ), 0 , 136, 0 , 4145 , 249, 131), // #881 - INST(Vcvttsd2si , VexRm_Wx , V(F20F00,2C,_,I,x,x,3,T1F), 0 , 139, 0 , 4157 , 251, 125), // #882 - INST(Vcvttsd2usi , VexRm_Wx , E(F20F00,78,_,I,_,x,3,T1F), 0 , 140, 0 , 4168 , 252, 68 ), // #883 - INST(Vcvttss2si , VexRm_Wx , V(F30F00,2C,_,I,x,x,2,T1F), 0 , 143, 0 , 4180 , 253, 125), // #884 - INST(Vcvttss2usi , VexRm_Wx , E(F30F00,78,_,I,_,x,2,T1F), 0 , 144, 0 , 4191 , 254, 68 ), // #885 - INST(Vcvtudq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,0,3,HV ), 0 , 146, 0 , 4203 , 255, 129), // #886 - INST(Vcvtudq2ps , VexRm_Lx , E(F20F00,7A,_,x,_,0,4,FV ), 0 , 147, 0 , 4214 , 238, 129), // #887 - INST(Vcvtuqq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,1,4,FV ), 0 , 138, 0 , 4225 , 232, 131), // #888 - INST(Vcvtuqq2ps , VexRm_Lx_Narrow , E(F20F00,7A,_,x,_,1,4,FV ), 0 , 148, 0 , 4236 , 233, 131), // #889 - INST(Vcvtusi2sd , VexRvm_Wx , E(F20F00,7B,_,I,_,x,2,T1W), 0 , 149, 0 , 4247 , 256, 68 ), // #890 - INST(Vcvtusi2ss , VexRvm_Wx , E(F30F00,7B,_,I,_,x,2,T1W), 0 , 150, 0 , 4258 , 256, 68 ), // #891 - INST(Vdbpsadbw , VexRvmi_Lx , E(660F3A,42,_,x,_,0,4,FVM), 0 , 151, 0 , 4269 , 257, 137), // #892 - INST(Vdivpd , VexRvm_Lx , V(660F00,5E,_,x,I,1,4,FV ), 0 , 104, 0 , 4279 , 196, 124), // #893 - INST(Vdivps , VexRvm_Lx , V(000F00,5E,_,x,I,0,4,FV ), 0 , 105, 0 , 4286 , 197, 124), // #894 - INST(Vdivsd , VexRvm , V(F20F00,5E,_,I,I,1,3,T1S), 0 , 106, 0 , 4293 , 198, 125), // #895 - INST(Vdivss , VexRvm , V(F30F00,5E,_,I,I,0,2,T1S), 0 , 107, 0 , 4300 , 199, 125), // #896 - INST(Vdpbf16ps , VexRvm_Lx , E(F30F38,52,_,_,_,0,4,FV ), 0 , 128, 0 , 4307 , 211, 135), // #897 - INST(Vdppd , VexRvmi_Lx , V(660F3A,41,_,x,I,_,_,_ ), 0 , 74 , 0 , 4317 , 258, 126), // #898 - INST(Vdpps , VexRvmi_Lx , V(660F3A,40,_,x,I,_,_,_ ), 0 , 74 , 0 , 4323 , 212, 126), // #899 - INST(Verr , X86M_NoSize , O(000F00,00,4,_,_,_,_,_ ), 0 , 98 , 0 , 4329 , 107, 10 ), // #900 - INST(Verw , X86M_NoSize , O(000F00,00,5,_,_,_,_,_ ), 0 , 78 , 0 , 4334 , 107, 10 ), // #901 - INST(Vexp2pd , VexRm , E(660F38,C8,_,2,_,1,4,FV ), 0 , 152, 0 , 4339 , 259, 138), // #902 - INST(Vexp2ps , VexRm , E(660F38,C8,_,2,_,0,4,FV ), 0 , 153, 0 , 4347 , 260, 138), // #903 - INST(Vexpandpd , VexRm_Lx , E(660F38,88,_,x,_,1,3,T1S), 0 , 124, 0 , 4355 , 261, 129), // #904 - INST(Vexpandps , VexRm_Lx , E(660F38,88,_,x,_,0,2,T1S), 0 , 125, 0 , 4365 , 261, 129), // #905 - INST(Vextractf128 , VexMri , V(660F3A,19,_,1,0,_,_,_ ), 0 , 154, 0 , 4375 , 262, 126), // #906 - INST(Vextractf32x4 , VexMri_Lx , E(660F3A,19,_,x,_,0,4,T4 ), 0 , 155, 0 , 4388 , 263, 129), // #907 - INST(Vextractf32x8 , VexMri , E(660F3A,1B,_,2,_,0,5,T8 ), 0 , 156, 0 , 4402 , 264, 66 ), // #908 - INST(Vextractf64x2 , VexMri_Lx , E(660F3A,19,_,x,_,1,4,T2 ), 0 , 157, 0 , 4416 , 263, 131), // #909 - INST(Vextractf64x4 , VexMri , E(660F3A,1B,_,2,_,1,5,T4 ), 0 , 158, 0 , 4430 , 264, 68 ), // #910 - INST(Vextracti128 , VexMri , V(660F3A,39,_,1,0,_,_,_ ), 0 , 154, 0 , 4444 , 262, 132), // #911 - INST(Vextracti32x4 , VexMri_Lx , E(660F3A,39,_,x,_,0,4,T4 ), 0 , 155, 0 , 4457 , 263, 129), // #912 - INST(Vextracti32x8 , VexMri , E(660F3A,3B,_,2,_,0,5,T8 ), 0 , 156, 0 , 4471 , 264, 66 ), // #913 - INST(Vextracti64x2 , VexMri_Lx , E(660F3A,39,_,x,_,1,4,T2 ), 0 , 157, 0 , 4485 , 263, 131), // #914 - INST(Vextracti64x4 , VexMri , E(660F3A,3B,_,2,_,1,5,T4 ), 0 , 158, 0 , 4499 , 264, 68 ), // #915 - INST(Vextractps , VexMri , V(660F3A,17,_,0,I,I,2,T1S), 0 , 159, 0 , 4513 , 265, 125), // #916 - INST(Vfixupimmpd , VexRvmi_Lx , E(660F3A,54,_,x,_,1,4,FV ), 0 , 111, 0 , 4524 , 266, 129), // #917 - INST(Vfixupimmps , VexRvmi_Lx , E(660F3A,54,_,x,_,0,4,FV ), 0 , 110, 0 , 4536 , 267, 129), // #918 - INST(Vfixupimmsd , VexRvmi , E(660F3A,55,_,I,_,1,3,T1S), 0 , 160, 0 , 4548 , 268, 68 ), // #919 - INST(Vfixupimmss , VexRvmi , E(660F3A,55,_,I,_,0,2,T1S), 0 , 161, 0 , 4560 , 269, 68 ), // #920 - INST(Vfmadd132pd , VexRvm_Lx , V(660F38,98,_,x,1,1,4,FV ), 0 , 162, 0 , 4572 , 196, 139), // #921 - INST(Vfmadd132ps , VexRvm_Lx , V(660F38,98,_,x,0,0,4,FV ), 0 , 163, 0 , 4584 , 197, 139), // #922 - INST(Vfmadd132sd , VexRvm , V(660F38,99,_,I,1,1,3,T1S), 0 , 164, 0 , 4596 , 198, 140), // #923 - INST(Vfmadd132ss , VexRvm , V(660F38,99,_,I,0,0,2,T1S), 0 , 121, 0 , 4608 , 199, 140), // #924 - INST(Vfmadd213pd , VexRvm_Lx , V(660F38,A8,_,x,1,1,4,FV ), 0 , 162, 0 , 4620 , 196, 139), // #925 - INST(Vfmadd213ps , VexRvm_Lx , V(660F38,A8,_,x,0,0,4,FV ), 0 , 163, 0 , 4632 , 197, 139), // #926 - INST(Vfmadd213sd , VexRvm , V(660F38,A9,_,I,1,1,3,T1S), 0 , 164, 0 , 4644 , 198, 140), // #927 - INST(Vfmadd213ss , VexRvm , V(660F38,A9,_,I,0,0,2,T1S), 0 , 121, 0 , 4656 , 199, 140), // #928 - INST(Vfmadd231pd , VexRvm_Lx , V(660F38,B8,_,x,1,1,4,FV ), 0 , 162, 0 , 4668 , 196, 139), // #929 - INST(Vfmadd231ps , VexRvm_Lx , V(660F38,B8,_,x,0,0,4,FV ), 0 , 163, 0 , 4680 , 197, 139), // #930 - INST(Vfmadd231sd , VexRvm , V(660F38,B9,_,I,1,1,3,T1S), 0 , 164, 0 , 4692 , 198, 140), // #931 - INST(Vfmadd231ss , VexRvm , V(660F38,B9,_,I,0,0,2,T1S), 0 , 121, 0 , 4704 , 199, 140), // #932 - INST(Vfmaddpd , Fma4_Lx , V(660F3A,69,_,x,x,_,_,_ ), 0 , 74 , 0 , 4716 , 270, 141), // #933 - INST(Vfmaddps , Fma4_Lx , V(660F3A,68,_,x,x,_,_,_ ), 0 , 74 , 0 , 4725 , 270, 141), // #934 - INST(Vfmaddsd , Fma4 , V(660F3A,6B,_,0,x,_,_,_ ), 0 , 74 , 0 , 4734 , 271, 141), // #935 - INST(Vfmaddss , Fma4 , V(660F3A,6A,_,0,x,_,_,_ ), 0 , 74 , 0 , 4743 , 272, 141), // #936 - INST(Vfmaddsub132pd , VexRvm_Lx , V(660F38,96,_,x,1,1,4,FV ), 0 , 162, 0 , 4752 , 196, 139), // #937 - INST(Vfmaddsub132ps , VexRvm_Lx , V(660F38,96,_,x,0,0,4,FV ), 0 , 163, 0 , 4767 , 197, 139), // #938 - INST(Vfmaddsub213pd , VexRvm_Lx , V(660F38,A6,_,x,1,1,4,FV ), 0 , 162, 0 , 4782 , 196, 139), // #939 - INST(Vfmaddsub213ps , VexRvm_Lx , V(660F38,A6,_,x,0,0,4,FV ), 0 , 163, 0 , 4797 , 197, 139), // #940 - INST(Vfmaddsub231pd , VexRvm_Lx , V(660F38,B6,_,x,1,1,4,FV ), 0 , 162, 0 , 4812 , 196, 139), // #941 - INST(Vfmaddsub231ps , VexRvm_Lx , V(660F38,B6,_,x,0,0,4,FV ), 0 , 163, 0 , 4827 , 197, 139), // #942 - INST(Vfmaddsubpd , Fma4_Lx , V(660F3A,5D,_,x,x,_,_,_ ), 0 , 74 , 0 , 4842 , 270, 141), // #943 - INST(Vfmaddsubps , Fma4_Lx , V(660F3A,5C,_,x,x,_,_,_ ), 0 , 74 , 0 , 4854 , 270, 141), // #944 - INST(Vfmsub132pd , VexRvm_Lx , V(660F38,9A,_,x,1,1,4,FV ), 0 , 162, 0 , 4866 , 196, 139), // #945 - INST(Vfmsub132ps , VexRvm_Lx , V(660F38,9A,_,x,0,0,4,FV ), 0 , 163, 0 , 4878 , 197, 139), // #946 - INST(Vfmsub132sd , VexRvm , V(660F38,9B,_,I,1,1,3,T1S), 0 , 164, 0 , 4890 , 198, 140), // #947 - INST(Vfmsub132ss , VexRvm , V(660F38,9B,_,I,0,0,2,T1S), 0 , 121, 0 , 4902 , 199, 140), // #948 - INST(Vfmsub213pd , VexRvm_Lx , V(660F38,AA,_,x,1,1,4,FV ), 0 , 162, 0 , 4914 , 196, 139), // #949 - INST(Vfmsub213ps , VexRvm_Lx , V(660F38,AA,_,x,0,0,4,FV ), 0 , 163, 0 , 4926 , 197, 139), // #950 - INST(Vfmsub213sd , VexRvm , V(660F38,AB,_,I,1,1,3,T1S), 0 , 164, 0 , 4938 , 198, 140), // #951 - INST(Vfmsub213ss , VexRvm , V(660F38,AB,_,I,0,0,2,T1S), 0 , 121, 0 , 4950 , 199, 140), // #952 - INST(Vfmsub231pd , VexRvm_Lx , V(660F38,BA,_,x,1,1,4,FV ), 0 , 162, 0 , 4962 , 196, 139), // #953 - INST(Vfmsub231ps , VexRvm_Lx , V(660F38,BA,_,x,0,0,4,FV ), 0 , 163, 0 , 4974 , 197, 139), // #954 - INST(Vfmsub231sd , VexRvm , V(660F38,BB,_,I,1,1,3,T1S), 0 , 164, 0 , 4986 , 198, 140), // #955 - INST(Vfmsub231ss , VexRvm , V(660F38,BB,_,I,0,0,2,T1S), 0 , 121, 0 , 4998 , 199, 140), // #956 - INST(Vfmsubadd132pd , VexRvm_Lx , V(660F38,97,_,x,1,1,4,FV ), 0 , 162, 0 , 5010 , 196, 139), // #957 - INST(Vfmsubadd132ps , VexRvm_Lx , V(660F38,97,_,x,0,0,4,FV ), 0 , 163, 0 , 5025 , 197, 139), // #958 - INST(Vfmsubadd213pd , VexRvm_Lx , V(660F38,A7,_,x,1,1,4,FV ), 0 , 162, 0 , 5040 , 196, 139), // #959 - INST(Vfmsubadd213ps , VexRvm_Lx , V(660F38,A7,_,x,0,0,4,FV ), 0 , 163, 0 , 5055 , 197, 139), // #960 - INST(Vfmsubadd231pd , VexRvm_Lx , V(660F38,B7,_,x,1,1,4,FV ), 0 , 162, 0 , 5070 , 196, 139), // #961 - INST(Vfmsubadd231ps , VexRvm_Lx , V(660F38,B7,_,x,0,0,4,FV ), 0 , 163, 0 , 5085 , 197, 139), // #962 - INST(Vfmsubaddpd , Fma4_Lx , V(660F3A,5F,_,x,x,_,_,_ ), 0 , 74 , 0 , 5100 , 270, 141), // #963 - INST(Vfmsubaddps , Fma4_Lx , V(660F3A,5E,_,x,x,_,_,_ ), 0 , 74 , 0 , 5112 , 270, 141), // #964 - INST(Vfmsubpd , Fma4_Lx , V(660F3A,6D,_,x,x,_,_,_ ), 0 , 74 , 0 , 5124 , 270, 141), // #965 - INST(Vfmsubps , Fma4_Lx , V(660F3A,6C,_,x,x,_,_,_ ), 0 , 74 , 0 , 5133 , 270, 141), // #966 - INST(Vfmsubsd , Fma4 , V(660F3A,6F,_,0,x,_,_,_ ), 0 , 74 , 0 , 5142 , 271, 141), // #967 - INST(Vfmsubss , Fma4 , V(660F3A,6E,_,0,x,_,_,_ ), 0 , 74 , 0 , 5151 , 272, 141), // #968 - INST(Vfnmadd132pd , VexRvm_Lx , V(660F38,9C,_,x,1,1,4,FV ), 0 , 162, 0 , 5160 , 196, 139), // #969 - INST(Vfnmadd132ps , VexRvm_Lx , V(660F38,9C,_,x,0,0,4,FV ), 0 , 163, 0 , 5173 , 197, 139), // #970 - INST(Vfnmadd132sd , VexRvm , V(660F38,9D,_,I,1,1,3,T1S), 0 , 164, 0 , 5186 , 198, 140), // #971 - INST(Vfnmadd132ss , VexRvm , V(660F38,9D,_,I,0,0,2,T1S), 0 , 121, 0 , 5199 , 199, 140), // #972 - INST(Vfnmadd213pd , VexRvm_Lx , V(660F38,AC,_,x,1,1,4,FV ), 0 , 162, 0 , 5212 , 196, 139), // #973 - INST(Vfnmadd213ps , VexRvm_Lx , V(660F38,AC,_,x,0,0,4,FV ), 0 , 163, 0 , 5225 , 197, 139), // #974 - INST(Vfnmadd213sd , VexRvm , V(660F38,AD,_,I,1,1,3,T1S), 0 , 164, 0 , 5238 , 198, 140), // #975 - INST(Vfnmadd213ss , VexRvm , V(660F38,AD,_,I,0,0,2,T1S), 0 , 121, 0 , 5251 , 199, 140), // #976 - INST(Vfnmadd231pd , VexRvm_Lx , V(660F38,BC,_,x,1,1,4,FV ), 0 , 162, 0 , 5264 , 196, 139), // #977 - INST(Vfnmadd231ps , VexRvm_Lx , V(660F38,BC,_,x,0,0,4,FV ), 0 , 163, 0 , 5277 , 197, 139), // #978 - INST(Vfnmadd231sd , VexRvm , V(660F38,BD,_,I,1,1,3,T1S), 0 , 164, 0 , 5290 , 198, 140), // #979 - INST(Vfnmadd231ss , VexRvm , V(660F38,BD,_,I,0,0,2,T1S), 0 , 121, 0 , 5303 , 199, 140), // #980 - INST(Vfnmaddpd , Fma4_Lx , V(660F3A,79,_,x,x,_,_,_ ), 0 , 74 , 0 , 5316 , 270, 141), // #981 - INST(Vfnmaddps , Fma4_Lx , V(660F3A,78,_,x,x,_,_,_ ), 0 , 74 , 0 , 5326 , 270, 141), // #982 - INST(Vfnmaddsd , Fma4 , V(660F3A,7B,_,0,x,_,_,_ ), 0 , 74 , 0 , 5336 , 271, 141), // #983 - INST(Vfnmaddss , Fma4 , V(660F3A,7A,_,0,x,_,_,_ ), 0 , 74 , 0 , 5346 , 272, 141), // #984 - INST(Vfnmsub132pd , VexRvm_Lx , V(660F38,9E,_,x,1,1,4,FV ), 0 , 162, 0 , 5356 , 196, 139), // #985 - INST(Vfnmsub132ps , VexRvm_Lx , V(660F38,9E,_,x,0,0,4,FV ), 0 , 163, 0 , 5369 , 197, 139), // #986 - INST(Vfnmsub132sd , VexRvm , V(660F38,9F,_,I,1,1,3,T1S), 0 , 164, 0 , 5382 , 198, 140), // #987 - INST(Vfnmsub132ss , VexRvm , V(660F38,9F,_,I,0,0,2,T1S), 0 , 121, 0 , 5395 , 199, 140), // #988 - INST(Vfnmsub213pd , VexRvm_Lx , V(660F38,AE,_,x,1,1,4,FV ), 0 , 162, 0 , 5408 , 196, 139), // #989 - INST(Vfnmsub213ps , VexRvm_Lx , V(660F38,AE,_,x,0,0,4,FV ), 0 , 163, 0 , 5421 , 197, 139), // #990 - INST(Vfnmsub213sd , VexRvm , V(660F38,AF,_,I,1,1,3,T1S), 0 , 164, 0 , 5434 , 198, 140), // #991 - INST(Vfnmsub213ss , VexRvm , V(660F38,AF,_,I,0,0,2,T1S), 0 , 121, 0 , 5447 , 199, 140), // #992 - INST(Vfnmsub231pd , VexRvm_Lx , V(660F38,BE,_,x,1,1,4,FV ), 0 , 162, 0 , 5460 , 196, 139), // #993 - INST(Vfnmsub231ps , VexRvm_Lx , V(660F38,BE,_,x,0,0,4,FV ), 0 , 163, 0 , 5473 , 197, 139), // #994 - INST(Vfnmsub231sd , VexRvm , V(660F38,BF,_,I,1,1,3,T1S), 0 , 164, 0 , 5486 , 198, 140), // #995 - INST(Vfnmsub231ss , VexRvm , V(660F38,BF,_,I,0,0,2,T1S), 0 , 121, 0 , 5499 , 199, 140), // #996 - INST(Vfnmsubpd , Fma4_Lx , V(660F3A,7D,_,x,x,_,_,_ ), 0 , 74 , 0 , 5512 , 270, 141), // #997 - INST(Vfnmsubps , Fma4_Lx , V(660F3A,7C,_,x,x,_,_,_ ), 0 , 74 , 0 , 5522 , 270, 141), // #998 - INST(Vfnmsubsd , Fma4 , V(660F3A,7F,_,0,x,_,_,_ ), 0 , 74 , 0 , 5532 , 271, 141), // #999 - INST(Vfnmsubss , Fma4 , V(660F3A,7E,_,0,x,_,_,_ ), 0 , 74 , 0 , 5542 , 272, 141), // #1000 - INST(Vfpclasspd , VexRmi_Lx , E(660F3A,66,_,x,_,1,4,FV ), 0 , 111, 0 , 5552 , 273, 131), // #1001 - INST(Vfpclassps , VexRmi_Lx , E(660F3A,66,_,x,_,0,4,FV ), 0 , 110, 0 , 5563 , 274, 131), // #1002 - INST(Vfpclasssd , VexRmi_Lx , E(660F3A,67,_,I,_,1,3,T1S), 0 , 160, 0 , 5574 , 275, 66 ), // #1003 - INST(Vfpclassss , VexRmi_Lx , E(660F3A,67,_,I,_,0,2,T1S), 0 , 161, 0 , 5585 , 276, 66 ), // #1004 - INST(Vfrczpd , VexRm_Lx , V(XOP_M9,81,_,x,0,_,_,_ ), 0 , 80 , 0 , 5596 , 277, 142), // #1005 - INST(Vfrczps , VexRm_Lx , V(XOP_M9,80,_,x,0,_,_,_ ), 0 , 80 , 0 , 5604 , 277, 142), // #1006 - INST(Vfrczsd , VexRm , V(XOP_M9,83,_,0,0,_,_,_ ), 0 , 80 , 0 , 5612 , 278, 142), // #1007 - INST(Vfrczss , VexRm , V(XOP_M9,82,_,0,0,_,_,_ ), 0 , 80 , 0 , 5620 , 279, 142), // #1008 - INST(Vgatherdpd , VexRmvRm_VM , V(660F38,92,_,x,1,_,_,_ ), E(660F38,92,_,x,_,1,3,T1S), 165, 81 , 5628 , 280, 143), // #1009 - INST(Vgatherdps , VexRmvRm_VM , V(660F38,92,_,x,0,_,_,_ ), E(660F38,92,_,x,_,0,2,T1S), 97 , 82 , 5639 , 281, 143), // #1010 - INST(Vgatherpf0dpd , VexM_VM , E(660F38,C6,1,2,_,1,3,T1S), 0 , 166, 0 , 5650 , 282, 144), // #1011 - INST(Vgatherpf0dps , VexM_VM , E(660F38,C6,1,2,_,0,2,T1S), 0 , 167, 0 , 5664 , 283, 144), // #1012 - INST(Vgatherpf0qpd , VexM_VM , E(660F38,C7,1,2,_,1,3,T1S), 0 , 166, 0 , 5678 , 284, 144), // #1013 - INST(Vgatherpf0qps , VexM_VM , E(660F38,C7,1,2,_,0,2,T1S), 0 , 167, 0 , 5692 , 284, 144), // #1014 - INST(Vgatherpf1dpd , VexM_VM , E(660F38,C6,2,2,_,1,3,T1S), 0 , 168, 0 , 5706 , 282, 144), // #1015 - INST(Vgatherpf1dps , VexM_VM , E(660F38,C6,2,2,_,0,2,T1S), 0 , 169, 0 , 5720 , 283, 144), // #1016 - INST(Vgatherpf1qpd , VexM_VM , E(660F38,C7,2,2,_,1,3,T1S), 0 , 168, 0 , 5734 , 284, 144), // #1017 - INST(Vgatherpf1qps , VexM_VM , E(660F38,C7,2,2,_,0,2,T1S), 0 , 169, 0 , 5748 , 284, 144), // #1018 - INST(Vgatherqpd , VexRmvRm_VM , V(660F38,93,_,x,1,_,_,_ ), E(660F38,93,_,x,_,1,3,T1S), 165, 83 , 5762 , 285, 143), // #1019 - INST(Vgatherqps , VexRmvRm_VM , V(660F38,93,_,x,0,_,_,_ ), E(660F38,93,_,x,_,0,2,T1S), 97 , 84 , 5773 , 286, 143), // #1020 - INST(Vgetexppd , VexRm_Lx , E(660F38,42,_,x,_,1,4,FV ), 0 , 112, 0 , 5784 , 246, 129), // #1021 - INST(Vgetexpps , VexRm_Lx , E(660F38,42,_,x,_,0,4,FV ), 0 , 113, 0 , 5794 , 250, 129), // #1022 - INST(Vgetexpsd , VexRvm , E(660F38,43,_,I,_,1,3,T1S), 0 , 124, 0 , 5804 , 287, 68 ), // #1023 - INST(Vgetexpss , VexRvm , E(660F38,43,_,I,_,0,2,T1S), 0 , 125, 0 , 5814 , 288, 68 ), // #1024 - INST(Vgetmantpd , VexRmi_Lx , E(660F3A,26,_,x,_,1,4,FV ), 0 , 111, 0 , 5824 , 289, 129), // #1025 - INST(Vgetmantps , VexRmi_Lx , E(660F3A,26,_,x,_,0,4,FV ), 0 , 110, 0 , 5835 , 290, 129), // #1026 - INST(Vgetmantsd , VexRvmi , E(660F3A,27,_,I,_,1,3,T1S), 0 , 160, 0 , 5846 , 268, 68 ), // #1027 - INST(Vgetmantss , VexRvmi , E(660F3A,27,_,I,_,0,2,T1S), 0 , 161, 0 , 5857 , 269, 68 ), // #1028 - INST(Vgf2p8affineinvqb, VexRvmi_Lx , V(660F3A,CF,_,x,1,1,4,FV ), 0 , 170, 0 , 5868 , 291, 145), // #1029 - INST(Vgf2p8affineqb , VexRvmi_Lx , V(660F3A,CE,_,x,1,1,4,FV ), 0 , 170, 0 , 5886 , 291, 145), // #1030 - INST(Vgf2p8mulb , VexRvm_Lx , V(660F38,CF,_,x,0,0,4,FV ), 0 , 163, 0 , 5901 , 292, 145), // #1031 - INST(Vhaddpd , VexRvm_Lx , V(660F00,7C,_,x,I,_,_,_ ), 0 , 70 , 0 , 5912 , 200, 126), // #1032 - INST(Vhaddps , VexRvm_Lx , V(F20F00,7C,_,x,I,_,_,_ ), 0 , 108, 0 , 5920 , 200, 126), // #1033 - INST(Vhsubpd , VexRvm_Lx , V(660F00,7D,_,x,I,_,_,_ ), 0 , 70 , 0 , 5928 , 200, 126), // #1034 - INST(Vhsubps , VexRvm_Lx , V(F20F00,7D,_,x,I,_,_,_ ), 0 , 108, 0 , 5936 , 200, 126), // #1035 - INST(Vinsertf128 , VexRvmi , V(660F3A,18,_,1,0,_,_,_ ), 0 , 154, 0 , 5944 , 293, 126), // #1036 - INST(Vinsertf32x4 , VexRvmi_Lx , E(660F3A,18,_,x,_,0,4,T4 ), 0 , 155, 0 , 5956 , 294, 129), // #1037 - INST(Vinsertf32x8 , VexRvmi , E(660F3A,1A,_,2,_,0,5,T8 ), 0 , 156, 0 , 5969 , 295, 66 ), // #1038 - INST(Vinsertf64x2 , VexRvmi_Lx , E(660F3A,18,_,x,_,1,4,T2 ), 0 , 157, 0 , 5982 , 294, 131), // #1039 - INST(Vinsertf64x4 , VexRvmi , E(660F3A,1A,_,2,_,1,5,T4 ), 0 , 158, 0 , 5995 , 295, 68 ), // #1040 - INST(Vinserti128 , VexRvmi , V(660F3A,38,_,1,0,_,_,_ ), 0 , 154, 0 , 6008 , 293, 132), // #1041 - INST(Vinserti32x4 , VexRvmi_Lx , E(660F3A,38,_,x,_,0,4,T4 ), 0 , 155, 0 , 6020 , 294, 129), // #1042 - INST(Vinserti32x8 , VexRvmi , E(660F3A,3A,_,2,_,0,5,T8 ), 0 , 156, 0 , 6033 , 295, 66 ), // #1043 - INST(Vinserti64x2 , VexRvmi_Lx , E(660F3A,38,_,x,_,1,4,T2 ), 0 , 157, 0 , 6046 , 294, 131), // #1044 - INST(Vinserti64x4 , VexRvmi , E(660F3A,3A,_,2,_,1,5,T4 ), 0 , 158, 0 , 6059 , 295, 68 ), // #1045 - INST(Vinsertps , VexRvmi , V(660F3A,21,_,0,I,0,2,T1S), 0 , 159, 0 , 6072 , 296, 125), // #1046 - INST(Vlddqu , VexRm_Lx , V(F20F00,F0,_,x,I,_,_,_ ), 0 , 108, 0 , 6082 , 297, 126), // #1047 - INST(Vldmxcsr , VexM , V(000F00,AE,2,0,I,_,_,_ ), 0 , 171, 0 , 6089 , 298, 126), // #1048 - INST(Vmaskmovdqu , VexRm_ZDI , V(660F00,F7,_,0,I,_,_,_ ), 0 , 70 , 0 , 6098 , 299, 126), // #1049 - INST(Vmaskmovpd , VexRvmMvr_Lx , V(660F38,2D,_,x,0,_,_,_ ), V(660F38,2F,_,x,0,_,_,_ ), 97 , 85 , 6110 , 300, 126), // #1050 - INST(Vmaskmovps , VexRvmMvr_Lx , V(660F38,2C,_,x,0,_,_,_ ), V(660F38,2E,_,x,0,_,_,_ ), 97 , 86 , 6121 , 300, 126), // #1051 - INST(Vmaxpd , VexRvm_Lx , V(660F00,5F,_,x,I,1,4,FV ), 0 , 104, 0 , 6132 , 301, 124), // #1052 - INST(Vmaxps , VexRvm_Lx , V(000F00,5F,_,x,I,0,4,FV ), 0 , 105, 0 , 6139 , 302, 124), // #1053 - INST(Vmaxsd , VexRvm , V(F20F00,5F,_,I,I,1,3,T1S), 0 , 106, 0 , 6146 , 303, 124), // #1054 - INST(Vmaxss , VexRvm , V(F30F00,5F,_,I,I,0,2,T1S), 0 , 107, 0 , 6153 , 242, 124), // #1055 - INST(Vmcall , X86Op , O(000F01,C1,_,_,_,_,_,_ ), 0 , 21 , 0 , 6160 , 30 , 58 ), // #1056 - INST(Vmclear , X86M_Only , O(660F00,C7,6,_,_,_,_,_ ), 0 , 26 , 0 , 6167 , 32 , 58 ), // #1057 - INST(Vmfunc , X86Op , O(000F01,D4,_,_,_,_,_,_ ), 0 , 21 , 0 , 6175 , 30 , 58 ), // #1058 - INST(Vminpd , VexRvm_Lx , V(660F00,5D,_,x,I,1,4,FV ), 0 , 104, 0 , 6182 , 301, 124), // #1059 - INST(Vminps , VexRvm_Lx , V(000F00,5D,_,x,I,0,4,FV ), 0 , 105, 0 , 6189 , 302, 124), // #1060 - INST(Vminsd , VexRvm , V(F20F00,5D,_,I,I,1,3,T1S), 0 , 106, 0 , 6196 , 303, 124), // #1061 - INST(Vminss , VexRvm , V(F30F00,5D,_,I,I,0,2,T1S), 0 , 107, 0 , 6203 , 242, 124), // #1062 - INST(Vmlaunch , X86Op , O(000F01,C2,_,_,_,_,_,_ ), 0 , 21 , 0 , 6210 , 30 , 58 ), // #1063 - INST(Vmload , X86Op_xAX , O(000F01,DA,_,_,_,_,_,_ ), 0 , 21 , 0 , 6219 , 304, 22 ), // #1064 - INST(Vmmcall , X86Op , O(000F01,D9,_,_,_,_,_,_ ), 0 , 21 , 0 , 6226 , 30 , 22 ), // #1065 - INST(Vmovapd , VexRmMr_Lx , V(660F00,28,_,x,I,1,4,FVM), V(660F00,29,_,x,I,1,4,FVM), 172, 87 , 6234 , 305, 124), // #1066 - INST(Vmovaps , VexRmMr_Lx , V(000F00,28,_,x,I,0,4,FVM), V(000F00,29,_,x,I,0,4,FVM), 173, 88 , 6242 , 305, 124), // #1067 - INST(Vmovd , VexMovdMovq , V(660F00,6E,_,0,0,0,2,T1S), V(660F00,7E,_,0,0,0,2,T1S), 174, 89 , 6250 , 306, 125), // #1068 - INST(Vmovddup , VexRm_Lx , V(F20F00,12,_,x,I,1,3,DUP), 0 , 175, 0 , 6256 , 307, 124), // #1069 - INST(Vmovdqa , VexRmMr_Lx , V(660F00,6F,_,x,I,_,_,_ ), V(660F00,7F,_,x,I,_,_,_ ), 70 , 90 , 6265 , 308, 126), // #1070 - INST(Vmovdqa32 , VexRmMr_Lx , E(660F00,6F,_,x,_,0,4,FVM), E(660F00,7F,_,x,_,0,4,FVM), 176, 91 , 6273 , 309, 129), // #1071 - INST(Vmovdqa64 , VexRmMr_Lx , E(660F00,6F,_,x,_,1,4,FVM), E(660F00,7F,_,x,_,1,4,FVM), 177, 92 , 6283 , 309, 129), // #1072 - INST(Vmovdqu , VexRmMr_Lx , V(F30F00,6F,_,x,I,_,_,_ ), V(F30F00,7F,_,x,I,_,_,_ ), 178, 93 , 6293 , 308, 126), // #1073 - INST(Vmovdqu16 , VexRmMr_Lx , E(F20F00,6F,_,x,_,1,4,FVM), E(F20F00,7F,_,x,_,1,4,FVM), 179, 94 , 6301 , 309, 137), // #1074 - INST(Vmovdqu32 , VexRmMr_Lx , E(F30F00,6F,_,x,_,0,4,FVM), E(F30F00,7F,_,x,_,0,4,FVM), 180, 95 , 6311 , 309, 129), // #1075 - INST(Vmovdqu64 , VexRmMr_Lx , E(F30F00,6F,_,x,_,1,4,FVM), E(F30F00,7F,_,x,_,1,4,FVM), 181, 96 , 6321 , 309, 129), // #1076 - INST(Vmovdqu8 , VexRmMr_Lx , E(F20F00,6F,_,x,_,0,4,FVM), E(F20F00,7F,_,x,_,0,4,FVM), 182, 97 , 6331 , 309, 137), // #1077 - INST(Vmovhlps , VexRvm , V(000F00,12,_,0,I,0,_,_ ), 0 , 73 , 0 , 6340 , 310, 125), // #1078 - INST(Vmovhpd , VexRvmMr , V(660F00,16,_,0,I,1,3,T1S), V(660F00,17,_,0,I,1,3,T1S), 122, 98 , 6349 , 311, 125), // #1079 - INST(Vmovhps , VexRvmMr , V(000F00,16,_,0,I,0,3,T2 ), V(000F00,17,_,0,I,0,3,T2 ), 183, 99 , 6357 , 311, 125), // #1080 - INST(Vmovlhps , VexRvm , V(000F00,16,_,0,I,0,_,_ ), 0 , 73 , 0 , 6365 , 310, 125), // #1081 - INST(Vmovlpd , VexRvmMr , V(660F00,12,_,0,I,1,3,T1S), V(660F00,13,_,0,I,1,3,T1S), 122, 100, 6374 , 311, 125), // #1082 - INST(Vmovlps , VexRvmMr , V(000F00,12,_,0,I,0,3,T2 ), V(000F00,13,_,0,I,0,3,T2 ), 183, 101, 6382 , 311, 125), // #1083 - INST(Vmovmskpd , VexRm_Lx , V(660F00,50,_,x,I,_,_,_ ), 0 , 70 , 0 , 6390 , 312, 126), // #1084 - INST(Vmovmskps , VexRm_Lx , V(000F00,50,_,x,I,_,_,_ ), 0 , 73 , 0 , 6400 , 312, 126), // #1085 - INST(Vmovntdq , VexMr_Lx , V(660F00,E7,_,x,I,0,4,FVM), 0 , 184, 0 , 6410 , 313, 124), // #1086 - INST(Vmovntdqa , VexRm_Lx , V(660F38,2A,_,x,I,0,4,FVM), 0 , 109, 0 , 6419 , 314, 133), // #1087 - INST(Vmovntpd , VexMr_Lx , V(660F00,2B,_,x,I,1,4,FVM), 0 , 172, 0 , 6429 , 313, 124), // #1088 - INST(Vmovntps , VexMr_Lx , V(000F00,2B,_,x,I,0,4,FVM), 0 , 173, 0 , 6438 , 313, 124), // #1089 - INST(Vmovq , VexMovdMovq , V(660F00,6E,_,0,I,1,3,T1S), V(660F00,7E,_,0,I,1,3,T1S), 122, 102, 6447 , 315, 125), // #1090 - INST(Vmovsd , VexMovssMovsd , V(F20F00,10,_,I,I,1,3,T1S), V(F20F00,11,_,I,I,1,3,T1S), 106, 103, 6453 , 316, 125), // #1091 - INST(Vmovshdup , VexRm_Lx , V(F30F00,16,_,x,I,0,4,FVM), 0 , 185, 0 , 6460 , 317, 124), // #1092 - INST(Vmovsldup , VexRm_Lx , V(F30F00,12,_,x,I,0,4,FVM), 0 , 185, 0 , 6470 , 317, 124), // #1093 - INST(Vmovss , VexMovssMovsd , V(F30F00,10,_,I,I,0,2,T1S), V(F30F00,11,_,I,I,0,2,T1S), 107, 104, 6480 , 318, 125), // #1094 - INST(Vmovupd , VexRmMr_Lx , V(660F00,10,_,x,I,1,4,FVM), V(660F00,11,_,x,I,1,4,FVM), 172, 105, 6487 , 305, 124), // #1095 - INST(Vmovups , VexRmMr_Lx , V(000F00,10,_,x,I,0,4,FVM), V(000F00,11,_,x,I,0,4,FVM), 173, 106, 6495 , 305, 124), // #1096 - INST(Vmpsadbw , VexRvmi_Lx , V(660F3A,42,_,x,I,_,_,_ ), 0 , 74 , 0 , 6503 , 212, 146), // #1097 - INST(Vmptrld , X86M_Only , O(000F00,C7,6,_,_,_,_,_ ), 0 , 81 , 0 , 6512 , 32 , 58 ), // #1098 - INST(Vmptrst , X86M_Only , O(000F00,C7,7,_,_,_,_,_ ), 0 , 22 , 0 , 6520 , 32 , 58 ), // #1099 - INST(Vmread , X86Mr_NoSize , O(000F00,78,_,_,_,_,_,_ ), 0 , 4 , 0 , 6528 , 319, 58 ), // #1100 - INST(Vmresume , X86Op , O(000F01,C3,_,_,_,_,_,_ ), 0 , 21 , 0 , 6535 , 30 , 58 ), // #1101 - INST(Vmrun , X86Op_xAX , O(000F01,D8,_,_,_,_,_,_ ), 0 , 21 , 0 , 6544 , 304, 22 ), // #1102 - INST(Vmsave , X86Op_xAX , O(000F01,DB,_,_,_,_,_,_ ), 0 , 21 , 0 , 6550 , 304, 22 ), // #1103 - INST(Vmulpd , VexRvm_Lx , V(660F00,59,_,x,I,1,4,FV ), 0 , 104, 0 , 6557 , 196, 124), // #1104 - INST(Vmulps , VexRvm_Lx , V(000F00,59,_,x,I,0,4,FV ), 0 , 105, 0 , 6564 , 197, 124), // #1105 - INST(Vmulsd , VexRvm_Lx , V(F20F00,59,_,I,I,1,3,T1S), 0 , 106, 0 , 6571 , 198, 125), // #1106 - INST(Vmulss , VexRvm_Lx , V(F30F00,59,_,I,I,0,2,T1S), 0 , 107, 0 , 6578 , 199, 125), // #1107 - INST(Vmwrite , X86Rm_NoSize , O(000F00,79,_,_,_,_,_,_ ), 0 , 4 , 0 , 6585 , 320, 58 ), // #1108 - INST(Vmxon , X86M_Only , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 24 , 0 , 6593 , 32 , 58 ), // #1109 - INST(Vorpd , VexRvm_Lx , V(660F00,56,_,x,I,1,4,FV ), 0 , 104, 0 , 6599 , 208, 130), // #1110 - INST(Vorps , VexRvm_Lx , V(000F00,56,_,x,I,0,4,FV ), 0 , 105, 0 , 6605 , 209, 130), // #1111 - INST(Vp2intersectd , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,0,4,FV ), 0 , 127, 0 , 6611 , 321, 147), // #1112 - INST(Vp2intersectq , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,1,4,FV ), 0 , 186, 0 , 6625 , 322, 147), // #1113 - INST(Vp4dpwssd , VexRm_T1_4X , E(F20F38,52,_,2,_,0,4,T4X), 0 , 102, 0 , 6639 , 194, 148), // #1114 - INST(Vp4dpwssds , VexRm_T1_4X , E(F20F38,53,_,2,_,0,4,T4X), 0 , 102, 0 , 6649 , 194, 148), // #1115 - INST(Vpabsb , VexRm_Lx , V(660F38,1C,_,x,I,_,4,FVM), 0 , 109, 0 , 6660 , 317, 149), // #1116 - INST(Vpabsd , VexRm_Lx , V(660F38,1E,_,x,I,0,4,FV ), 0 , 163, 0 , 6667 , 317, 133), // #1117 - INST(Vpabsq , VexRm_Lx , E(660F38,1F,_,x,_,1,4,FV ), 0 , 112, 0 , 6674 , 261, 129), // #1118 - INST(Vpabsw , VexRm_Lx , V(660F38,1D,_,x,I,_,4,FVM), 0 , 109, 0 , 6681 , 317, 149), // #1119 - INST(Vpackssdw , VexRvm_Lx , V(660F00,6B,_,x,I,0,4,FV ), 0 , 133, 0 , 6688 , 207, 149), // #1120 - INST(Vpacksswb , VexRvm_Lx , V(660F00,63,_,x,I,I,4,FVM), 0 , 184, 0 , 6698 , 292, 149), // #1121 - INST(Vpackusdw , VexRvm_Lx , V(660F38,2B,_,x,I,0,4,FV ), 0 , 163, 0 , 6708 , 207, 149), // #1122 - INST(Vpackuswb , VexRvm_Lx , V(660F00,67,_,x,I,I,4,FVM), 0 , 184, 0 , 6718 , 292, 149), // #1123 - INST(Vpaddb , VexRvm_Lx , V(660F00,FC,_,x,I,I,4,FVM), 0 , 184, 0 , 6728 , 292, 149), // #1124 - INST(Vpaddd , VexRvm_Lx , V(660F00,FE,_,x,I,0,4,FV ), 0 , 133, 0 , 6735 , 207, 133), // #1125 - INST(Vpaddq , VexRvm_Lx , V(660F00,D4,_,x,I,1,4,FV ), 0 , 104, 0 , 6742 , 206, 133), // #1126 - INST(Vpaddsb , VexRvm_Lx , V(660F00,EC,_,x,I,I,4,FVM), 0 , 184, 0 , 6749 , 292, 149), // #1127 - INST(Vpaddsw , VexRvm_Lx , V(660F00,ED,_,x,I,I,4,FVM), 0 , 184, 0 , 6757 , 292, 149), // #1128 - INST(Vpaddusb , VexRvm_Lx , V(660F00,DC,_,x,I,I,4,FVM), 0 , 184, 0 , 6765 , 292, 149), // #1129 - INST(Vpaddusw , VexRvm_Lx , V(660F00,DD,_,x,I,I,4,FVM), 0 , 184, 0 , 6774 , 292, 149), // #1130 - INST(Vpaddw , VexRvm_Lx , V(660F00,FD,_,x,I,I,4,FVM), 0 , 184, 0 , 6783 , 292, 149), // #1131 - INST(Vpalignr , VexRvmi_Lx , V(660F3A,0F,_,x,I,I,4,FVM), 0 , 187, 0 , 6790 , 291, 149), // #1132 - INST(Vpand , VexRvm_Lx , V(660F00,DB,_,x,I,_,_,_ ), 0 , 70 , 0 , 6799 , 323, 146), // #1133 - INST(Vpandd , VexRvm_Lx , E(660F00,DB,_,x,_,0,4,FV ), 0 , 188, 0 , 6805 , 324, 129), // #1134 - INST(Vpandn , VexRvm_Lx , V(660F00,DF,_,x,I,_,_,_ ), 0 , 70 , 0 , 6812 , 325, 146), // #1135 - INST(Vpandnd , VexRvm_Lx , E(660F00,DF,_,x,_,0,4,FV ), 0 , 188, 0 , 6819 , 326, 129), // #1136 - INST(Vpandnq , VexRvm_Lx , E(660F00,DF,_,x,_,1,4,FV ), 0 , 130, 0 , 6827 , 327, 129), // #1137 - INST(Vpandq , VexRvm_Lx , E(660F00,DB,_,x,_,1,4,FV ), 0 , 130, 0 , 6835 , 328, 129), // #1138 - INST(Vpavgb , VexRvm_Lx , V(660F00,E0,_,x,I,I,4,FVM), 0 , 184, 0 , 6842 , 292, 149), // #1139 - INST(Vpavgw , VexRvm_Lx , V(660F00,E3,_,x,I,I,4,FVM), 0 , 184, 0 , 6849 , 292, 149), // #1140 - INST(Vpblendd , VexRvmi_Lx , V(660F3A,02,_,x,0,_,_,_ ), 0 , 74 , 0 , 6856 , 212, 132), // #1141 - INST(Vpblendmb , VexRvm_Lx , E(660F38,66,_,x,_,0,4,FVM), 0 , 189, 0 , 6865 , 329, 137), // #1142 - INST(Vpblendmd , VexRvm_Lx , E(660F38,64,_,x,_,0,4,FV ), 0 , 113, 0 , 6875 , 211, 129), // #1143 - INST(Vpblendmq , VexRvm_Lx , E(660F38,64,_,x,_,1,4,FV ), 0 , 112, 0 , 6885 , 210, 129), // #1144 - INST(Vpblendmw , VexRvm_Lx , E(660F38,66,_,x,_,1,4,FVM), 0 , 190, 0 , 6895 , 329, 137), // #1145 - INST(Vpblendvb , VexRvmr_Lx , V(660F3A,4C,_,x,0,_,_,_ ), 0 , 74 , 0 , 6905 , 213, 146), // #1146 - INST(Vpblendw , VexRvmi_Lx , V(660F3A,0E,_,x,I,_,_,_ ), 0 , 74 , 0 , 6915 , 212, 146), // #1147 - INST(Vpbroadcastb , VexRm_Lx_Bcst , V(660F38,78,_,x,0,0,0,T1S), E(660F38,7A,_,x,0,0,0,T1S), 191, 107, 6924 , 330, 150), // #1148 - INST(Vpbroadcastd , VexRm_Lx_Bcst , V(660F38,58,_,x,0,0,2,T1S), E(660F38,7C,_,x,0,0,0,T1S), 121, 108, 6937 , 331, 143), // #1149 - INST(Vpbroadcastmb2q , VexRm_Lx , E(F30F38,2A,_,x,_,1,_,_ ), 0 , 192, 0 , 6950 , 332, 151), // #1150 - INST(Vpbroadcastmw2d , VexRm_Lx , E(F30F38,3A,_,x,_,0,_,_ ), 0 , 193, 0 , 6966 , 332, 151), // #1151 - INST(Vpbroadcastq , VexRm_Lx_Bcst , V(660F38,59,_,x,0,1,3,T1S), E(660F38,7C,_,x,0,1,0,T1S), 120, 109, 6982 , 333, 143), // #1152 - INST(Vpbroadcastw , VexRm_Lx_Bcst , V(660F38,79,_,x,0,0,1,T1S), E(660F38,7B,_,x,0,0,0,T1S), 194, 110, 6995 , 334, 150), // #1153 - INST(Vpclmulqdq , VexRvmi_Lx , V(660F3A,44,_,x,I,_,4,FVM), 0 , 187, 0 , 7008 , 335, 152), // #1154 - INST(Vpcmov , VexRvrmRvmr_Lx , V(XOP_M8,A2,_,x,x,_,_,_ ), 0 , 195, 0 , 7019 , 270, 142), // #1155 - INST(Vpcmpb , VexRvmi_Lx , E(660F3A,3F,_,x,_,0,4,FVM), 0 , 151, 0 , 7026 , 336, 137), // #1156 - INST(Vpcmpd , VexRvmi_Lx , E(660F3A,1F,_,x,_,0,4,FV ), 0 , 110, 0 , 7033 , 337, 129), // #1157 - INST(Vpcmpeqb , VexRvm_Lx_KEvex , V(660F00,74,_,x,I,I,4,FV ), 0 , 133, 0 , 7040 , 338, 149), // #1158 - INST(Vpcmpeqd , VexRvm_Lx_KEvex , V(660F00,76,_,x,I,0,4,FVM), 0 , 184, 0 , 7049 , 339, 133), // #1159 - INST(Vpcmpeqq , VexRvm_Lx_KEvex , V(660F38,29,_,x,I,1,4,FVM), 0 , 196, 0 , 7058 , 340, 133), // #1160 - INST(Vpcmpeqw , VexRvm_Lx_KEvex , V(660F00,75,_,x,I,I,4,FV ), 0 , 133, 0 , 7067 , 338, 149), // #1161 - INST(Vpcmpestri , VexRmi , V(660F3A,61,_,0,I,_,_,_ ), 0 , 74 , 0 , 7076 , 341, 153), // #1162 - INST(Vpcmpestrm , VexRmi , V(660F3A,60,_,0,I,_,_,_ ), 0 , 74 , 0 , 7087 , 342, 153), // #1163 - INST(Vpcmpgtb , VexRvm_Lx_KEvex , V(660F00,64,_,x,I,I,4,FV ), 0 , 133, 0 , 7098 , 338, 149), // #1164 - INST(Vpcmpgtd , VexRvm_Lx_KEvex , V(660F00,66,_,x,I,0,4,FVM), 0 , 184, 0 , 7107 , 339, 133), // #1165 - INST(Vpcmpgtq , VexRvm_Lx_KEvex , V(660F38,37,_,x,I,1,4,FVM), 0 , 196, 0 , 7116 , 340, 133), // #1166 - INST(Vpcmpgtw , VexRvm_Lx_KEvex , V(660F00,65,_,x,I,I,4,FV ), 0 , 133, 0 , 7125 , 338, 149), // #1167 - INST(Vpcmpistri , VexRmi , V(660F3A,63,_,0,I,_,_,_ ), 0 , 74 , 0 , 7134 , 343, 153), // #1168 - INST(Vpcmpistrm , VexRmi , V(660F3A,62,_,0,I,_,_,_ ), 0 , 74 , 0 , 7145 , 344, 153), // #1169 - INST(Vpcmpq , VexRvmi_Lx , E(660F3A,1F,_,x,_,1,4,FV ), 0 , 111, 0 , 7156 , 345, 129), // #1170 - INST(Vpcmpub , VexRvmi_Lx , E(660F3A,3E,_,x,_,0,4,FVM), 0 , 151, 0 , 7163 , 336, 137), // #1171 - INST(Vpcmpud , VexRvmi_Lx , E(660F3A,1E,_,x,_,0,4,FV ), 0 , 110, 0 , 7171 , 337, 129), // #1172 - INST(Vpcmpuq , VexRvmi_Lx , E(660F3A,1E,_,x,_,1,4,FV ), 0 , 111, 0 , 7179 , 345, 129), // #1173 - INST(Vpcmpuw , VexRvmi_Lx , E(660F3A,3E,_,x,_,1,4,FVM), 0 , 197, 0 , 7187 , 345, 137), // #1174 - INST(Vpcmpw , VexRvmi_Lx , E(660F3A,3F,_,x,_,1,4,FVM), 0 , 197, 0 , 7195 , 345, 137), // #1175 - INST(Vpcomb , VexRvmi , V(XOP_M8,CC,_,0,0,_,_,_ ), 0 , 195, 0 , 7202 , 258, 142), // #1176 - INST(Vpcomd , VexRvmi , V(XOP_M8,CE,_,0,0,_,_,_ ), 0 , 195, 0 , 7209 , 258, 142), // #1177 - INST(Vpcompressb , VexMr_Lx , E(660F38,63,_,x,_,0,0,T1S), 0 , 198, 0 , 7216 , 227, 154), // #1178 - INST(Vpcompressd , VexMr_Lx , E(660F38,8B,_,x,_,0,2,T1S), 0 , 125, 0 , 7228 , 227, 129), // #1179 - INST(Vpcompressq , VexMr_Lx , E(660F38,8B,_,x,_,1,3,T1S), 0 , 124, 0 , 7240 , 227, 129), // #1180 - INST(Vpcompressw , VexMr_Lx , E(660F38,63,_,x,_,1,1,T1S), 0 , 199, 0 , 7252 , 227, 154), // #1181 - INST(Vpcomq , VexRvmi , V(XOP_M8,CF,_,0,0,_,_,_ ), 0 , 195, 0 , 7264 , 258, 142), // #1182 - INST(Vpcomub , VexRvmi , V(XOP_M8,EC,_,0,0,_,_,_ ), 0 , 195, 0 , 7271 , 258, 142), // #1183 - INST(Vpcomud , VexRvmi , V(XOP_M8,EE,_,0,0,_,_,_ ), 0 , 195, 0 , 7279 , 258, 142), // #1184 - INST(Vpcomuq , VexRvmi , V(XOP_M8,EF,_,0,0,_,_,_ ), 0 , 195, 0 , 7287 , 258, 142), // #1185 - INST(Vpcomuw , VexRvmi , V(XOP_M8,ED,_,0,0,_,_,_ ), 0 , 195, 0 , 7295 , 258, 142), // #1186 - INST(Vpcomw , VexRvmi , V(XOP_M8,CD,_,0,0,_,_,_ ), 0 , 195, 0 , 7303 , 258, 142), // #1187 - INST(Vpconflictd , VexRm_Lx , E(660F38,C4,_,x,_,0,4,FV ), 0 , 113, 0 , 7310 , 346, 151), // #1188 - INST(Vpconflictq , VexRm_Lx , E(660F38,C4,_,x,_,1,4,FV ), 0 , 112, 0 , 7322 , 346, 151), // #1189 - INST(Vpdpbusd , VexRvm_Lx , V(660F38,50,_,x,_,0,4,FV ), 0 , 163, 0 , 7334 , 347, 155), // #1190 - INST(Vpdpbusds , VexRvm_Lx , V(660F38,51,_,x,_,0,4,FV ), 0 , 163, 0 , 7343 , 347, 155), // #1191 - INST(Vpdpwssd , VexRvm_Lx , V(660F38,52,_,x,_,0,4,FV ), 0 , 163, 0 , 7353 , 347, 155), // #1192 - INST(Vpdpwssds , VexRvm_Lx , V(660F38,53,_,x,_,0,4,FV ), 0 , 163, 0 , 7362 , 347, 155), // #1193 - INST(Vperm2f128 , VexRvmi , V(660F3A,06,_,1,0,_,_,_ ), 0 , 154, 0 , 7372 , 348, 126), // #1194 - INST(Vperm2i128 , VexRvmi , V(660F3A,46,_,1,0,_,_,_ ), 0 , 154, 0 , 7383 , 348, 132), // #1195 - INST(Vpermb , VexRvm_Lx , E(660F38,8D,_,x,_,0,4,FVM), 0 , 189, 0 , 7394 , 329, 156), // #1196 - INST(Vpermd , VexRvm_Lx , V(660F38,36,_,x,0,0,4,FV ), 0 , 163, 0 , 7401 , 349, 143), // #1197 - INST(Vpermi2b , VexRvm_Lx , E(660F38,75,_,x,_,0,4,FVM), 0 , 189, 0 , 7408 , 329, 156), // #1198 - INST(Vpermi2d , VexRvm_Lx , E(660F38,76,_,x,_,0,4,FV ), 0 , 113, 0 , 7417 , 211, 129), // #1199 - INST(Vpermi2pd , VexRvm_Lx , E(660F38,77,_,x,_,1,4,FV ), 0 , 112, 0 , 7426 , 210, 129), // #1200 - INST(Vpermi2ps , VexRvm_Lx , E(660F38,77,_,x,_,0,4,FV ), 0 , 113, 0 , 7436 , 211, 129), // #1201 - INST(Vpermi2q , VexRvm_Lx , E(660F38,76,_,x,_,1,4,FV ), 0 , 112, 0 , 7446 , 210, 129), // #1202 - INST(Vpermi2w , VexRvm_Lx , E(660F38,75,_,x,_,1,4,FVM), 0 , 190, 0 , 7455 , 329, 137), // #1203 - INST(Vpermil2pd , VexRvrmiRvmri_Lx , V(660F3A,49,_,x,x,_,_,_ ), 0 , 74 , 0 , 7464 , 350, 142), // #1204 - INST(Vpermil2ps , VexRvrmiRvmri_Lx , V(660F3A,48,_,x,x,_,_,_ ), 0 , 74 , 0 , 7475 , 350, 142), // #1205 - INST(Vpermilpd , VexRvmRmi_Lx , V(660F38,0D,_,x,0,1,4,FV ), V(660F3A,05,_,x,0,1,4,FV ), 200, 111, 7486 , 351, 124), // #1206 - INST(Vpermilps , VexRvmRmi_Lx , V(660F38,0C,_,x,0,0,4,FV ), V(660F3A,04,_,x,0,0,4,FV ), 163, 112, 7496 , 351, 124), // #1207 - INST(Vpermpd , VexRvmRmi_Lx , E(660F38,16,_,x,1,1,4,FV ), V(660F3A,01,_,x,1,1,4,FV ), 201, 113, 7506 , 352, 143), // #1208 - INST(Vpermps , VexRvm_Lx , V(660F38,16,_,x,0,0,4,FV ), 0 , 163, 0 , 7514 , 349, 143), // #1209 - INST(Vpermq , VexRvmRmi_Lx , E(660F38,36,_,x,_,1,4,FV ), V(660F3A,00,_,x,1,1,4,FV ), 112, 114, 7522 , 352, 143), // #1210 - INST(Vpermt2b , VexRvm_Lx , E(660F38,7D,_,x,_,0,4,FVM), 0 , 189, 0 , 7529 , 329, 156), // #1211 - INST(Vpermt2d , VexRvm_Lx , E(660F38,7E,_,x,_,0,4,FV ), 0 , 113, 0 , 7538 , 211, 129), // #1212 - INST(Vpermt2pd , VexRvm_Lx , E(660F38,7F,_,x,_,1,4,FV ), 0 , 112, 0 , 7547 , 210, 129), // #1213 - INST(Vpermt2ps , VexRvm_Lx , E(660F38,7F,_,x,_,0,4,FV ), 0 , 113, 0 , 7557 , 211, 129), // #1214 - INST(Vpermt2q , VexRvm_Lx , E(660F38,7E,_,x,_,1,4,FV ), 0 , 112, 0 , 7567 , 210, 129), // #1215 - INST(Vpermt2w , VexRvm_Lx , E(660F38,7D,_,x,_,1,4,FVM), 0 , 190, 0 , 7576 , 329, 137), // #1216 - INST(Vpermw , VexRvm_Lx , E(660F38,8D,_,x,_,1,4,FVM), 0 , 190, 0 , 7585 , 329, 137), // #1217 - INST(Vpexpandb , VexRm_Lx , E(660F38,62,_,x,_,0,0,T1S), 0 , 198, 0 , 7592 , 261, 154), // #1218 - INST(Vpexpandd , VexRm_Lx , E(660F38,89,_,x,_,0,2,T1S), 0 , 125, 0 , 7602 , 261, 129), // #1219 - INST(Vpexpandq , VexRm_Lx , E(660F38,89,_,x,_,1,3,T1S), 0 , 124, 0 , 7612 , 261, 129), // #1220 - INST(Vpexpandw , VexRm_Lx , E(660F38,62,_,x,_,1,1,T1S), 0 , 199, 0 , 7622 , 261, 154), // #1221 - INST(Vpextrb , VexMri , V(660F3A,14,_,0,0,I,0,T1S), 0 , 202, 0 , 7632 , 353, 157), // #1222 - INST(Vpextrd , VexMri , V(660F3A,16,_,0,0,0,2,T1S), 0 , 159, 0 , 7640 , 265, 158), // #1223 - INST(Vpextrq , VexMri , V(660F3A,16,_,0,1,1,3,T1S), 0 , 203, 0 , 7648 , 354, 158), // #1224 - INST(Vpextrw , VexMri_Vpextrw , V(660F3A,15,_,0,0,I,1,T1S), 0 , 204, 0 , 7656 , 355, 157), // #1225 - INST(Vpgatherdd , VexRmvRm_VM , V(660F38,90,_,x,0,_,_,_ ), E(660F38,90,_,x,_,0,2,T1S), 97 , 115, 7664 , 281, 143), // #1226 - INST(Vpgatherdq , VexRmvRm_VM , V(660F38,90,_,x,1,_,_,_ ), E(660F38,90,_,x,_,1,3,T1S), 165, 116, 7675 , 280, 143), // #1227 - INST(Vpgatherqd , VexRmvRm_VM , V(660F38,91,_,x,0,_,_,_ ), E(660F38,91,_,x,_,0,2,T1S), 97 , 117, 7686 , 286, 143), // #1228 - INST(Vpgatherqq , VexRmvRm_VM , V(660F38,91,_,x,1,_,_,_ ), E(660F38,91,_,x,_,1,3,T1S), 165, 118, 7697 , 285, 143), // #1229 - INST(Vphaddbd , VexRm , V(XOP_M9,C2,_,0,0,_,_,_ ), 0 , 80 , 0 , 7708 , 202, 142), // #1230 - INST(Vphaddbq , VexRm , V(XOP_M9,C3,_,0,0,_,_,_ ), 0 , 80 , 0 , 7717 , 202, 142), // #1231 - INST(Vphaddbw , VexRm , V(XOP_M9,C1,_,0,0,_,_,_ ), 0 , 80 , 0 , 7726 , 202, 142), // #1232 - INST(Vphaddd , VexRvm_Lx , V(660F38,02,_,x,I,_,_,_ ), 0 , 97 , 0 , 7735 , 200, 146), // #1233 - INST(Vphadddq , VexRm , V(XOP_M9,CB,_,0,0,_,_,_ ), 0 , 80 , 0 , 7743 , 202, 142), // #1234 - INST(Vphaddsw , VexRvm_Lx , V(660F38,03,_,x,I,_,_,_ ), 0 , 97 , 0 , 7752 , 200, 146), // #1235 - INST(Vphaddubd , VexRm , V(XOP_M9,D2,_,0,0,_,_,_ ), 0 , 80 , 0 , 7761 , 202, 142), // #1236 - INST(Vphaddubq , VexRm , V(XOP_M9,D3,_,0,0,_,_,_ ), 0 , 80 , 0 , 7771 , 202, 142), // #1237 - INST(Vphaddubw , VexRm , V(XOP_M9,D1,_,0,0,_,_,_ ), 0 , 80 , 0 , 7781 , 202, 142), // #1238 - INST(Vphaddudq , VexRm , V(XOP_M9,DB,_,0,0,_,_,_ ), 0 , 80 , 0 , 7791 , 202, 142), // #1239 - INST(Vphadduwd , VexRm , V(XOP_M9,D6,_,0,0,_,_,_ ), 0 , 80 , 0 , 7801 , 202, 142), // #1240 - INST(Vphadduwq , VexRm , V(XOP_M9,D7,_,0,0,_,_,_ ), 0 , 80 , 0 , 7811 , 202, 142), // #1241 - INST(Vphaddw , VexRvm_Lx , V(660F38,01,_,x,I,_,_,_ ), 0 , 97 , 0 , 7821 , 200, 146), // #1242 - INST(Vphaddwd , VexRm , V(XOP_M9,C6,_,0,0,_,_,_ ), 0 , 80 , 0 , 7829 , 202, 142), // #1243 - INST(Vphaddwq , VexRm , V(XOP_M9,C7,_,0,0,_,_,_ ), 0 , 80 , 0 , 7838 , 202, 142), // #1244 - INST(Vphminposuw , VexRm , V(660F38,41,_,0,I,_,_,_ ), 0 , 97 , 0 , 7847 , 202, 126), // #1245 - INST(Vphsubbw , VexRm , V(XOP_M9,E1,_,0,0,_,_,_ ), 0 , 80 , 0 , 7859 , 202, 142), // #1246 - INST(Vphsubd , VexRvm_Lx , V(660F38,06,_,x,I,_,_,_ ), 0 , 97 , 0 , 7868 , 200, 146), // #1247 - INST(Vphsubdq , VexRm , V(XOP_M9,E3,_,0,0,_,_,_ ), 0 , 80 , 0 , 7876 , 202, 142), // #1248 - INST(Vphsubsw , VexRvm_Lx , V(660F38,07,_,x,I,_,_,_ ), 0 , 97 , 0 , 7885 , 200, 146), // #1249 - INST(Vphsubw , VexRvm_Lx , V(660F38,05,_,x,I,_,_,_ ), 0 , 97 , 0 , 7894 , 200, 146), // #1250 - INST(Vphsubwd , VexRm , V(XOP_M9,E2,_,0,0,_,_,_ ), 0 , 80 , 0 , 7902 , 202, 142), // #1251 - INST(Vpinsrb , VexRvmi , V(660F3A,20,_,0,0,I,0,T1S), 0 , 202, 0 , 7911 , 356, 157), // #1252 - INST(Vpinsrd , VexRvmi , V(660F3A,22,_,0,0,0,2,T1S), 0 , 159, 0 , 7919 , 357, 158), // #1253 - INST(Vpinsrq , VexRvmi , V(660F3A,22,_,0,1,1,3,T1S), 0 , 203, 0 , 7927 , 358, 158), // #1254 - INST(Vpinsrw , VexRvmi , V(660F00,C4,_,0,0,I,1,T1S), 0 , 205, 0 , 7935 , 359, 157), // #1255 - INST(Vplzcntd , VexRm_Lx , E(660F38,44,_,x,_,0,4,FV ), 0 , 113, 0 , 7943 , 346, 151), // #1256 - INST(Vplzcntq , VexRm_Lx , E(660F38,44,_,x,_,1,4,FV ), 0 , 112, 0 , 7952 , 360, 151), // #1257 - INST(Vpmacsdd , VexRvmr , V(XOP_M8,9E,_,0,0,_,_,_ ), 0 , 195, 0 , 7961 , 361, 142), // #1258 - INST(Vpmacsdqh , VexRvmr , V(XOP_M8,9F,_,0,0,_,_,_ ), 0 , 195, 0 , 7970 , 361, 142), // #1259 - INST(Vpmacsdql , VexRvmr , V(XOP_M8,97,_,0,0,_,_,_ ), 0 , 195, 0 , 7980 , 361, 142), // #1260 - INST(Vpmacssdd , VexRvmr , V(XOP_M8,8E,_,0,0,_,_,_ ), 0 , 195, 0 , 7990 , 361, 142), // #1261 - INST(Vpmacssdqh , VexRvmr , V(XOP_M8,8F,_,0,0,_,_,_ ), 0 , 195, 0 , 8000 , 361, 142), // #1262 - INST(Vpmacssdql , VexRvmr , V(XOP_M8,87,_,0,0,_,_,_ ), 0 , 195, 0 , 8011 , 361, 142), // #1263 - INST(Vpmacsswd , VexRvmr , V(XOP_M8,86,_,0,0,_,_,_ ), 0 , 195, 0 , 8022 , 361, 142), // #1264 - INST(Vpmacssww , VexRvmr , V(XOP_M8,85,_,0,0,_,_,_ ), 0 , 195, 0 , 8032 , 361, 142), // #1265 - INST(Vpmacswd , VexRvmr , V(XOP_M8,96,_,0,0,_,_,_ ), 0 , 195, 0 , 8042 , 361, 142), // #1266 - INST(Vpmacsww , VexRvmr , V(XOP_M8,95,_,0,0,_,_,_ ), 0 , 195, 0 , 8051 , 361, 142), // #1267 - INST(Vpmadcsswd , VexRvmr , V(XOP_M8,A6,_,0,0,_,_,_ ), 0 , 195, 0 , 8060 , 361, 142), // #1268 - INST(Vpmadcswd , VexRvmr , V(XOP_M8,B6,_,0,0,_,_,_ ), 0 , 195, 0 , 8071 , 361, 142), // #1269 - INST(Vpmadd52huq , VexRvm_Lx , E(660F38,B5,_,x,_,1,4,FV ), 0 , 112, 0 , 8081 , 210, 159), // #1270 - INST(Vpmadd52luq , VexRvm_Lx , E(660F38,B4,_,x,_,1,4,FV ), 0 , 112, 0 , 8093 , 210, 159), // #1271 - INST(Vpmaddubsw , VexRvm_Lx , V(660F38,04,_,x,I,I,4,FVM), 0 , 109, 0 , 8105 , 292, 149), // #1272 - INST(Vpmaddwd , VexRvm_Lx , V(660F00,F5,_,x,I,I,4,FVM), 0 , 184, 0 , 8116 , 292, 149), // #1273 - INST(Vpmaskmovd , VexRvmMvr_Lx , V(660F38,8C,_,x,0,_,_,_ ), V(660F38,8E,_,x,0,_,_,_ ), 97 , 119, 8125 , 300, 132), // #1274 - INST(Vpmaskmovq , VexRvmMvr_Lx , V(660F38,8C,_,x,1,_,_,_ ), V(660F38,8E,_,x,1,_,_,_ ), 165, 120, 8136 , 300, 132), // #1275 - INST(Vpmaxsb , VexRvm_Lx , V(660F38,3C,_,x,I,I,4,FVM), 0 , 109, 0 , 8147 , 362, 149), // #1276 - INST(Vpmaxsd , VexRvm_Lx , V(660F38,3D,_,x,I,0,4,FV ), 0 , 163, 0 , 8155 , 209, 133), // #1277 - INST(Vpmaxsq , VexRvm_Lx , E(660F38,3D,_,x,_,1,4,FV ), 0 , 112, 0 , 8163 , 210, 129), // #1278 - INST(Vpmaxsw , VexRvm_Lx , V(660F00,EE,_,x,I,I,4,FVM), 0 , 184, 0 , 8171 , 362, 149), // #1279 - INST(Vpmaxub , VexRvm_Lx , V(660F00,DE,_,x,I,I,4,FVM), 0 , 184, 0 , 8179 , 362, 149), // #1280 - INST(Vpmaxud , VexRvm_Lx , V(660F38,3F,_,x,I,0,4,FV ), 0 , 163, 0 , 8187 , 209, 133), // #1281 - INST(Vpmaxuq , VexRvm_Lx , E(660F38,3F,_,x,_,1,4,FV ), 0 , 112, 0 , 8195 , 210, 129), // #1282 - INST(Vpmaxuw , VexRvm_Lx , V(660F38,3E,_,x,I,I,4,FVM), 0 , 109, 0 , 8203 , 362, 149), // #1283 - INST(Vpminsb , VexRvm_Lx , V(660F38,38,_,x,I,I,4,FVM), 0 , 109, 0 , 8211 , 362, 149), // #1284 - INST(Vpminsd , VexRvm_Lx , V(660F38,39,_,x,I,0,4,FV ), 0 , 163, 0 , 8219 , 209, 133), // #1285 - INST(Vpminsq , VexRvm_Lx , E(660F38,39,_,x,_,1,4,FV ), 0 , 112, 0 , 8227 , 210, 129), // #1286 - INST(Vpminsw , VexRvm_Lx , V(660F00,EA,_,x,I,I,4,FVM), 0 , 184, 0 , 8235 , 362, 149), // #1287 - INST(Vpminub , VexRvm_Lx , V(660F00,DA,_,x,I,_,4,FVM), 0 , 184, 0 , 8243 , 362, 149), // #1288 - INST(Vpminud , VexRvm_Lx , V(660F38,3B,_,x,I,0,4,FV ), 0 , 163, 0 , 8251 , 209, 133), // #1289 - INST(Vpminuq , VexRvm_Lx , E(660F38,3B,_,x,_,1,4,FV ), 0 , 112, 0 , 8259 , 210, 129), // #1290 - INST(Vpminuw , VexRvm_Lx , V(660F38,3A,_,x,I,_,4,FVM), 0 , 109, 0 , 8267 , 362, 149), // #1291 - INST(Vpmovb2m , VexRm_Lx , E(F30F38,29,_,x,_,0,_,_ ), 0 , 193, 0 , 8275 , 363, 137), // #1292 - INST(Vpmovd2m , VexRm_Lx , E(F30F38,39,_,x,_,0,_,_ ), 0 , 193, 0 , 8284 , 363, 131), // #1293 - INST(Vpmovdb , VexMr_Lx , E(F30F38,31,_,x,_,0,2,QVM), 0 , 206, 0 , 8293 , 364, 129), // #1294 - INST(Vpmovdw , VexMr_Lx , E(F30F38,33,_,x,_,0,3,HVM), 0 , 207, 0 , 8301 , 365, 129), // #1295 - INST(Vpmovm2b , VexRm_Lx , E(F30F38,28,_,x,_,0,_,_ ), 0 , 193, 0 , 8309 , 332, 137), // #1296 - INST(Vpmovm2d , VexRm_Lx , E(F30F38,38,_,x,_,0,_,_ ), 0 , 193, 0 , 8318 , 332, 131), // #1297 - INST(Vpmovm2q , VexRm_Lx , E(F30F38,38,_,x,_,1,_,_ ), 0 , 192, 0 , 8327 , 332, 131), // #1298 - INST(Vpmovm2w , VexRm_Lx , E(F30F38,28,_,x,_,1,_,_ ), 0 , 192, 0 , 8336 , 332, 137), // #1299 - INST(Vpmovmskb , VexRm_Lx , V(660F00,D7,_,x,I,_,_,_ ), 0 , 70 , 0 , 8345 , 312, 146), // #1300 - INST(Vpmovq2m , VexRm_Lx , E(F30F38,39,_,x,_,1,_,_ ), 0 , 192, 0 , 8355 , 363, 131), // #1301 - INST(Vpmovqb , VexMr_Lx , E(F30F38,32,_,x,_,0,1,OVM), 0 , 208, 0 , 8364 , 366, 129), // #1302 - INST(Vpmovqd , VexMr_Lx , E(F30F38,35,_,x,_,0,3,HVM), 0 , 207, 0 , 8372 , 365, 129), // #1303 - INST(Vpmovqw , VexMr_Lx , E(F30F38,34,_,x,_,0,2,QVM), 0 , 206, 0 , 8380 , 364, 129), // #1304 - INST(Vpmovsdb , VexMr_Lx , E(F30F38,21,_,x,_,0,2,QVM), 0 , 206, 0 , 8388 , 364, 129), // #1305 - INST(Vpmovsdw , VexMr_Lx , E(F30F38,23,_,x,_,0,3,HVM), 0 , 207, 0 , 8397 , 365, 129), // #1306 - INST(Vpmovsqb , VexMr_Lx , E(F30F38,22,_,x,_,0,1,OVM), 0 , 208, 0 , 8406 , 366, 129), // #1307 - INST(Vpmovsqd , VexMr_Lx , E(F30F38,25,_,x,_,0,3,HVM), 0 , 207, 0 , 8415 , 365, 129), // #1308 - INST(Vpmovsqw , VexMr_Lx , E(F30F38,24,_,x,_,0,2,QVM), 0 , 206, 0 , 8424 , 364, 129), // #1309 - INST(Vpmovswb , VexMr_Lx , E(F30F38,20,_,x,_,0,3,HVM), 0 , 207, 0 , 8433 , 365, 137), // #1310 - INST(Vpmovsxbd , VexRm_Lx , V(660F38,21,_,x,I,I,2,QVM), 0 , 209, 0 , 8442 , 367, 133), // #1311 - INST(Vpmovsxbq , VexRm_Lx , V(660F38,22,_,x,I,I,1,OVM), 0 , 210, 0 , 8452 , 368, 133), // #1312 - INST(Vpmovsxbw , VexRm_Lx , V(660F38,20,_,x,I,I,3,HVM), 0 , 132, 0 , 8462 , 369, 149), // #1313 - INST(Vpmovsxdq , VexRm_Lx , V(660F38,25,_,x,I,0,3,HVM), 0 , 132, 0 , 8472 , 369, 133), // #1314 - INST(Vpmovsxwd , VexRm_Lx , V(660F38,23,_,x,I,I,3,HVM), 0 , 132, 0 , 8482 , 369, 133), // #1315 - INST(Vpmovsxwq , VexRm_Lx , V(660F38,24,_,x,I,I,2,QVM), 0 , 209, 0 , 8492 , 367, 133), // #1316 - INST(Vpmovusdb , VexMr_Lx , E(F30F38,11,_,x,_,0,2,QVM), 0 , 206, 0 , 8502 , 364, 129), // #1317 - INST(Vpmovusdw , VexMr_Lx , E(F30F38,13,_,x,_,0,3,HVM), 0 , 207, 0 , 8512 , 365, 129), // #1318 - INST(Vpmovusqb , VexMr_Lx , E(F30F38,12,_,x,_,0,1,OVM), 0 , 208, 0 , 8522 , 366, 129), // #1319 - INST(Vpmovusqd , VexMr_Lx , E(F30F38,15,_,x,_,0,3,HVM), 0 , 207, 0 , 8532 , 365, 129), // #1320 - INST(Vpmovusqw , VexMr_Lx , E(F30F38,14,_,x,_,0,2,QVM), 0 , 206, 0 , 8542 , 364, 129), // #1321 - INST(Vpmovuswb , VexMr_Lx , E(F30F38,10,_,x,_,0,3,HVM), 0 , 207, 0 , 8552 , 365, 137), // #1322 - INST(Vpmovw2m , VexRm_Lx , E(F30F38,29,_,x,_,1,_,_ ), 0 , 192, 0 , 8562 , 363, 137), // #1323 - INST(Vpmovwb , VexMr_Lx , E(F30F38,30,_,x,_,0,3,HVM), 0 , 207, 0 , 8571 , 365, 137), // #1324 - INST(Vpmovzxbd , VexRm_Lx , V(660F38,31,_,x,I,I,2,QVM), 0 , 209, 0 , 8579 , 367, 133), // #1325 - INST(Vpmovzxbq , VexRm_Lx , V(660F38,32,_,x,I,I,1,OVM), 0 , 210, 0 , 8589 , 368, 133), // #1326 - INST(Vpmovzxbw , VexRm_Lx , V(660F38,30,_,x,I,I,3,HVM), 0 , 132, 0 , 8599 , 369, 149), // #1327 - INST(Vpmovzxdq , VexRm_Lx , V(660F38,35,_,x,I,0,3,HVM), 0 , 132, 0 , 8609 , 369, 133), // #1328 - INST(Vpmovzxwd , VexRm_Lx , V(660F38,33,_,x,I,I,3,HVM), 0 , 132, 0 , 8619 , 369, 133), // #1329 - INST(Vpmovzxwq , VexRm_Lx , V(660F38,34,_,x,I,I,2,QVM), 0 , 209, 0 , 8629 , 367, 133), // #1330 - INST(Vpmuldq , VexRvm_Lx , V(660F38,28,_,x,I,1,4,FV ), 0 , 200, 0 , 8639 , 206, 133), // #1331 - INST(Vpmulhrsw , VexRvm_Lx , V(660F38,0B,_,x,I,I,4,FVM), 0 , 109, 0 , 8647 , 292, 149), // #1332 - INST(Vpmulhuw , VexRvm_Lx , V(660F00,E4,_,x,I,I,4,FVM), 0 , 184, 0 , 8657 , 292, 149), // #1333 - INST(Vpmulhw , VexRvm_Lx , V(660F00,E5,_,x,I,I,4,FVM), 0 , 184, 0 , 8666 , 292, 149), // #1334 - INST(Vpmulld , VexRvm_Lx , V(660F38,40,_,x,I,0,4,FV ), 0 , 163, 0 , 8674 , 207, 133), // #1335 - INST(Vpmullq , VexRvm_Lx , E(660F38,40,_,x,_,1,4,FV ), 0 , 112, 0 , 8682 , 210, 131), // #1336 - INST(Vpmullw , VexRvm_Lx , V(660F00,D5,_,x,I,I,4,FVM), 0 , 184, 0 , 8690 , 292, 149), // #1337 - INST(Vpmultishiftqb , VexRvm_Lx , E(660F38,83,_,x,_,1,4,FV ), 0 , 112, 0 , 8698 , 210, 156), // #1338 - INST(Vpmuludq , VexRvm_Lx , V(660F00,F4,_,x,I,1,4,FV ), 0 , 104, 0 , 8713 , 206, 133), // #1339 - INST(Vpopcntb , VexRm_Lx , E(660F38,54,_,x,_,0,4,FV ), 0 , 113, 0 , 8722 , 261, 160), // #1340 - INST(Vpopcntd , VexRm_Lx , E(660F38,55,_,x,_,0,4,FVM), 0 , 189, 0 , 8731 , 346, 161), // #1341 - INST(Vpopcntq , VexRm_Lx , E(660F38,55,_,x,_,1,4,FVM), 0 , 190, 0 , 8740 , 360, 161), // #1342 - INST(Vpopcntw , VexRm_Lx , E(660F38,54,_,x,_,1,4,FV ), 0 , 112, 0 , 8749 , 261, 160), // #1343 - INST(Vpor , VexRvm_Lx , V(660F00,EB,_,x,I,_,_,_ ), 0 , 70 , 0 , 8758 , 323, 146), // #1344 - INST(Vpord , VexRvm_Lx , E(660F00,EB,_,x,_,0,4,FV ), 0 , 188, 0 , 8763 , 324, 129), // #1345 - INST(Vporq , VexRvm_Lx , E(660F00,EB,_,x,_,1,4,FV ), 0 , 130, 0 , 8769 , 328, 129), // #1346 - INST(Vpperm , VexRvrmRvmr , V(XOP_M8,A3,_,0,x,_,_,_ ), 0 , 195, 0 , 8775 , 370, 142), // #1347 - INST(Vprold , VexVmi_Lx , E(660F00,72,1,x,_,0,4,FV ), 0 , 211, 0 , 8782 , 371, 129), // #1348 - INST(Vprolq , VexVmi_Lx , E(660F00,72,1,x,_,1,4,FV ), 0 , 212, 0 , 8789 , 372, 129), // #1349 - INST(Vprolvd , VexRvm_Lx , E(660F38,15,_,x,_,0,4,FV ), 0 , 113, 0 , 8796 , 211, 129), // #1350 - INST(Vprolvq , VexRvm_Lx , E(660F38,15,_,x,_,1,4,FV ), 0 , 112, 0 , 8804 , 210, 129), // #1351 - INST(Vprord , VexVmi_Lx , E(660F00,72,0,x,_,0,4,FV ), 0 , 188, 0 , 8812 , 371, 129), // #1352 - INST(Vprorq , VexVmi_Lx , E(660F00,72,0,x,_,1,4,FV ), 0 , 130, 0 , 8819 , 372, 129), // #1353 - INST(Vprorvd , VexRvm_Lx , E(660F38,14,_,x,_,0,4,FV ), 0 , 113, 0 , 8826 , 211, 129), // #1354 - INST(Vprorvq , VexRvm_Lx , E(660F38,14,_,x,_,1,4,FV ), 0 , 112, 0 , 8834 , 210, 129), // #1355 - INST(Vprotb , VexRvmRmvRmi , V(XOP_M9,90,_,0,x,_,_,_ ), V(XOP_M8,C0,_,0,x,_,_,_ ), 80 , 121, 8842 , 373, 142), // #1356 - INST(Vprotd , VexRvmRmvRmi , V(XOP_M9,92,_,0,x,_,_,_ ), V(XOP_M8,C2,_,0,x,_,_,_ ), 80 , 122, 8849 , 373, 142), // #1357 - INST(Vprotq , VexRvmRmvRmi , V(XOP_M9,93,_,0,x,_,_,_ ), V(XOP_M8,C3,_,0,x,_,_,_ ), 80 , 123, 8856 , 373, 142), // #1358 - INST(Vprotw , VexRvmRmvRmi , V(XOP_M9,91,_,0,x,_,_,_ ), V(XOP_M8,C1,_,0,x,_,_,_ ), 80 , 124, 8863 , 373, 142), // #1359 - INST(Vpsadbw , VexRvm_Lx , V(660F00,F6,_,x,I,I,4,FVM), 0 , 184, 0 , 8870 , 201, 149), // #1360 - INST(Vpscatterdd , VexMr_VM , E(660F38,A0,_,x,_,0,2,T1S), 0 , 125, 0 , 8878 , 374, 129), // #1361 - INST(Vpscatterdq , VexMr_VM , E(660F38,A0,_,x,_,1,3,T1S), 0 , 124, 0 , 8890 , 375, 129), // #1362 - INST(Vpscatterqd , VexMr_VM , E(660F38,A1,_,x,_,0,2,T1S), 0 , 125, 0 , 8902 , 376, 129), // #1363 - INST(Vpscatterqq , VexMr_VM , E(660F38,A1,_,x,_,1,3,T1S), 0 , 124, 0 , 8914 , 377, 129), // #1364 - INST(Vpshab , VexRvmRmv , V(XOP_M9,98,_,0,x,_,_,_ ), 0 , 80 , 0 , 8926 , 378, 142), // #1365 - INST(Vpshad , VexRvmRmv , V(XOP_M9,9A,_,0,x,_,_,_ ), 0 , 80 , 0 , 8933 , 378, 142), // #1366 - INST(Vpshaq , VexRvmRmv , V(XOP_M9,9B,_,0,x,_,_,_ ), 0 , 80 , 0 , 8940 , 378, 142), // #1367 - INST(Vpshaw , VexRvmRmv , V(XOP_M9,99,_,0,x,_,_,_ ), 0 , 80 , 0 , 8947 , 378, 142), // #1368 - INST(Vpshlb , VexRvmRmv , V(XOP_M9,94,_,0,x,_,_,_ ), 0 , 80 , 0 , 8954 , 378, 142), // #1369 - INST(Vpshld , VexRvmRmv , V(XOP_M9,96,_,0,x,_,_,_ ), 0 , 80 , 0 , 8961 , 378, 142), // #1370 - INST(Vpshldd , VexRvmi_Lx , E(660F3A,71,_,x,_,0,4,FV ), 0 , 110, 0 , 8968 , 204, 154), // #1371 - INST(Vpshldq , VexRvmi_Lx , E(660F3A,71,_,x,_,1,4,FV ), 0 , 111, 0 , 8976 , 205, 154), // #1372 - INST(Vpshldvd , VexRvm_Lx , E(660F38,71,_,x,_,0,4,FV ), 0 , 113, 0 , 8984 , 211, 154), // #1373 - INST(Vpshldvq , VexRvm_Lx , E(660F38,71,_,x,_,1,4,FV ), 0 , 112, 0 , 8993 , 210, 154), // #1374 - INST(Vpshldvw , VexRvm_Lx , E(660F38,70,_,x,_,1,4,FVM), 0 , 190, 0 , 9002 , 329, 154), // #1375 - INST(Vpshldw , VexRvmi_Lx , E(660F3A,70,_,x,_,1,4,FVM), 0 , 197, 0 , 9011 , 257, 154), // #1376 - INST(Vpshlq , VexRvmRmv , V(XOP_M9,97,_,0,x,_,_,_ ), 0 , 80 , 0 , 9019 , 378, 142), // #1377 - INST(Vpshlw , VexRvmRmv , V(XOP_M9,95,_,0,x,_,_,_ ), 0 , 80 , 0 , 9026 , 378, 142), // #1378 - INST(Vpshrdd , VexRvmi_Lx , E(660F3A,73,_,x,_,0,4,FV ), 0 , 110, 0 , 9033 , 204, 154), // #1379 - INST(Vpshrdq , VexRvmi_Lx , E(660F3A,73,_,x,_,1,4,FV ), 0 , 111, 0 , 9041 , 205, 154), // #1380 - INST(Vpshrdvd , VexRvm_Lx , E(660F38,73,_,x,_,0,4,FV ), 0 , 113, 0 , 9049 , 211, 154), // #1381 - INST(Vpshrdvq , VexRvm_Lx , E(660F38,73,_,x,_,1,4,FV ), 0 , 112, 0 , 9058 , 210, 154), // #1382 - INST(Vpshrdvw , VexRvm_Lx , E(660F38,72,_,x,_,1,4,FVM), 0 , 190, 0 , 9067 , 329, 154), // #1383 - INST(Vpshrdw , VexRvmi_Lx , E(660F3A,72,_,x,_,1,4,FVM), 0 , 197, 0 , 9076 , 257, 154), // #1384 - INST(Vpshufb , VexRvm_Lx , V(660F38,00,_,x,I,I,4,FVM), 0 , 109, 0 , 9084 , 292, 149), // #1385 - INST(Vpshufbitqmb , VexRvm_Lx , E(660F38,8F,_,x,0,0,4,FVM), 0 , 189, 0 , 9092 , 379, 160), // #1386 - INST(Vpshufd , VexRmi_Lx , V(660F00,70,_,x,I,0,4,FV ), 0 , 133, 0 , 9105 , 380, 133), // #1387 - INST(Vpshufhw , VexRmi_Lx , V(F30F00,70,_,x,I,I,4,FVM), 0 , 185, 0 , 9113 , 381, 149), // #1388 - INST(Vpshuflw , VexRmi_Lx , V(F20F00,70,_,x,I,I,4,FVM), 0 , 213, 0 , 9122 , 381, 149), // #1389 - INST(Vpsignb , VexRvm_Lx , V(660F38,08,_,x,I,_,_,_ ), 0 , 97 , 0 , 9131 , 200, 146), // #1390 - INST(Vpsignd , VexRvm_Lx , V(660F38,0A,_,x,I,_,_,_ ), 0 , 97 , 0 , 9139 , 200, 146), // #1391 - INST(Vpsignw , VexRvm_Lx , V(660F38,09,_,x,I,_,_,_ ), 0 , 97 , 0 , 9147 , 200, 146), // #1392 - INST(Vpslld , VexRvmVmi_Lx_MEvex , V(660F00,F2,_,x,I,0,4,128), V(660F00,72,6,x,I,0,4,FV ), 214, 125, 9155 , 382, 133), // #1393 - INST(Vpslldq , VexVmi_Lx_MEvex , V(660F00,73,7,x,I,I,4,FVM), 0 , 215, 0 , 9162 , 383, 149), // #1394 - INST(Vpsllq , VexRvmVmi_Lx_MEvex , V(660F00,F3,_,x,I,1,4,128), V(660F00,73,6,x,I,1,4,FV ), 216, 126, 9170 , 384, 133), // #1395 - INST(Vpsllvd , VexRvm_Lx , V(660F38,47,_,x,0,0,4,FV ), 0 , 163, 0 , 9177 , 207, 143), // #1396 - INST(Vpsllvq , VexRvm_Lx , V(660F38,47,_,x,1,1,4,FV ), 0 , 162, 0 , 9185 , 206, 143), // #1397 - INST(Vpsllvw , VexRvm_Lx , E(660F38,12,_,x,_,1,4,FVM), 0 , 190, 0 , 9193 , 329, 137), // #1398 - INST(Vpsllw , VexRvmVmi_Lx_MEvex , V(660F00,F1,_,x,I,I,4,128), V(660F00,71,6,x,I,I,4,FVM), 214, 127, 9201 , 385, 149), // #1399 - INST(Vpsrad , VexRvmVmi_Lx_MEvex , V(660F00,E2,_,x,I,0,4,128), V(660F00,72,4,x,I,0,4,FV ), 214, 128, 9208 , 382, 133), // #1400 - INST(Vpsraq , VexRvmVmi_Lx_MEvex , E(660F00,E2,_,x,_,1,4,128), E(660F00,72,4,x,_,1,4,FV ), 217, 129, 9215 , 386, 129), // #1401 - INST(Vpsravd , VexRvm_Lx , V(660F38,46,_,x,0,0,4,FV ), 0 , 163, 0 , 9222 , 207, 143), // #1402 - INST(Vpsravq , VexRvm_Lx , E(660F38,46,_,x,_,1,4,FV ), 0 , 112, 0 , 9230 , 210, 129), // #1403 - INST(Vpsravw , VexRvm_Lx , E(660F38,11,_,x,_,1,4,FVM), 0 , 190, 0 , 9238 , 329, 137), // #1404 - INST(Vpsraw , VexRvmVmi_Lx_MEvex , V(660F00,E1,_,x,I,I,4,128), V(660F00,71,4,x,I,I,4,FVM), 214, 130, 9246 , 385, 149), // #1405 - INST(Vpsrld , VexRvmVmi_Lx_MEvex , V(660F00,D2,_,x,I,0,4,128), V(660F00,72,2,x,I,0,4,FV ), 214, 131, 9253 , 382, 133), // #1406 - INST(Vpsrldq , VexVmi_Lx_MEvex , V(660F00,73,3,x,I,I,4,FVM), 0 , 218, 0 , 9260 , 383, 149), // #1407 - INST(Vpsrlq , VexRvmVmi_Lx_MEvex , V(660F00,D3,_,x,I,1,4,128), V(660F00,73,2,x,I,1,4,FV ), 216, 132, 9268 , 384, 133), // #1408 - INST(Vpsrlvd , VexRvm_Lx , V(660F38,45,_,x,0,0,4,FV ), 0 , 163, 0 , 9275 , 207, 143), // #1409 - INST(Vpsrlvq , VexRvm_Lx , V(660F38,45,_,x,1,1,4,FV ), 0 , 162, 0 , 9283 , 206, 143), // #1410 - INST(Vpsrlvw , VexRvm_Lx , E(660F38,10,_,x,_,1,4,FVM), 0 , 190, 0 , 9291 , 329, 137), // #1411 - INST(Vpsrlw , VexRvmVmi_Lx_MEvex , V(660F00,D1,_,x,I,I,4,128), V(660F00,71,2,x,I,I,4,FVM), 214, 133, 9299 , 385, 149), // #1412 - INST(Vpsubb , VexRvm_Lx , V(660F00,F8,_,x,I,I,4,FVM), 0 , 184, 0 , 9306 , 387, 149), // #1413 - INST(Vpsubd , VexRvm_Lx , V(660F00,FA,_,x,I,0,4,FV ), 0 , 133, 0 , 9313 , 388, 133), // #1414 - INST(Vpsubq , VexRvm_Lx , V(660F00,FB,_,x,I,1,4,FV ), 0 , 104, 0 , 9320 , 389, 133), // #1415 - INST(Vpsubsb , VexRvm_Lx , V(660F00,E8,_,x,I,I,4,FVM), 0 , 184, 0 , 9327 , 387, 149), // #1416 - INST(Vpsubsw , VexRvm_Lx , V(660F00,E9,_,x,I,I,4,FVM), 0 , 184, 0 , 9335 , 387, 149), // #1417 - INST(Vpsubusb , VexRvm_Lx , V(660F00,D8,_,x,I,I,4,FVM), 0 , 184, 0 , 9343 , 387, 149), // #1418 - INST(Vpsubusw , VexRvm_Lx , V(660F00,D9,_,x,I,I,4,FVM), 0 , 184, 0 , 9352 , 387, 149), // #1419 - INST(Vpsubw , VexRvm_Lx , V(660F00,F9,_,x,I,I,4,FVM), 0 , 184, 0 , 9361 , 387, 149), // #1420 - INST(Vpternlogd , VexRvmi_Lx , E(660F3A,25,_,x,_,0,4,FV ), 0 , 110, 0 , 9368 , 204, 129), // #1421 - INST(Vpternlogq , VexRvmi_Lx , E(660F3A,25,_,x,_,1,4,FV ), 0 , 111, 0 , 9379 , 205, 129), // #1422 - INST(Vptest , VexRm_Lx , V(660F38,17,_,x,I,_,_,_ ), 0 , 97 , 0 , 9390 , 277, 153), // #1423 - INST(Vptestmb , VexRvm_Lx , E(660F38,26,_,x,_,0,4,FVM), 0 , 189, 0 , 9397 , 379, 137), // #1424 - INST(Vptestmd , VexRvm_Lx , E(660F38,27,_,x,_,0,4,FV ), 0 , 113, 0 , 9406 , 390, 129), // #1425 - INST(Vptestmq , VexRvm_Lx , E(660F38,27,_,x,_,1,4,FV ), 0 , 112, 0 , 9415 , 391, 129), // #1426 - INST(Vptestmw , VexRvm_Lx , E(660F38,26,_,x,_,1,4,FVM), 0 , 190, 0 , 9424 , 379, 137), // #1427 - INST(Vptestnmb , VexRvm_Lx , E(F30F38,26,_,x,_,0,4,FVM), 0 , 219, 0 , 9433 , 379, 137), // #1428 - INST(Vptestnmd , VexRvm_Lx , E(F30F38,27,_,x,_,0,4,FV ), 0 , 128, 0 , 9443 , 390, 129), // #1429 - INST(Vptestnmq , VexRvm_Lx , E(F30F38,27,_,x,_,1,4,FV ), 0 , 220, 0 , 9453 , 391, 129), // #1430 - INST(Vptestnmw , VexRvm_Lx , E(F30F38,26,_,x,_,1,4,FVM), 0 , 221, 0 , 9463 , 379, 137), // #1431 - INST(Vpunpckhbw , VexRvm_Lx , V(660F00,68,_,x,I,I,4,FVM), 0 , 184, 0 , 9473 , 292, 149), // #1432 - INST(Vpunpckhdq , VexRvm_Lx , V(660F00,6A,_,x,I,0,4,FV ), 0 , 133, 0 , 9484 , 207, 133), // #1433 - INST(Vpunpckhqdq , VexRvm_Lx , V(660F00,6D,_,x,I,1,4,FV ), 0 , 104, 0 , 9495 , 206, 133), // #1434 - INST(Vpunpckhwd , VexRvm_Lx , V(660F00,69,_,x,I,I,4,FVM), 0 , 184, 0 , 9507 , 292, 149), // #1435 - INST(Vpunpcklbw , VexRvm_Lx , V(660F00,60,_,x,I,I,4,FVM), 0 , 184, 0 , 9518 , 292, 149), // #1436 - INST(Vpunpckldq , VexRvm_Lx , V(660F00,62,_,x,I,0,4,FV ), 0 , 133, 0 , 9529 , 207, 133), // #1437 - INST(Vpunpcklqdq , VexRvm_Lx , V(660F00,6C,_,x,I,1,4,FV ), 0 , 104, 0 , 9540 , 206, 133), // #1438 - INST(Vpunpcklwd , VexRvm_Lx , V(660F00,61,_,x,I,I,4,FVM), 0 , 184, 0 , 9552 , 292, 149), // #1439 - INST(Vpxor , VexRvm_Lx , V(660F00,EF,_,x,I,_,_,_ ), 0 , 70 , 0 , 9563 , 325, 146), // #1440 - INST(Vpxord , VexRvm_Lx , E(660F00,EF,_,x,_,0,4,FV ), 0 , 188, 0 , 9569 , 326, 129), // #1441 - INST(Vpxorq , VexRvm_Lx , E(660F00,EF,_,x,_,1,4,FV ), 0 , 130, 0 , 9576 , 327, 129), // #1442 - INST(Vrangepd , VexRvmi_Lx , E(660F3A,50,_,x,_,1,4,FV ), 0 , 111, 0 , 9583 , 266, 131), // #1443 - INST(Vrangeps , VexRvmi_Lx , E(660F3A,50,_,x,_,0,4,FV ), 0 , 110, 0 , 9592 , 267, 131), // #1444 - INST(Vrangesd , VexRvmi , E(660F3A,51,_,I,_,1,3,T1S), 0 , 160, 0 , 9601 , 268, 66 ), // #1445 - INST(Vrangess , VexRvmi , E(660F3A,51,_,I,_,0,2,T1S), 0 , 161, 0 , 9610 , 269, 66 ), // #1446 - INST(Vrcp14pd , VexRm_Lx , E(660F38,4C,_,x,_,1,4,FV ), 0 , 112, 0 , 9619 , 360, 129), // #1447 - INST(Vrcp14ps , VexRm_Lx , E(660F38,4C,_,x,_,0,4,FV ), 0 , 113, 0 , 9628 , 346, 129), // #1448 - INST(Vrcp14sd , VexRvm , E(660F38,4D,_,I,_,1,3,T1S), 0 , 124, 0 , 9637 , 392, 68 ), // #1449 - INST(Vrcp14ss , VexRvm , E(660F38,4D,_,I,_,0,2,T1S), 0 , 125, 0 , 9646 , 393, 68 ), // #1450 - INST(Vrcp28pd , VexRm , E(660F38,CA,_,2,_,1,4,FV ), 0 , 152, 0 , 9655 , 259, 138), // #1451 - INST(Vrcp28ps , VexRm , E(660F38,CA,_,2,_,0,4,FV ), 0 , 153, 0 , 9664 , 260, 138), // #1452 - INST(Vrcp28sd , VexRvm , E(660F38,CB,_,I,_,1,3,T1S), 0 , 124, 0 , 9673 , 287, 138), // #1453 - INST(Vrcp28ss , VexRvm , E(660F38,CB,_,I,_,0,2,T1S), 0 , 125, 0 , 9682 , 288, 138), // #1454 - INST(Vrcpps , VexRm_Lx , V(000F00,53,_,x,I,_,_,_ ), 0 , 73 , 0 , 9691 , 277, 126), // #1455 - INST(Vrcpss , VexRvm , V(F30F00,53,_,I,I,_,_,_ ), 0 , 178, 0 , 9698 , 394, 126), // #1456 - INST(Vreducepd , VexRmi_Lx , E(660F3A,56,_,x,_,1,4,FV ), 0 , 111, 0 , 9705 , 372, 131), // #1457 - INST(Vreduceps , VexRmi_Lx , E(660F3A,56,_,x,_,0,4,FV ), 0 , 110, 0 , 9715 , 371, 131), // #1458 - INST(Vreducesd , VexRvmi , E(660F3A,57,_,I,_,1,3,T1S), 0 , 160, 0 , 9725 , 395, 66 ), // #1459 - INST(Vreducess , VexRvmi , E(660F3A,57,_,I,_,0,2,T1S), 0 , 161, 0 , 9735 , 396, 66 ), // #1460 - INST(Vrndscalepd , VexRmi_Lx , E(660F3A,09,_,x,_,1,4,FV ), 0 , 111, 0 , 9745 , 289, 129), // #1461 - INST(Vrndscaleps , VexRmi_Lx , E(660F3A,08,_,x,_,0,4,FV ), 0 , 110, 0 , 9757 , 290, 129), // #1462 - INST(Vrndscalesd , VexRvmi , E(660F3A,0B,_,I,_,1,3,T1S), 0 , 160, 0 , 9769 , 268, 68 ), // #1463 - INST(Vrndscaless , VexRvmi , E(660F3A,0A,_,I,_,0,2,T1S), 0 , 161, 0 , 9781 , 269, 68 ), // #1464 - INST(Vroundpd , VexRmi_Lx , V(660F3A,09,_,x,I,_,_,_ ), 0 , 74 , 0 , 9793 , 397, 126), // #1465 - INST(Vroundps , VexRmi_Lx , V(660F3A,08,_,x,I,_,_,_ ), 0 , 74 , 0 , 9802 , 397, 126), // #1466 - INST(Vroundsd , VexRvmi , V(660F3A,0B,_,I,I,_,_,_ ), 0 , 74 , 0 , 9811 , 398, 126), // #1467 - INST(Vroundss , VexRvmi , V(660F3A,0A,_,I,I,_,_,_ ), 0 , 74 , 0 , 9820 , 399, 126), // #1468 - INST(Vrsqrt14pd , VexRm_Lx , E(660F38,4E,_,x,_,1,4,FV ), 0 , 112, 0 , 9829 , 360, 129), // #1469 - INST(Vrsqrt14ps , VexRm_Lx , E(660F38,4E,_,x,_,0,4,FV ), 0 , 113, 0 , 9840 , 346, 129), // #1470 - INST(Vrsqrt14sd , VexRvm , E(660F38,4F,_,I,_,1,3,T1S), 0 , 124, 0 , 9851 , 392, 68 ), // #1471 - INST(Vrsqrt14ss , VexRvm , E(660F38,4F,_,I,_,0,2,T1S), 0 , 125, 0 , 9862 , 393, 68 ), // #1472 - INST(Vrsqrt28pd , VexRm , E(660F38,CC,_,2,_,1,4,FV ), 0 , 152, 0 , 9873 , 259, 138), // #1473 - INST(Vrsqrt28ps , VexRm , E(660F38,CC,_,2,_,0,4,FV ), 0 , 153, 0 , 9884 , 260, 138), // #1474 - INST(Vrsqrt28sd , VexRvm , E(660F38,CD,_,I,_,1,3,T1S), 0 , 124, 0 , 9895 , 287, 138), // #1475 - INST(Vrsqrt28ss , VexRvm , E(660F38,CD,_,I,_,0,2,T1S), 0 , 125, 0 , 9906 , 288, 138), // #1476 - INST(Vrsqrtps , VexRm_Lx , V(000F00,52,_,x,I,_,_,_ ), 0 , 73 , 0 , 9917 , 277, 126), // #1477 - INST(Vrsqrtss , VexRvm , V(F30F00,52,_,I,I,_,_,_ ), 0 , 178, 0 , 9926 , 394, 126), // #1478 - INST(Vscalefpd , VexRvm_Lx , E(660F38,2C,_,x,_,1,4,FV ), 0 , 112, 0 , 9935 , 400, 129), // #1479 - INST(Vscalefps , VexRvm_Lx , E(660F38,2C,_,x,_,0,4,FV ), 0 , 113, 0 , 9945 , 401, 129), // #1480 - INST(Vscalefsd , VexRvm , E(660F38,2D,_,I,_,1,3,T1S), 0 , 124, 0 , 9955 , 402, 68 ), // #1481 - INST(Vscalefss , VexRvm , E(660F38,2D,_,I,_,0,2,T1S), 0 , 125, 0 , 9965 , 403, 68 ), // #1482 - INST(Vscatterdpd , VexMr_VM , E(660F38,A2,_,x,_,1,3,T1S), 0 , 124, 0 , 9975 , 375, 129), // #1483 - INST(Vscatterdps , VexMr_VM , E(660F38,A2,_,x,_,0,2,T1S), 0 , 125, 0 , 9987 , 374, 129), // #1484 - INST(Vscatterpf0dpd , VexM_VM , E(660F38,C6,5,2,_,1,3,T1S), 0 , 222, 0 , 9999 , 282, 144), // #1485 - INST(Vscatterpf0dps , VexM_VM , E(660F38,C6,5,2,_,0,2,T1S), 0 , 223, 0 , 10014, 283, 144), // #1486 - INST(Vscatterpf0qpd , VexM_VM , E(660F38,C7,5,2,_,1,3,T1S), 0 , 222, 0 , 10029, 284, 144), // #1487 - INST(Vscatterpf0qps , VexM_VM , E(660F38,C7,5,2,_,0,2,T1S), 0 , 223, 0 , 10044, 284, 144), // #1488 - INST(Vscatterpf1dpd , VexM_VM , E(660F38,C6,6,2,_,1,3,T1S), 0 , 224, 0 , 10059, 282, 144), // #1489 - INST(Vscatterpf1dps , VexM_VM , E(660F38,C6,6,2,_,0,2,T1S), 0 , 225, 0 , 10074, 283, 144), // #1490 - INST(Vscatterpf1qpd , VexM_VM , E(660F38,C7,6,2,_,1,3,T1S), 0 , 224, 0 , 10089, 284, 144), // #1491 - INST(Vscatterpf1qps , VexM_VM , E(660F38,C7,6,2,_,0,2,T1S), 0 , 225, 0 , 10104, 284, 144), // #1492 - INST(Vscatterqpd , VexMr_VM , E(660F38,A3,_,x,_,1,3,T1S), 0 , 124, 0 , 10119, 377, 129), // #1493 - INST(Vscatterqps , VexMr_VM , E(660F38,A3,_,x,_,0,2,T1S), 0 , 125, 0 , 10131, 376, 129), // #1494 - INST(Vshuff32x4 , VexRvmi_Lx , E(660F3A,23,_,x,_,0,4,FV ), 0 , 110, 0 , 10143, 404, 129), // #1495 - INST(Vshuff64x2 , VexRvmi_Lx , E(660F3A,23,_,x,_,1,4,FV ), 0 , 111, 0 , 10154, 405, 129), // #1496 - INST(Vshufi32x4 , VexRvmi_Lx , E(660F3A,43,_,x,_,0,4,FV ), 0 , 110, 0 , 10165, 404, 129), // #1497 - INST(Vshufi64x2 , VexRvmi_Lx , E(660F3A,43,_,x,_,1,4,FV ), 0 , 111, 0 , 10176, 405, 129), // #1498 - INST(Vshufpd , VexRvmi_Lx , V(660F00,C6,_,x,I,1,4,FV ), 0 , 104, 0 , 10187, 406, 124), // #1499 - INST(Vshufps , VexRvmi_Lx , V(000F00,C6,_,x,I,0,4,FV ), 0 , 105, 0 , 10195, 407, 124), // #1500 - INST(Vsqrtpd , VexRm_Lx , V(660F00,51,_,x,I,1,4,FV ), 0 , 104, 0 , 10203, 408, 124), // #1501 - INST(Vsqrtps , VexRm_Lx , V(000F00,51,_,x,I,0,4,FV ), 0 , 105, 0 , 10211, 229, 124), // #1502 - INST(Vsqrtsd , VexRvm , V(F20F00,51,_,I,I,1,3,T1S), 0 , 106, 0 , 10219, 198, 125), // #1503 - INST(Vsqrtss , VexRvm , V(F30F00,51,_,I,I,0,2,T1S), 0 , 107, 0 , 10227, 199, 125), // #1504 - INST(Vstmxcsr , VexM , V(000F00,AE,3,0,I,_,_,_ ), 0 , 226, 0 , 10235, 298, 126), // #1505 - INST(Vsubpd , VexRvm_Lx , V(660F00,5C,_,x,I,1,4,FV ), 0 , 104, 0 , 10244, 196, 124), // #1506 - INST(Vsubps , VexRvm_Lx , V(000F00,5C,_,x,I,0,4,FV ), 0 , 105, 0 , 10251, 197, 124), // #1507 - INST(Vsubsd , VexRvm , V(F20F00,5C,_,I,I,1,3,T1S), 0 , 106, 0 , 10258, 198, 125), // #1508 - INST(Vsubss , VexRvm , V(F30F00,5C,_,I,I,0,2,T1S), 0 , 107, 0 , 10265, 199, 125), // #1509 - INST(Vtestpd , VexRm_Lx , V(660F38,0F,_,x,0,_,_,_ ), 0 , 97 , 0 , 10272, 277, 153), // #1510 - INST(Vtestps , VexRm_Lx , V(660F38,0E,_,x,0,_,_,_ ), 0 , 97 , 0 , 10280, 277, 153), // #1511 - INST(Vucomisd , VexRm , V(660F00,2E,_,I,I,1,3,T1S), 0 , 122, 0 , 10288, 225, 134), // #1512 - INST(Vucomiss , VexRm , V(000F00,2E,_,I,I,0,2,T1S), 0 , 123, 0 , 10297, 226, 134), // #1513 - INST(Vunpckhpd , VexRvm_Lx , V(660F00,15,_,x,I,1,4,FV ), 0 , 104, 0 , 10306, 206, 124), // #1514 - INST(Vunpckhps , VexRvm_Lx , V(000F00,15,_,x,I,0,4,FV ), 0 , 105, 0 , 10316, 207, 124), // #1515 - INST(Vunpcklpd , VexRvm_Lx , V(660F00,14,_,x,I,1,4,FV ), 0 , 104, 0 , 10326, 206, 124), // #1516 - INST(Vunpcklps , VexRvm_Lx , V(000F00,14,_,x,I,0,4,FV ), 0 , 105, 0 , 10336, 207, 124), // #1517 - INST(Vxorpd , VexRvm_Lx , V(660F00,57,_,x,I,1,4,FV ), 0 , 104, 0 , 10346, 389, 130), // #1518 - INST(Vxorps , VexRvm_Lx , V(000F00,57,_,x,I,0,4,FV ), 0 , 105, 0 , 10353, 388, 130), // #1519 - INST(Vzeroall , VexOp , V(000F00,77,_,1,I,_,_,_ ), 0 , 69 , 0 , 10360, 409, 126), // #1520 - INST(Vzeroupper , VexOp , V(000F00,77,_,0,I,_,_,_ ), 0 , 73 , 0 , 10369, 409, 126), // #1521 - INST(Wbinvd , X86Op , O(000F00,09,_,_,_,_,_,_ ), 0 , 4 , 0 , 10380, 30 , 0 ), // #1522 - INST(Wbnoinvd , X86Op , O(F30F00,09,_,_,_,_,_,_ ), 0 , 6 , 0 , 10387, 30 , 162), // #1523 - INST(Wrfsbase , X86M , O(F30F00,AE,2,_,x,_,_,_ ), 0 , 227, 0 , 10396, 173, 104), // #1524 - INST(Wrgsbase , X86M , O(F30F00,AE,3,_,x,_,_,_ ), 0 , 228, 0 , 10405, 173, 104), // #1525 - INST(Wrmsr , X86Op , O(000F00,30,_,_,_,_,_,_ ), 0 , 4 , 0 , 10414, 174, 105), // #1526 - INST(Wrssd , X86Mr , O(000F38,F6,_,_,_,_,_,_ ), 0 , 84 , 0 , 10420, 410, 56 ), // #1527 - INST(Wrssq , X86Mr , O(000F38,F6,_,_,1,_,_,_ ), 0 , 229, 0 , 10426, 411, 56 ), // #1528 - INST(Wrussd , X86Mr , O(660F38,F5,_,_,_,_,_,_ ), 0 , 2 , 0 , 10432, 410, 56 ), // #1529 - INST(Wrussq , X86Mr , O(660F38,F5,_,_,1,_,_,_ ), 0 , 230, 0 , 10439, 411, 56 ), // #1530 - INST(Xabort , X86Op_Mod11RM_I8 , O(000000,C6,7,_,_,_,_,_ ), 0 , 27 , 0 , 10446, 80 , 163), // #1531 - INST(Xadd , X86Xadd , O(000F00,C0,_,_,x,_,_,_ ), 0 , 4 , 0 , 10453, 412, 38 ), // #1532 - INST(Xbegin , X86JmpRel , O(000000,C7,7,_,_,_,_,_ ), 0 , 27 , 0 , 10458, 413, 163), // #1533 - INST(Xchg , X86Xchg , O(000000,86,_,_,x,_,_,_ ), 0 , 0 , 0 , 462 , 414, 0 ), // #1534 - INST(Xend , X86Op , O(000F01,D5,_,_,_,_,_,_ ), 0 , 21 , 0 , 10465, 30 , 163), // #1535 - INST(Xgetbv , X86Op , O(000F01,D0,_,_,_,_,_,_ ), 0 , 21 , 0 , 10470, 174, 164), // #1536 - INST(Xlatb , X86Op , O(000000,D7,_,_,_,_,_,_ ), 0 , 0 , 0 , 10477, 30 , 0 ), // #1537 - INST(Xor , X86Arith , O(000000,30,6,_,x,_,_,_ ), 0 , 32 , 0 , 9565 , 179, 1 ), // #1538 - INST(Xorpd , ExtRm , O(660F00,57,_,_,_,_,_,_ ), 0 , 3 , 0 , 10347, 151, 4 ), // #1539 - INST(Xorps , ExtRm , O(000F00,57,_,_,_,_,_,_ ), 0 , 4 , 0 , 10354, 151, 5 ), // #1540 - INST(Xresldtrk , X86Op , O(F20F01,E9,_,_,_,_,_,_ ), 0 , 93 , 0 , 10483, 30 , 165), // #1541 - INST(Xrstor , X86M_Only_EDX_EAX , O(000F00,AE,5,_,_,_,_,_ ), 0 , 78 , 0 , 1164 , 415, 164), // #1542 - INST(Xrstor64 , X86M_Only_EDX_EAX , O(000F00,AE,5,_,1,_,_,_ ), 0 , 231, 0 , 1172 , 416, 164), // #1543 - INST(Xrstors , X86M_Only_EDX_EAX , O(000F00,C7,3,_,_,_,_,_ ), 0 , 79 , 0 , 10493, 415, 166), // #1544 - INST(Xrstors64 , X86M_Only_EDX_EAX , O(000F00,C7,3,_,1,_,_,_ ), 0 , 232, 0 , 10501, 416, 166), // #1545 - INST(Xsave , X86M_Only_EDX_EAX , O(000F00,AE,4,_,_,_,_,_ ), 0 , 98 , 0 , 1182 , 415, 164), // #1546 - INST(Xsave64 , X86M_Only_EDX_EAX , O(000F00,AE,4,_,1,_,_,_ ), 0 , 233, 0 , 1189 , 416, 164), // #1547 - INST(Xsavec , X86M_Only_EDX_EAX , O(000F00,C7,4,_,_,_,_,_ ), 0 , 98 , 0 , 10511, 415, 167), // #1548 - INST(Xsavec64 , X86M_Only_EDX_EAX , O(000F00,C7,4,_,1,_,_,_ ), 0 , 233, 0 , 10518, 416, 167), // #1549 - INST(Xsaveopt , X86M_Only_EDX_EAX , O(000F00,AE,6,_,_,_,_,_ ), 0 , 81 , 0 , 10527, 415, 168), // #1550 - INST(Xsaveopt64 , X86M_Only_EDX_EAX , O(000F00,AE,6,_,1,_,_,_ ), 0 , 234, 0 , 10536, 416, 168), // #1551 - INST(Xsaves , X86M_Only_EDX_EAX , O(000F00,C7,5,_,_,_,_,_ ), 0 , 78 , 0 , 10547, 415, 166), // #1552 - INST(Xsaves64 , X86M_Only_EDX_EAX , O(000F00,C7,5,_,1,_,_,_ ), 0 , 231, 0 , 10554, 416, 166), // #1553 - INST(Xsetbv , X86Op , O(000F01,D1,_,_,_,_,_,_ ), 0 , 21 , 0 , 10563, 174, 164), // #1554 - INST(Xsusldtrk , X86Op , O(F20F01,E8,_,_,_,_,_,_ ), 0 , 93 , 0 , 10570, 30 , 165), // #1555 - INST(Xtest , X86Op , O(000F01,D6,_,_,_,_,_,_ ), 0 , 21 , 0 , 10580, 30 , 169) // #1556 + INST(Umwait , X86R32_EDX_EAX , O(F20F00,AE,6,_,_,_,_,_ ), 0 , 100, 0 , 3240 , 191, 121), // #793 + INST(Unpckhpd , ExtRm , O(660F00,15,_,_,_,_,_,_ ), 0 , 3 , 0 , 11417, 5 , 4 ), // #794 + INST(Unpckhps , ExtRm , O(000F00,15,_,_,_,_,_,_ ), 0 , 4 , 0 , 11427, 5 , 5 ), // #795 + INST(Unpcklpd , ExtRm , O(660F00,14,_,_,_,_,_,_ ), 0 , 3 , 0 , 11437, 5 , 4 ), // #796 + INST(Unpcklps , ExtRm , O(000F00,14,_,_,_,_,_,_ ), 0 , 4 , 0 , 11447, 5 , 5 ), // #797 + INST(V4fmaddps , VexRm_T1_4X , E(F20F38,9A,_,2,_,0,4,T4X), 0 , 101, 0 , 3247 , 194, 123), // #798 + INST(V4fmaddss , VexRm_T1_4X , E(F20F38,9B,_,0,_,0,4,T4X), 0 , 102, 0 , 3257 , 195, 123), // #799 + INST(V4fnmaddps , VexRm_T1_4X , E(F20F38,AA,_,2,_,0,4,T4X), 0 , 101, 0 , 3267 , 194, 123), // #800 + INST(V4fnmaddss , VexRm_T1_4X , E(F20F38,AB,_,0,_,0,4,T4X), 0 , 102, 0 , 3278 , 195, 123), // #801 + INST(Vaddpd , VexRvm_Lx , V(660F00,58,_,x,I,1,4,FV ), 0 , 103, 0 , 3289 , 196, 124), // #802 + INST(Vaddph , VexRvm_Lx , E(00MAP5,58,_,_,_,0,4,FV ), 0 , 104, 0 , 3296 , 197, 125), // #803 + INST(Vaddps , VexRvm_Lx , V(000F00,58,_,x,I,0,4,FV ), 0 , 105, 0 , 3303 , 198, 124), // #804 + INST(Vaddsd , VexRvm , V(F20F00,58,_,I,I,1,3,T1S), 0 , 106, 0 , 3310 , 199, 126), // #805 + INST(Vaddsh , VexRvm , E(F3MAP5,58,_,_,_,0,1,T1S), 0 , 107, 0 , 3317 , 200, 127), // #806 + INST(Vaddss , VexRvm , V(F30F00,58,_,I,I,0,2,T1S), 0 , 108, 0 , 3324 , 201, 126), // #807 + INST(Vaddsubpd , VexRvm_Lx , V(660F00,D0,_,x,I,_,_,_ ), 0 , 69 , 0 , 3331 , 202, 128), // #808 + INST(Vaddsubps , VexRvm_Lx , V(F20F00,D0,_,x,I,_,_,_ ), 0 , 109, 0 , 3341 , 202, 128), // #809 + INST(Vaesdec , VexRvm_Lx , V(660F38,DE,_,x,I,_,4,FVM), 0 , 110, 0 , 3351 , 203, 129), // #810 + INST(Vaesdeclast , VexRvm_Lx , V(660F38,DF,_,x,I,_,4,FVM), 0 , 110, 0 , 3359 , 203, 129), // #811 + INST(Vaesenc , VexRvm_Lx , V(660F38,DC,_,x,I,_,4,FVM), 0 , 110, 0 , 3371 , 203, 129), // #812 + INST(Vaesenclast , VexRvm_Lx , V(660F38,DD,_,x,I,_,4,FVM), 0 , 110, 0 , 3379 , 203, 129), // #813 + INST(Vaesimc , VexRm , V(660F38,DB,_,0,I,_,_,_ ), 0 , 96 , 0 , 3391 , 204, 130), // #814 + INST(Vaeskeygenassist , VexRmi , V(660F3A,DF,_,0,I,_,_,_ ), 0 , 73 , 0 , 3399 , 205, 130), // #815 + INST(Valignd , VexRvmi_Lx , E(660F3A,03,_,x,_,0,4,FV ), 0 , 111, 0 , 3416 , 206, 131), // #816 + INST(Valignq , VexRvmi_Lx , E(660F3A,03,_,x,_,1,4,FV ), 0 , 112, 0 , 3424 , 207, 131), // #817 + INST(Vandnpd , VexRvm_Lx , V(660F00,55,_,x,I,1,4,FV ), 0 , 103, 0 , 3432 , 208, 132), // #818 + INST(Vandnps , VexRvm_Lx , V(000F00,55,_,x,I,0,4,FV ), 0 , 105, 0 , 3440 , 209, 132), // #819 + INST(Vandpd , VexRvm_Lx , V(660F00,54,_,x,I,1,4,FV ), 0 , 103, 0 , 3448 , 210, 132), // #820 + INST(Vandps , VexRvm_Lx , V(000F00,54,_,x,I,0,4,FV ), 0 , 105, 0 , 3455 , 211, 132), // #821 + INST(Vblendmpd , VexRvm_Lx , E(660F38,65,_,x,_,1,4,FV ), 0 , 113, 0 , 3462 , 212, 131), // #822 + INST(Vblendmps , VexRvm_Lx , E(660F38,65,_,x,_,0,4,FV ), 0 , 114, 0 , 3472 , 213, 131), // #823 + INST(Vblendpd , VexRvmi_Lx , V(660F3A,0D,_,x,I,_,_,_ ), 0 , 73 , 0 , 3482 , 214, 128), // #824 + INST(Vblendps , VexRvmi_Lx , V(660F3A,0C,_,x,I,_,_,_ ), 0 , 73 , 0 , 3491 , 214, 128), // #825 + INST(Vblendvpd , VexRvmr_Lx , V(660F3A,4B,_,x,0,_,_,_ ), 0 , 73 , 0 , 3500 , 215, 128), // #826 + INST(Vblendvps , VexRvmr_Lx , V(660F3A,4A,_,x,0,_,_,_ ), 0 , 73 , 0 , 3510 , 215, 128), // #827 + INST(Vbroadcastf128 , VexRm , V(660F38,1A,_,1,0,_,_,_ ), 0 , 115, 0 , 3520 , 216, 128), // #828 + INST(Vbroadcastf32x2 , VexRm_Lx , E(660F38,19,_,x,_,0,3,T2 ), 0 , 116, 0 , 3535 , 217, 133), // #829 + INST(Vbroadcastf32x4 , VexRm_Lx , E(660F38,1A,_,x,_,0,4,T4 ), 0 , 117, 0 , 3551 , 218, 68 ), // #830 + INST(Vbroadcastf32x8 , VexRm , E(660F38,1B,_,2,_,0,5,T8 ), 0 , 118, 0 , 3567 , 219, 66 ), // #831 + INST(Vbroadcastf64x2 , VexRm_Lx , E(660F38,1A,_,x,_,1,4,T2 ), 0 , 119, 0 , 3583 , 218, 133), // #832 + INST(Vbroadcastf64x4 , VexRm , E(660F38,1B,_,2,_,1,5,T4 ), 0 , 120, 0 , 3599 , 219, 68 ), // #833 + INST(Vbroadcasti128 , VexRm , V(660F38,5A,_,1,0,_,_,_ ), 0 , 115, 0 , 3615 , 216, 134), // #834 + INST(Vbroadcasti32x2 , VexRm_Lx , E(660F38,59,_,x,_,0,3,T2 ), 0 , 116, 0 , 3630 , 220, 133), // #835 + INST(Vbroadcasti32x4 , VexRm_Lx , E(660F38,5A,_,x,_,0,4,T4 ), 0 , 117, 0 , 3646 , 218, 131), // #836 + INST(Vbroadcasti32x8 , VexRm , E(660F38,5B,_,2,_,0,5,T8 ), 0 , 118, 0 , 3662 , 219, 66 ), // #837 + INST(Vbroadcasti64x2 , VexRm_Lx , E(660F38,5A,_,x,_,1,4,T2 ), 0 , 119, 0 , 3678 , 218, 133), // #838 + INST(Vbroadcasti64x4 , VexRm , E(660F38,5B,_,2,_,1,5,T4 ), 0 , 120, 0 , 3694 , 219, 68 ), // #839 + INST(Vbroadcastsd , VexRm_Lx , V(660F38,19,_,x,0,1,3,T1S), 0 , 121, 0 , 3710 , 221, 135), // #840 + INST(Vbroadcastss , VexRm_Lx , V(660F38,18,_,x,0,0,2,T1S), 0 , 122, 0 , 3723 , 222, 135), // #841 + INST(Vcmppd , VexRvmi_Lx_KEvex , V(660F00,C2,_,x,I,1,4,FV ), 0 , 103, 0 , 3736 , 223, 124), // #842 + INST(Vcmpph , VexRvmi_Lx_KEvex , E(000F3A,C2,_,_,_,0,4,FV ), 0 , 123, 0 , 3743 , 224, 125), // #843 + INST(Vcmpps , VexRvmi_Lx_KEvex , V(000F00,C2,_,x,I,0,4,FV ), 0 , 105, 0 , 3750 , 225, 124), // #844 + INST(Vcmpsd , VexRvmi_KEvex , V(F20F00,C2,_,I,I,1,3,T1S), 0 , 106, 0 , 3757 , 226, 126), // #845 + INST(Vcmpsh , VexRvmi_KEvex , E(F30F3A,C2,_,_,_,0,1,T1S), 0 , 124, 0 , 3764 , 227, 127), // #846 + INST(Vcmpss , VexRvmi_KEvex , V(F30F00,C2,_,I,I,0,2,T1S), 0 , 108, 0 , 3771 , 228, 126), // #847 + INST(Vcomisd , VexRm , V(660F00,2F,_,I,I,1,3,T1S), 0 , 125, 0 , 3778 , 229, 136), // #848 + INST(Vcomish , VexRm , E(00MAP5,2F,_,_,_,0,1,T1S), 0 , 126, 0 , 3786 , 230, 127), // #849 + INST(Vcomiss , VexRm , V(000F00,2F,_,I,I,0,2,T1S), 0 , 127, 0 , 3794 , 231, 136), // #850 + INST(Vcompresspd , VexMr_Lx , E(660F38,8A,_,x,_,1,3,T1S), 0 , 128, 0 , 3802 , 232, 131), // #851 + INST(Vcompressps , VexMr_Lx , E(660F38,8A,_,x,_,0,2,T1S), 0 , 129, 0 , 3814 , 232, 131), // #852 + INST(Vcvtdq2pd , VexRm_Lx , V(F30F00,E6,_,x,I,0,3,HV ), 0 , 130, 0 , 3826 , 233, 124), // #853 + INST(Vcvtdq2ph , VexRm_Lx , E(00MAP5,5B,_,_,_,0,4,FV ), 0 , 104, 0 , 3836 , 234, 125), // #854 + INST(Vcvtdq2ps , VexRm_Lx , V(000F00,5B,_,x,I,0,4,FV ), 0 , 105, 0 , 3846 , 235, 124), // #855 + INST(Vcvtne2ps2bf16 , VexRvm_Lx , E(F20F38,72,_,_,_,0,4,FV ), 0 , 131, 0 , 3856 , 213, 137), // #856 + INST(Vcvtneps2bf16 , VexRm_Lx_Narrow , E(F30F38,72,_,_,_,0,4,FV ), 0 , 132, 0 , 3871 , 236, 137), // #857 + INST(Vcvtpd2dq , VexRm_Lx_Narrow , V(F20F00,E6,_,x,I,1,4,FV ), 0 , 133, 0 , 3885 , 237, 124), // #858 + INST(Vcvtpd2ph , VexRm_Lx , E(66MAP5,5A,_,_,_,1,4,FV ), 0 , 134, 0 , 3895 , 238, 125), // #859 + INST(Vcvtpd2ps , VexRm_Lx_Narrow , V(660F00,5A,_,x,I,1,4,FV ), 0 , 103, 0 , 3905 , 237, 124), // #860 + INST(Vcvtpd2qq , VexRm_Lx , E(660F00,7B,_,x,_,1,4,FV ), 0 , 135, 0 , 3915 , 239, 133), // #861 + INST(Vcvtpd2udq , VexRm_Lx_Narrow , E(000F00,79,_,x,_,1,4,FV ), 0 , 136, 0 , 3925 , 240, 131), // #862 + INST(Vcvtpd2uqq , VexRm_Lx , E(660F00,79,_,x,_,1,4,FV ), 0 , 135, 0 , 3936 , 239, 133), // #863 + INST(Vcvtph2dq , VexRm_Lx , E(66MAP5,5B,_,_,_,0,3,HV ), 0 , 137, 0 , 3947 , 241, 125), // #864 + INST(Vcvtph2pd , VexRm_Lx , E(00MAP5,5A,_,_,_,0,2,QV ), 0 , 138, 0 , 3957 , 242, 125), // #865 + INST(Vcvtph2ps , VexRm_Lx , V(660F38,13,_,x,0,0,3,HVM), 0 , 139, 0 , 3967 , 243, 138), // #866 + INST(Vcvtph2psx , VexRm_Lx , E(66MAP6,13,_,_,_,0,3,HV ), 0 , 140, 0 , 3977 , 244, 125), // #867 + INST(Vcvtph2qq , VexRm_Lx , E(66MAP5,7B,_,_,_,0,2,QV ), 0 , 141, 0 , 3988 , 245, 125), // #868 + INST(Vcvtph2udq , VexRm_Lx , E(00MAP5,79,_,_,_,0,3,HV ), 0 , 142, 0 , 3998 , 241, 125), // #869 + INST(Vcvtph2uqq , VexRm_Lx , E(66MAP5,79,_,_,_,0,2,QV ), 0 , 141, 0 , 4009 , 245, 125), // #870 + INST(Vcvtph2uw , VexRm_Lx , E(00MAP5,7D,_,_,_,0,4,FV ), 0 , 104, 0 , 4020 , 246, 125), // #871 + INST(Vcvtph2w , VexRm_Lx , E(66MAP5,7D,_,_,_,0,4,FV ), 0 , 143, 0 , 4030 , 246, 125), // #872 + INST(Vcvtps2dq , VexRm_Lx , V(660F00,5B,_,x,I,0,4,FV ), 0 , 144, 0 , 4039 , 235, 124), // #873 + INST(Vcvtps2pd , VexRm_Lx , V(000F00,5A,_,x,I,0,3,HV ), 0 , 145, 0 , 4049 , 247, 124), // #874 + INST(Vcvtps2ph , VexMri_Lx , V(660F3A,1D,_,x,0,0,3,HVM), 0 , 146, 0 , 4059 , 248, 138), // #875 + INST(Vcvtps2phx , VexRm_Lx , E(66MAP5,1D,_,_,_,0,4,FV ), 0 , 143, 0 , 4069 , 234, 125), // #876 + INST(Vcvtps2qq , VexRm_Lx , E(660F00,7B,_,x,_,0,3,HV ), 0 , 147, 0 , 4080 , 249, 133), // #877 + INST(Vcvtps2udq , VexRm_Lx , E(000F00,79,_,x,_,0,4,FV ), 0 , 148, 0 , 4090 , 250, 131), // #878 + INST(Vcvtps2uqq , VexRm_Lx , E(660F00,79,_,x,_,0,3,HV ), 0 , 147, 0 , 4101 , 249, 133), // #879 + INST(Vcvtqq2pd , VexRm_Lx , E(F30F00,E6,_,x,_,1,4,FV ), 0 , 149, 0 , 4112 , 239, 133), // #880 + INST(Vcvtqq2ph , VexRm_Lx , E(00MAP5,5B,_,_,_,1,4,FV ), 0 , 150, 0 , 4122 , 238, 125), // #881 + INST(Vcvtqq2ps , VexRm_Lx_Narrow , E(000F00,5B,_,x,_,1,4,FV ), 0 , 136, 0 , 4132 , 240, 133), // #882 + INST(Vcvtsd2sh , VexRvm , E(F2MAP5,5A,_,_,_,1,3,T1S), 0 , 151, 0 , 4142 , 251, 127), // #883 + INST(Vcvtsd2si , VexRm_Wx , V(F20F00,2D,_,I,x,x,3,T1F), 0 , 152, 0 , 4152 , 252, 126), // #884 + INST(Vcvtsd2ss , VexRvm , V(F20F00,5A,_,I,I,1,3,T1S), 0 , 106, 0 , 4162 , 199, 126), // #885 + INST(Vcvtsd2usi , VexRm_Wx , E(F20F00,79,_,I,_,x,3,T1F), 0 , 153, 0 , 4172 , 253, 68 ), // #886 + INST(Vcvtsh2sd , VexRvm , E(F3MAP5,5A,_,_,_,0,1,T1S), 0 , 107, 0 , 4183 , 254, 127), // #887 + INST(Vcvtsh2si , VexRm_Wx , E(F3MAP5,2D,_,_,_,x,1,T1S), 0 , 107, 0 , 4193 , 255, 127), // #888 + INST(Vcvtsh2ss , VexRvm , E(00MAP6,13,_,_,_,0,1,T1S), 0 , 154, 0 , 4203 , 254, 127), // #889 + INST(Vcvtsh2usi , VexRm_Wx , E(F3MAP5,79,_,_,_,x,1,T1S), 0 , 107, 0 , 4213 , 255, 127), // #890 + INST(Vcvtsi2sd , VexRvm_Wx , V(F20F00,2A,_,I,x,x,2,T1W), 0 , 155, 0 , 4224 , 256, 126), // #891 + INST(Vcvtsi2sh , VexRvm_Wx , E(F3MAP5,2A,_,_,_,x,2,T1W), 0 , 156, 0 , 4234 , 257, 127), // #892 + INST(Vcvtsi2ss , VexRvm_Wx , V(F30F00,2A,_,I,x,x,2,T1W), 0 , 157, 0 , 4244 , 256, 126), // #893 + INST(Vcvtss2sd , VexRvm , V(F30F00,5A,_,I,I,0,2,T1S), 0 , 108, 0 , 4254 , 258, 126), // #894 + INST(Vcvtss2sh , VexRvm , E(00MAP5,1D,_,_,_,0,2,T1S), 0 , 158, 0 , 4264 , 259, 127), // #895 + INST(Vcvtss2si , VexRm_Wx , V(F30F00,2D,_,I,x,x,2,T1F), 0 , 108, 0 , 4274 , 260, 126), // #896 + INST(Vcvtss2usi , VexRm_Wx , E(F30F00,79,_,I,_,x,2,T1F), 0 , 159, 0 , 4284 , 261, 68 ), // #897 + INST(Vcvttpd2dq , VexRm_Lx_Narrow , V(660F00,E6,_,x,I,1,4,FV ), 0 , 103, 0 , 4295 , 262, 124), // #898 + INST(Vcvttpd2qq , VexRm_Lx , E(660F00,7A,_,x,_,1,4,FV ), 0 , 135, 0 , 4306 , 263, 131), // #899 + INST(Vcvttpd2udq , VexRm_Lx_Narrow , E(000F00,78,_,x,_,1,4,FV ), 0 , 136, 0 , 4317 , 264, 131), // #900 + INST(Vcvttpd2uqq , VexRm_Lx , E(660F00,78,_,x,_,1,4,FV ), 0 , 135, 0 , 4329 , 263, 133), // #901 + INST(Vcvttph2dq , VexRm_Lx , E(F3MAP5,5B,_,_,_,0,3,HV ), 0 , 160, 0 , 4341 , 244, 125), // #902 + INST(Vcvttph2qq , VexRm_Lx , E(66MAP5,7A,_,_,_,0,2,QV ), 0 , 141, 0 , 4352 , 242, 125), // #903 + INST(Vcvttph2udq , VexRm_Lx , E(00MAP5,78,_,_,_,0,3,HV ), 0 , 142, 0 , 4363 , 244, 125), // #904 + INST(Vcvttph2uqq , VexRm_Lx , E(66MAP5,78,_,_,_,0,2,QV ), 0 , 141, 0 , 4375 , 242, 125), // #905 + INST(Vcvttph2uw , VexRm_Lx , E(00MAP5,7C,_,_,_,0,4,FV ), 0 , 104, 0 , 4387 , 265, 125), // #906 + INST(Vcvttph2w , VexRm_Lx , E(66MAP5,7C,_,_,_,0,4,FV ), 0 , 143, 0 , 4398 , 265, 125), // #907 + INST(Vcvttps2dq , VexRm_Lx , V(F30F00,5B,_,x,I,0,4,FV ), 0 , 161, 0 , 4408 , 266, 124), // #908 + INST(Vcvttps2qq , VexRm_Lx , E(660F00,7A,_,x,_,0,3,HV ), 0 , 147, 0 , 4419 , 267, 133), // #909 + INST(Vcvttps2udq , VexRm_Lx , E(000F00,78,_,x,_,0,4,FV ), 0 , 148, 0 , 4430 , 268, 131), // #910 + INST(Vcvttps2uqq , VexRm_Lx , E(660F00,78,_,x,_,0,3,HV ), 0 , 147, 0 , 4442 , 267, 133), // #911 + INST(Vcvttsd2si , VexRm_Wx , V(F20F00,2C,_,I,x,x,3,T1F), 0 , 152, 0 , 4454 , 269, 126), // #912 + INST(Vcvttsd2usi , VexRm_Wx , E(F20F00,78,_,I,_,x,3,T1F), 0 , 153, 0 , 4465 , 270, 68 ), // #913 + INST(Vcvttsh2si , VexRm_Wx , E(F3MAP5,2C,_,_,_,x,1,T1S), 0 , 107, 0 , 4477 , 271, 127), // #914 + INST(Vcvttsh2usi , VexRm_Wx , E(F3MAP5,78,_,_,_,x,1,T1S), 0 , 107, 0 , 4488 , 271, 127), // #915 + INST(Vcvttss2si , VexRm_Wx , V(F30F00,2C,_,I,x,x,2,T1F), 0 , 108, 0 , 4500 , 272, 126), // #916 + INST(Vcvttss2usi , VexRm_Wx , E(F30F00,78,_,I,_,x,2,T1F), 0 , 159, 0 , 4511 , 273, 68 ), // #917 + INST(Vcvtudq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,0,3,HV ), 0 , 162, 0 , 4523 , 274, 131), // #918 + INST(Vcvtudq2ph , VexRm_Lx , E(F2MAP5,7A,_,_,_,0,4,FV ), 0 , 163, 0 , 4534 , 234, 125), // #919 + INST(Vcvtudq2ps , VexRm_Lx , E(F20F00,7A,_,x,_,0,4,FV ), 0 , 164, 0 , 4545 , 250, 131), // #920 + INST(Vcvtuqq2pd , VexRm_Lx , E(F30F00,7A,_,x,_,1,4,FV ), 0 , 149, 0 , 4556 , 239, 133), // #921 + INST(Vcvtuqq2ph , VexRm_Lx , E(F2MAP5,7A,_,_,_,1,4,FV ), 0 , 165, 0 , 4567 , 238, 125), // #922 + INST(Vcvtuqq2ps , VexRm_Lx_Narrow , E(F20F00,7A,_,x,_,1,4,FV ), 0 , 166, 0 , 4578 , 240, 133), // #923 + INST(Vcvtusi2sd , VexRvm_Wx , E(F20F00,7B,_,I,_,x,2,T1W), 0 , 167, 0 , 4589 , 257, 68 ), // #924 + INST(Vcvtusi2sh , VexRvm_Wx , E(F3MAP5,7B,_,_,_,x,2,T1W), 0 , 156, 0 , 4600 , 257, 127), // #925 + INST(Vcvtusi2ss , VexRvm_Wx , E(F30F00,7B,_,I,_,x,2,T1W), 0 , 168, 0 , 4611 , 257, 68 ), // #926 + INST(Vcvtuw2ph , VexRm_Lx , E(F2MAP5,7D,_,_,_,0,4,FV ), 0 , 163, 0 , 4622 , 246, 125), // #927 + INST(Vcvtw2ph , VexRm_Lx , E(F3MAP5,7D,_,_,_,0,4,FV ), 0 , 169, 0 , 4632 , 246, 125), // #928 + INST(Vdbpsadbw , VexRvmi_Lx , E(660F3A,42,_,x,_,0,4,FVM), 0 , 111, 0 , 4641 , 275, 139), // #929 + INST(Vdivpd , VexRvm_Lx , V(660F00,5E,_,x,I,1,4,FV ), 0 , 103, 0 , 4651 , 196, 124), // #930 + INST(Vdivph , VexRvm_Lx , E(00MAP5,5E,_,_,_,0,4,FV ), 0 , 104, 0 , 4658 , 197, 125), // #931 + INST(Vdivps , VexRvm_Lx , V(000F00,5E,_,x,I,0,4,FV ), 0 , 105, 0 , 4665 , 198, 124), // #932 + INST(Vdivsd , VexRvm , V(F20F00,5E,_,I,I,1,3,T1S), 0 , 106, 0 , 4672 , 199, 126), // #933 + INST(Vdivsh , VexRvm , E(F3MAP5,5E,_,_,_,0,1,T1S), 0 , 107, 0 , 4679 , 200, 127), // #934 + INST(Vdivss , VexRvm , V(F30F00,5E,_,I,I,0,2,T1S), 0 , 108, 0 , 4686 , 201, 126), // #935 + INST(Vdpbf16ps , VexRvm_Lx , E(F30F38,52,_,_,_,0,4,FV ), 0 , 132, 0 , 4693 , 213, 137), // #936 + INST(Vdppd , VexRvmi_Lx , V(660F3A,41,_,x,I,_,_,_ ), 0 , 73 , 0 , 4703 , 276, 128), // #937 + INST(Vdpps , VexRvmi_Lx , V(660F3A,40,_,x,I,_,_,_ ), 0 , 73 , 0 , 4709 , 214, 128), // #938 + INST(Verr , X86M_NoSize , O(000F00,00,4,_,_,_,_,_ ), 0 , 97 , 0 , 4715 , 107, 10 ), // #939 + INST(Verw , X86M_NoSize , O(000F00,00,5,_,_,_,_,_ ), 0 , 77 , 0 , 4720 , 107, 10 ), // #940 + INST(Vexp2pd , VexRm , E(660F38,C8,_,2,_,1,4,FV ), 0 , 170, 0 , 4725 , 277, 140), // #941 + INST(Vexp2ps , VexRm , E(660F38,C8,_,2,_,0,4,FV ), 0 , 171, 0 , 4733 , 278, 140), // #942 + INST(Vexpandpd , VexRm_Lx , E(660F38,88,_,x,_,1,3,T1S), 0 , 128, 0 , 4741 , 279, 131), // #943 + INST(Vexpandps , VexRm_Lx , E(660F38,88,_,x,_,0,2,T1S), 0 , 129, 0 , 4751 , 279, 131), // #944 + INST(Vextractf128 , VexMri , V(660F3A,19,_,1,0,_,_,_ ), 0 , 172, 0 , 4761 , 280, 128), // #945 + INST(Vextractf32x4 , VexMri_Lx , E(660F3A,19,_,x,_,0,4,T4 ), 0 , 173, 0 , 4774 , 281, 131), // #946 + INST(Vextractf32x8 , VexMri , E(660F3A,1B,_,2,_,0,5,T8 ), 0 , 174, 0 , 4788 , 282, 66 ), // #947 + INST(Vextractf64x2 , VexMri_Lx , E(660F3A,19,_,x,_,1,4,T2 ), 0 , 175, 0 , 4802 , 281, 133), // #948 + INST(Vextractf64x4 , VexMri , E(660F3A,1B,_,2,_,1,5,T4 ), 0 , 176, 0 , 4816 , 282, 68 ), // #949 + INST(Vextracti128 , VexMri , V(660F3A,39,_,1,0,_,_,_ ), 0 , 172, 0 , 4830 , 280, 134), // #950 + INST(Vextracti32x4 , VexMri_Lx , E(660F3A,39,_,x,_,0,4,T4 ), 0 , 173, 0 , 4843 , 281, 131), // #951 + INST(Vextracti32x8 , VexMri , E(660F3A,3B,_,2,_,0,5,T8 ), 0 , 174, 0 , 4857 , 282, 66 ), // #952 + INST(Vextracti64x2 , VexMri_Lx , E(660F3A,39,_,x,_,1,4,T2 ), 0 , 175, 0 , 4871 , 281, 133), // #953 + INST(Vextracti64x4 , VexMri , E(660F3A,3B,_,2,_,1,5,T4 ), 0 , 176, 0 , 4885 , 282, 68 ), // #954 + INST(Vextractps , VexMri , V(660F3A,17,_,0,I,I,2,T1S), 0 , 177, 0 , 4899 , 283, 126), // #955 + INST(Vfcmaddcph , VexRvm_Lx , E(F2MAP6,56,_,_,_,0,4,FV ), 0 , 178, 0 , 4910 , 284, 125), // #956 + INST(Vfcmaddcsh , VexRvm , E(F2MAP6,57,_,_,_,0,2,T1S), 0 , 179, 0 , 4921 , 259, 125), // #957 + INST(Vfcmulcph , VexRvm_Lx , E(F2MAP6,D6,_,_,_,0,4,FV ), 0 , 178, 0 , 4932 , 284, 125), // #958 + INST(Vfcmulcsh , VexRvm , E(F2MAP6,D7,_,_,_,0,2,T1S), 0 , 179, 0 , 4942 , 259, 125), // #959 + INST(Vfixupimmpd , VexRvmi_Lx , E(660F3A,54,_,x,_,1,4,FV ), 0 , 112, 0 , 4952 , 285, 131), // #960 + INST(Vfixupimmps , VexRvmi_Lx , E(660F3A,54,_,x,_,0,4,FV ), 0 , 111, 0 , 4964 , 286, 131), // #961 + INST(Vfixupimmsd , VexRvmi , E(660F3A,55,_,I,_,1,3,T1S), 0 , 180, 0 , 4976 , 287, 68 ), // #962 + INST(Vfixupimmss , VexRvmi , E(660F3A,55,_,I,_,0,2,T1S), 0 , 181, 0 , 4988 , 288, 68 ), // #963 + INST(Vfmadd132pd , VexRvm_Lx , V(660F38,98,_,x,1,1,4,FV ), 0 , 182, 0 , 5000 , 196, 141), // #964 + INST(Vfmadd132ph , VexRvm_Lx , E(66MAP6,98,_,_,_,0,4,FV ), 0 , 183, 0 , 5012 , 197, 125), // #965 + INST(Vfmadd132ps , VexRvm_Lx , V(660F38,98,_,x,0,0,4,FV ), 0 , 110, 0 , 5024 , 198, 141), // #966 + INST(Vfmadd132sd , VexRvm , V(660F38,99,_,I,1,1,3,T1S), 0 , 184, 0 , 5036 , 199, 142), // #967 + INST(Vfmadd132sh , VexRvm , E(66MAP6,99,_,_,_,0,1,T1S), 0 , 185, 0 , 5048 , 200, 127), // #968 + INST(Vfmadd132ss , VexRvm , V(660F38,99,_,I,0,0,2,T1S), 0 , 122, 0 , 5060 , 201, 142), // #969 + INST(Vfmadd213pd , VexRvm_Lx , V(660F38,A8,_,x,1,1,4,FV ), 0 , 182, 0 , 5072 , 196, 141), // #970 + INST(Vfmadd213ph , VexRvm_Lx , E(66MAP6,A8,_,_,_,0,4,FV ), 0 , 183, 0 , 5084 , 197, 125), // #971 + INST(Vfmadd213ps , VexRvm_Lx , V(660F38,A8,_,x,0,0,4,FV ), 0 , 110, 0 , 5096 , 198, 141), // #972 + INST(Vfmadd213sd , VexRvm , V(660F38,A9,_,I,1,1,3,T1S), 0 , 184, 0 , 5108 , 199, 142), // #973 + INST(Vfmadd213sh , VexRvm , E(66MAP6,A9,_,_,_,0,1,T1S), 0 , 185, 0 , 5120 , 200, 127), // #974 + INST(Vfmadd213ss , VexRvm , V(660F38,A9,_,I,0,0,2,T1S), 0 , 122, 0 , 5132 , 201, 142), // #975 + INST(Vfmadd231pd , VexRvm_Lx , V(660F38,B8,_,x,1,1,4,FV ), 0 , 182, 0 , 5144 , 196, 141), // #976 + INST(Vfmadd231ph , VexRvm_Lx , E(66MAP6,B8,_,_,_,0,4,FV ), 0 , 183, 0 , 5156 , 197, 125), // #977 + INST(Vfmadd231ps , VexRvm_Lx , V(660F38,B8,_,x,0,0,4,FV ), 0 , 110, 0 , 5168 , 198, 141), // #978 + INST(Vfmadd231sd , VexRvm , V(660F38,B9,_,I,1,1,3,T1S), 0 , 184, 0 , 5180 , 199, 142), // #979 + INST(Vfmadd231sh , VexRvm , E(66MAP6,B9,_,_,_,0,1,T1S), 0 , 185, 0 , 5192 , 200, 127), // #980 + INST(Vfmadd231ss , VexRvm , V(660F38,B9,_,I,0,0,2,T1S), 0 , 122, 0 , 5204 , 201, 142), // #981 + INST(Vfmaddcph , VexRvm_Lx , E(F3MAP6,56,_,_,_,0,4,FV ), 0 , 186, 0 , 5216 , 284, 125), // #982 + INST(Vfmaddcsh , VexRvm , E(F3MAP6,57,_,_,_,0,2,T1S), 0 , 187, 0 , 5226 , 259, 125), // #983 + INST(Vfmaddpd , Fma4_Lx , V(660F3A,69,_,x,x,_,_,_ ), 0 , 73 , 0 , 5236 , 289, 143), // #984 + INST(Vfmaddps , Fma4_Lx , V(660F3A,68,_,x,x,_,_,_ ), 0 , 73 , 0 , 5245 , 289, 143), // #985 + INST(Vfmaddsd , Fma4 , V(660F3A,6B,_,0,x,_,_,_ ), 0 , 73 , 0 , 5254 , 290, 143), // #986 + INST(Vfmaddss , Fma4 , V(660F3A,6A,_,0,x,_,_,_ ), 0 , 73 , 0 , 5263 , 291, 143), // #987 + INST(Vfmaddsub132pd , VexRvm_Lx , V(660F38,96,_,x,1,1,4,FV ), 0 , 182, 0 , 5272 , 196, 141), // #988 + INST(Vfmaddsub132ph , VexRvm_Lx , E(66MAP6,96,_,_,_,0,4,FV ), 0 , 183, 0 , 5287 , 197, 125), // #989 + INST(Vfmaddsub132ps , VexRvm_Lx , V(660F38,96,_,x,0,0,4,FV ), 0 , 110, 0 , 5302 , 198, 141), // #990 + INST(Vfmaddsub213pd , VexRvm_Lx , V(660F38,A6,_,x,1,1,4,FV ), 0 , 182, 0 , 5317 , 196, 141), // #991 + INST(Vfmaddsub213ph , VexRvm_Lx , E(66MAP6,A6,_,_,_,0,4,FV ), 0 , 183, 0 , 5332 , 197, 125), // #992 + INST(Vfmaddsub213ps , VexRvm_Lx , V(660F38,A6,_,x,0,0,4,FV ), 0 , 110, 0 , 5347 , 198, 141), // #993 + INST(Vfmaddsub231pd , VexRvm_Lx , V(660F38,B6,_,x,1,1,4,FV ), 0 , 182, 0 , 5362 , 196, 141), // #994 + INST(Vfmaddsub231ph , VexRvm_Lx , E(66MAP6,B6,_,_,_,0,4,FV ), 0 , 183, 0 , 5377 , 197, 125), // #995 + INST(Vfmaddsub231ps , VexRvm_Lx , V(660F38,B6,_,x,0,0,4,FV ), 0 , 110, 0 , 5392 , 198, 141), // #996 + INST(Vfmaddsubpd , Fma4_Lx , V(660F3A,5D,_,x,x,_,_,_ ), 0 , 73 , 0 , 5407 , 289, 143), // #997 + INST(Vfmaddsubps , Fma4_Lx , V(660F3A,5C,_,x,x,_,_,_ ), 0 , 73 , 0 , 5419 , 289, 143), // #998 + INST(Vfmsub132pd , VexRvm_Lx , V(660F38,9A,_,x,1,1,4,FV ), 0 , 182, 0 , 5431 , 196, 141), // #999 + INST(Vfmsub132ph , VexRvm_Lx , E(66MAP6,9A,_,_,_,0,4,FV ), 0 , 183, 0 , 5443 , 197, 125), // #1000 + INST(Vfmsub132ps , VexRvm_Lx , V(660F38,9A,_,x,0,0,4,FV ), 0 , 110, 0 , 5455 , 198, 141), // #1001 + INST(Vfmsub132sd , VexRvm , V(660F38,9B,_,I,1,1,3,T1S), 0 , 184, 0 , 5467 , 199, 142), // #1002 + INST(Vfmsub132sh , VexRvm , E(66MAP6,9B,_,_,_,0,1,T1S), 0 , 185, 0 , 5479 , 200, 127), // #1003 + INST(Vfmsub132ss , VexRvm , V(660F38,9B,_,I,0,0,2,T1S), 0 , 122, 0 , 5491 , 201, 142), // #1004 + INST(Vfmsub213pd , VexRvm_Lx , V(660F38,AA,_,x,1,1,4,FV ), 0 , 182, 0 , 5503 , 196, 141), // #1005 + INST(Vfmsub213ph , VexRvm_Lx , E(66MAP6,AA,_,_,_,0,4,FV ), 0 , 183, 0 , 5515 , 197, 125), // #1006 + INST(Vfmsub213ps , VexRvm_Lx , V(660F38,AA,_,x,0,0,4,FV ), 0 , 110, 0 , 5527 , 198, 141), // #1007 + INST(Vfmsub213sd , VexRvm , V(660F38,AB,_,I,1,1,3,T1S), 0 , 184, 0 , 5539 , 199, 142), // #1008 + INST(Vfmsub213sh , VexRvm , E(66MAP6,AB,_,_,_,0,1,T1S), 0 , 185, 0 , 5551 , 200, 127), // #1009 + INST(Vfmsub213ss , VexRvm , V(660F38,AB,_,I,0,0,2,T1S), 0 , 122, 0 , 5563 , 201, 142), // #1010 + INST(Vfmsub231pd , VexRvm_Lx , V(660F38,BA,_,x,1,1,4,FV ), 0 , 182, 0 , 5575 , 196, 141), // #1011 + INST(Vfmsub231ph , VexRvm_Lx , E(66MAP6,BA,_,_,_,0,4,FV ), 0 , 183, 0 , 5587 , 197, 125), // #1012 + INST(Vfmsub231ps , VexRvm_Lx , V(660F38,BA,_,x,0,0,4,FV ), 0 , 110, 0 , 5599 , 198, 141), // #1013 + INST(Vfmsub231sd , VexRvm , V(660F38,BB,_,I,1,1,3,T1S), 0 , 184, 0 , 5611 , 199, 142), // #1014 + INST(Vfmsub231sh , VexRvm , E(66MAP6,BB,_,_,_,0,1,T1S), 0 , 185, 0 , 5623 , 200, 127), // #1015 + INST(Vfmsub231ss , VexRvm , V(660F38,BB,_,I,0,0,2,T1S), 0 , 122, 0 , 5635 , 201, 142), // #1016 + INST(Vfmsubadd132pd , VexRvm_Lx , V(660F38,97,_,x,1,1,4,FV ), 0 , 182, 0 , 5647 , 196, 141), // #1017 + INST(Vfmsubadd132ph , VexRvm_Lx , E(66MAP6,97,_,_,_,0,4,FV ), 0 , 183, 0 , 5662 , 197, 125), // #1018 + INST(Vfmsubadd132ps , VexRvm_Lx , V(660F38,97,_,x,0,0,4,FV ), 0 , 110, 0 , 5677 , 198, 141), // #1019 + INST(Vfmsubadd213pd , VexRvm_Lx , V(660F38,A7,_,x,1,1,4,FV ), 0 , 182, 0 , 5692 , 196, 141), // #1020 + INST(Vfmsubadd213ph , VexRvm_Lx , E(66MAP6,A7,_,_,_,0,4,FV ), 0 , 183, 0 , 5707 , 197, 125), // #1021 + INST(Vfmsubadd213ps , VexRvm_Lx , V(660F38,A7,_,x,0,0,4,FV ), 0 , 110, 0 , 5722 , 198, 141), // #1022 + INST(Vfmsubadd231pd , VexRvm_Lx , V(660F38,B7,_,x,1,1,4,FV ), 0 , 182, 0 , 5737 , 196, 141), // #1023 + INST(Vfmsubadd231ph , VexRvm_Lx , E(66MAP6,B7,_,_,_,0,4,FV ), 0 , 183, 0 , 5752 , 197, 125), // #1024 + INST(Vfmsubadd231ps , VexRvm_Lx , V(660F38,B7,_,x,0,0,4,FV ), 0 , 110, 0 , 5767 , 198, 141), // #1025 + INST(Vfmsubaddpd , Fma4_Lx , V(660F3A,5F,_,x,x,_,_,_ ), 0 , 73 , 0 , 5782 , 289, 143), // #1026 + INST(Vfmsubaddps , Fma4_Lx , V(660F3A,5E,_,x,x,_,_,_ ), 0 , 73 , 0 , 5794 , 289, 143), // #1027 + INST(Vfmsubpd , Fma4_Lx , V(660F3A,6D,_,x,x,_,_,_ ), 0 , 73 , 0 , 5806 , 289, 143), // #1028 + INST(Vfmsubps , Fma4_Lx , V(660F3A,6C,_,x,x,_,_,_ ), 0 , 73 , 0 , 5815 , 289, 143), // #1029 + INST(Vfmsubsd , Fma4 , V(660F3A,6F,_,0,x,_,_,_ ), 0 , 73 , 0 , 5824 , 290, 143), // #1030 + INST(Vfmsubss , Fma4 , V(660F3A,6E,_,0,x,_,_,_ ), 0 , 73 , 0 , 5833 , 291, 143), // #1031 + INST(Vfmulcph , VexRvm_Lx , E(F3MAP6,D6,_,_,_,0,4,FV ), 0 , 186, 0 , 5842 , 284, 125), // #1032 + INST(Vfmulcsh , VexRvm , E(F3MAP6,D7,_,_,_,0,2,T1S), 0 , 187, 0 , 5851 , 259, 125), // #1033 + INST(Vfnmadd132pd , VexRvm_Lx , V(660F38,9C,_,x,1,1,4,FV ), 0 , 182, 0 , 5860 , 196, 141), // #1034 + INST(Vfnmadd132ph , VexRvm_Lx , E(66MAP6,9C,_,_,_,0,4,FV ), 0 , 183, 0 , 5873 , 197, 125), // #1035 + INST(Vfnmadd132ps , VexRvm_Lx , V(660F38,9C,_,x,0,0,4,FV ), 0 , 110, 0 , 5886 , 198, 141), // #1036 + INST(Vfnmadd132sd , VexRvm , V(660F38,9D,_,I,1,1,3,T1S), 0 , 184, 0 , 5899 , 199, 142), // #1037 + INST(Vfnmadd132sh , VexRvm , E(66MAP6,9D,_,_,_,0,1,T1S), 0 , 185, 0 , 5912 , 200, 127), // #1038 + INST(Vfnmadd132ss , VexRvm , V(660F38,9D,_,I,0,0,2,T1S), 0 , 122, 0 , 5925 , 201, 142), // #1039 + INST(Vfnmadd213pd , VexRvm_Lx , V(660F38,AC,_,x,1,1,4,FV ), 0 , 182, 0 , 5938 , 196, 141), // #1040 + INST(Vfnmadd213ph , VexRvm_Lx , E(66MAP6,AC,_,_,_,0,4,FV ), 0 , 183, 0 , 5951 , 197, 125), // #1041 + INST(Vfnmadd213ps , VexRvm_Lx , V(660F38,AC,_,x,0,0,4,FV ), 0 , 110, 0 , 5964 , 198, 141), // #1042 + INST(Vfnmadd213sd , VexRvm , V(660F38,AD,_,I,1,1,3,T1S), 0 , 184, 0 , 5977 , 199, 142), // #1043 + INST(Vfnmadd213sh , VexRvm , E(66MAP6,AD,_,_,_,0,1,T1S), 0 , 185, 0 , 5990 , 200, 127), // #1044 + INST(Vfnmadd213ss , VexRvm , V(660F38,AD,_,I,0,0,2,T1S), 0 , 122, 0 , 6003 , 201, 142), // #1045 + INST(Vfnmadd231pd , VexRvm_Lx , V(660F38,BC,_,x,1,1,4,FV ), 0 , 182, 0 , 6016 , 196, 141), // #1046 + INST(Vfnmadd231ph , VexRvm_Lx , E(66MAP6,BC,_,_,_,0,4,FV ), 0 , 183, 0 , 6029 , 197, 125), // #1047 + INST(Vfnmadd231ps , VexRvm_Lx , V(660F38,BC,_,x,0,0,4,FV ), 0 , 110, 0 , 6042 , 198, 141), // #1048 + INST(Vfnmadd231sd , VexRvm , V(660F38,BD,_,I,1,1,3,T1S), 0 , 184, 0 , 6055 , 199, 142), // #1049 + INST(Vfnmadd231sh , VexRvm , E(66MAP6,BD,_,_,_,0,1,T1S), 0 , 185, 0 , 6068 , 200, 127), // #1050 + INST(Vfnmadd231ss , VexRvm , V(660F38,BD,_,I,0,0,2,T1S), 0 , 122, 0 , 6081 , 201, 142), // #1051 + INST(Vfnmaddpd , Fma4_Lx , V(660F3A,79,_,x,x,_,_,_ ), 0 , 73 , 0 , 6094 , 289, 143), // #1052 + INST(Vfnmaddps , Fma4_Lx , V(660F3A,78,_,x,x,_,_,_ ), 0 , 73 , 0 , 6104 , 289, 143), // #1053 + INST(Vfnmaddsd , Fma4 , V(660F3A,7B,_,0,x,_,_,_ ), 0 , 73 , 0 , 6114 , 290, 143), // #1054 + INST(Vfnmaddss , Fma4 , V(660F3A,7A,_,0,x,_,_,_ ), 0 , 73 , 0 , 6124 , 291, 143), // #1055 + INST(Vfnmsub132pd , VexRvm_Lx , V(660F38,9E,_,x,1,1,4,FV ), 0 , 182, 0 , 6134 , 196, 141), // #1056 + INST(Vfnmsub132ph , VexRvm_Lx , E(66MAP6,9E,_,_,_,0,4,FV ), 0 , 183, 0 , 6147 , 197, 125), // #1057 + INST(Vfnmsub132ps , VexRvm_Lx , V(660F38,9E,_,x,0,0,4,FV ), 0 , 110, 0 , 6160 , 198, 141), // #1058 + INST(Vfnmsub132sd , VexRvm , V(660F38,9F,_,I,1,1,3,T1S), 0 , 184, 0 , 6173 , 199, 142), // #1059 + INST(Vfnmsub132sh , VexRvm , E(66MAP6,9F,_,_,_,0,1,T1S), 0 , 185, 0 , 6186 , 200, 127), // #1060 + INST(Vfnmsub132ss , VexRvm , V(660F38,9F,_,I,0,0,2,T1S), 0 , 122, 0 , 6199 , 201, 142), // #1061 + INST(Vfnmsub213pd , VexRvm_Lx , V(660F38,AE,_,x,1,1,4,FV ), 0 , 182, 0 , 6212 , 196, 141), // #1062 + INST(Vfnmsub213ph , VexRvm_Lx , E(66MAP6,AE,_,_,_,0,4,FV ), 0 , 183, 0 , 6225 , 197, 125), // #1063 + INST(Vfnmsub213ps , VexRvm_Lx , V(660F38,AE,_,x,0,0,4,FV ), 0 , 110, 0 , 6238 , 198, 141), // #1064 + INST(Vfnmsub213sd , VexRvm , V(660F38,AF,_,I,1,1,3,T1S), 0 , 184, 0 , 6251 , 199, 142), // #1065 + INST(Vfnmsub213sh , VexRvm , E(66MAP6,AF,_,_,_,0,1,T1S), 0 , 185, 0 , 6264 , 200, 127), // #1066 + INST(Vfnmsub213ss , VexRvm , V(660F38,AF,_,I,0,0,2,T1S), 0 , 122, 0 , 6277 , 201, 142), // #1067 + INST(Vfnmsub231pd , VexRvm_Lx , V(660F38,BE,_,x,1,1,4,FV ), 0 , 182, 0 , 6290 , 196, 141), // #1068 + INST(Vfnmsub231ph , VexRvm_Lx , E(66MAP6,BE,_,_,_,0,4,FV ), 0 , 183, 0 , 6303 , 197, 125), // #1069 + INST(Vfnmsub231ps , VexRvm_Lx , V(660F38,BE,_,x,0,0,4,FV ), 0 , 110, 0 , 6316 , 198, 141), // #1070 + INST(Vfnmsub231sd , VexRvm , V(660F38,BF,_,I,1,1,3,T1S), 0 , 184, 0 , 6329 , 199, 142), // #1071 + INST(Vfnmsub231sh , VexRvm , E(66MAP6,BF,_,_,_,0,1,T1S), 0 , 185, 0 , 6342 , 200, 127), // #1072 + INST(Vfnmsub231ss , VexRvm , V(660F38,BF,_,I,0,0,2,T1S), 0 , 122, 0 , 6355 , 201, 142), // #1073 + INST(Vfnmsubpd , Fma4_Lx , V(660F3A,7D,_,x,x,_,_,_ ), 0 , 73 , 0 , 6368 , 289, 143), // #1074 + INST(Vfnmsubps , Fma4_Lx , V(660F3A,7C,_,x,x,_,_,_ ), 0 , 73 , 0 , 6378 , 289, 143), // #1075 + INST(Vfnmsubsd , Fma4 , V(660F3A,7F,_,0,x,_,_,_ ), 0 , 73 , 0 , 6388 , 290, 143), // #1076 + INST(Vfnmsubss , Fma4 , V(660F3A,7E,_,0,x,_,_,_ ), 0 , 73 , 0 , 6398 , 291, 143), // #1077 + INST(Vfpclasspd , VexRmi_Lx , E(660F3A,66,_,x,_,1,4,FV ), 0 , 112, 0 , 6408 , 292, 133), // #1078 + INST(Vfpclassph , VexRmi_Lx , E(000F3A,66,_,_,_,0,4,FV ), 0 , 123, 0 , 6419 , 293, 125), // #1079 + INST(Vfpclassps , VexRmi_Lx , E(660F3A,66,_,x,_,0,4,FV ), 0 , 111, 0 , 6430 , 294, 133), // #1080 + INST(Vfpclasssd , VexRmi , E(660F3A,67,_,I,_,1,3,T1S), 0 , 180, 0 , 6441 , 295, 66 ), // #1081 + INST(Vfpclasssh , VexRmi , E(000F3A,67,_,_,_,0,1,T1S), 0 , 188, 0 , 6452 , 296, 127), // #1082 + INST(Vfpclassss , VexRmi , E(660F3A,67,_,I,_,0,2,T1S), 0 , 181, 0 , 6463 , 297, 66 ), // #1083 + INST(Vfrczpd , VexRm_Lx , V(XOP_M9,81,_,x,0,_,_,_ ), 0 , 79 , 0 , 6474 , 298, 144), // #1084 + INST(Vfrczps , VexRm_Lx , V(XOP_M9,80,_,x,0,_,_,_ ), 0 , 79 , 0 , 6482 , 298, 144), // #1085 + INST(Vfrczsd , VexRm , V(XOP_M9,83,_,0,0,_,_,_ ), 0 , 79 , 0 , 6490 , 299, 144), // #1086 + INST(Vfrczss , VexRm , V(XOP_M9,82,_,0,0,_,_,_ ), 0 , 79 , 0 , 6498 , 300, 144), // #1087 + INST(Vgatherdpd , VexRmvRm_VM , V(660F38,92,_,x,1,_,_,_ ), E(660F38,92,_,x,_,1,3,T1S), 189, 80 , 6506 , 301, 145), // #1088 + INST(Vgatherdps , VexRmvRm_VM , V(660F38,92,_,x,0,_,_,_ ), E(660F38,92,_,x,_,0,2,T1S), 96 , 81 , 6517 , 302, 145), // #1089 + INST(Vgatherpf0dpd , VexM_VM , E(660F38,C6,1,2,_,1,3,T1S), 0 , 190, 0 , 6528 , 303, 146), // #1090 + INST(Vgatherpf0dps , VexM_VM , E(660F38,C6,1,2,_,0,2,T1S), 0 , 191, 0 , 6542 , 304, 146), // #1091 + INST(Vgatherpf0qpd , VexM_VM , E(660F38,C7,1,2,_,1,3,T1S), 0 , 190, 0 , 6556 , 305, 146), // #1092 + INST(Vgatherpf0qps , VexM_VM , E(660F38,C7,1,2,_,0,2,T1S), 0 , 191, 0 , 6570 , 305, 146), // #1093 + INST(Vgatherpf1dpd , VexM_VM , E(660F38,C6,2,2,_,1,3,T1S), 0 , 192, 0 , 6584 , 303, 146), // #1094 + INST(Vgatherpf1dps , VexM_VM , E(660F38,C6,2,2,_,0,2,T1S), 0 , 193, 0 , 6598 , 304, 146), // #1095 + INST(Vgatherpf1qpd , VexM_VM , E(660F38,C7,2,2,_,1,3,T1S), 0 , 192, 0 , 6612 , 305, 146), // #1096 + INST(Vgatherpf1qps , VexM_VM , E(660F38,C7,2,2,_,0,2,T1S), 0 , 193, 0 , 6626 , 305, 146), // #1097 + INST(Vgatherqpd , VexRmvRm_VM , V(660F38,93,_,x,1,_,_,_ ), E(660F38,93,_,x,_,1,3,T1S), 189, 82 , 6640 , 306, 145), // #1098 + INST(Vgatherqps , VexRmvRm_VM , V(660F38,93,_,x,0,_,_,_ ), E(660F38,93,_,x,_,0,2,T1S), 96 , 83 , 6651 , 307, 145), // #1099 + INST(Vgetexppd , VexRm_Lx , E(660F38,42,_,x,_,1,4,FV ), 0 , 113, 0 , 6662 , 263, 131), // #1100 + INST(Vgetexpph , VexRm_Lx , E(66MAP6,42,_,_,_,0,4,FV ), 0 , 183, 0 , 6672 , 265, 125), // #1101 + INST(Vgetexpps , VexRm_Lx , E(660F38,42,_,x,_,0,4,FV ), 0 , 114, 0 , 6682 , 268, 131), // #1102 + INST(Vgetexpsd , VexRvm , E(660F38,43,_,I,_,1,3,T1S), 0 , 128, 0 , 6692 , 308, 68 ), // #1103 + INST(Vgetexpsh , VexRvm , E(66MAP6,43,_,_,_,0,1,T1S), 0 , 185, 0 , 6702 , 254, 127), // #1104 + INST(Vgetexpss , VexRvm , E(660F38,43,_,I,_,0,2,T1S), 0 , 129, 0 , 6712 , 309, 68 ), // #1105 + INST(Vgetmantpd , VexRmi_Lx , E(660F3A,26,_,x,_,1,4,FV ), 0 , 112, 0 , 6722 , 310, 131), // #1106 + INST(Vgetmantph , VexRmi_Lx , E(000F3A,26,_,_,_,0,4,FV ), 0 , 123, 0 , 6733 , 311, 125), // #1107 + INST(Vgetmantps , VexRmi_Lx , E(660F3A,26,_,x,_,0,4,FV ), 0 , 111, 0 , 6744 , 312, 131), // #1108 + INST(Vgetmantsd , VexRvmi , E(660F3A,27,_,I,_,1,3,T1S), 0 , 180, 0 , 6755 , 287, 68 ), // #1109 + INST(Vgetmantsh , VexRvmi , E(000F3A,27,_,_,_,0,1,T1S), 0 , 188, 0 , 6766 , 313, 127), // #1110 + INST(Vgetmantss , VexRvmi , E(660F3A,27,_,I,_,0,2,T1S), 0 , 181, 0 , 6777 , 288, 68 ), // #1111 + INST(Vgf2p8affineinvqb, VexRvmi_Lx , V(660F3A,CF,_,x,1,1,4,FV ), 0 , 194, 0 , 6788 , 314, 147), // #1112 + INST(Vgf2p8affineqb , VexRvmi_Lx , V(660F3A,CE,_,x,1,1,4,FV ), 0 , 194, 0 , 6806 , 314, 147), // #1113 + INST(Vgf2p8mulb , VexRvm_Lx , V(660F38,CF,_,x,0,0,4,FV ), 0 , 110, 0 , 6821 , 315, 147), // #1114 + INST(Vhaddpd , VexRvm_Lx , V(660F00,7C,_,x,I,_,_,_ ), 0 , 69 , 0 , 6832 , 202, 128), // #1115 + INST(Vhaddps , VexRvm_Lx , V(F20F00,7C,_,x,I,_,_,_ ), 0 , 109, 0 , 6840 , 202, 128), // #1116 + INST(Vhsubpd , VexRvm_Lx , V(660F00,7D,_,x,I,_,_,_ ), 0 , 69 , 0 , 6848 , 202, 128), // #1117 + INST(Vhsubps , VexRvm_Lx , V(F20F00,7D,_,x,I,_,_,_ ), 0 , 109, 0 , 6856 , 202, 128), // #1118 + INST(Vinsertf128 , VexRvmi , V(660F3A,18,_,1,0,_,_,_ ), 0 , 172, 0 , 6864 , 316, 128), // #1119 + INST(Vinsertf32x4 , VexRvmi_Lx , E(660F3A,18,_,x,_,0,4,T4 ), 0 , 173, 0 , 6876 , 317, 131), // #1120 + INST(Vinsertf32x8 , VexRvmi , E(660F3A,1A,_,2,_,0,5,T8 ), 0 , 174, 0 , 6889 , 318, 66 ), // #1121 + INST(Vinsertf64x2 , VexRvmi_Lx , E(660F3A,18,_,x,_,1,4,T2 ), 0 , 175, 0 , 6902 , 317, 133), // #1122 + INST(Vinsertf64x4 , VexRvmi , E(660F3A,1A,_,2,_,1,5,T4 ), 0 , 176, 0 , 6915 , 318, 68 ), // #1123 + INST(Vinserti128 , VexRvmi , V(660F3A,38,_,1,0,_,_,_ ), 0 , 172, 0 , 6928 , 316, 134), // #1124 + INST(Vinserti32x4 , VexRvmi_Lx , E(660F3A,38,_,x,_,0,4,T4 ), 0 , 173, 0 , 6940 , 317, 131), // #1125 + INST(Vinserti32x8 , VexRvmi , E(660F3A,3A,_,2,_,0,5,T8 ), 0 , 174, 0 , 6953 , 318, 66 ), // #1126 + INST(Vinserti64x2 , VexRvmi_Lx , E(660F3A,38,_,x,_,1,4,T2 ), 0 , 175, 0 , 6966 , 317, 133), // #1127 + INST(Vinserti64x4 , VexRvmi , E(660F3A,3A,_,2,_,1,5,T4 ), 0 , 176, 0 , 6979 , 318, 68 ), // #1128 + INST(Vinsertps , VexRvmi , V(660F3A,21,_,0,I,0,2,T1S), 0 , 177, 0 , 6992 , 319, 126), // #1129 + INST(Vlddqu , VexRm_Lx , V(F20F00,F0,_,x,I,_,_,_ ), 0 , 109, 0 , 7002 , 320, 128), // #1130 + INST(Vldmxcsr , VexM , V(000F00,AE,2,0,I,_,_,_ ), 0 , 195, 0 , 7009 , 321, 128), // #1131 + INST(Vmaskmovdqu , VexRm_ZDI , V(660F00,F7,_,0,I,_,_,_ ), 0 , 69 , 0 , 7018 , 322, 128), // #1132 + INST(Vmaskmovpd , VexRvmMvr_Lx , V(660F38,2D,_,x,0,_,_,_ ), V(660F38,2F,_,x,0,_,_,_ ), 96 , 84 , 7030 , 323, 128), // #1133 + INST(Vmaskmovps , VexRvmMvr_Lx , V(660F38,2C,_,x,0,_,_,_ ), V(660F38,2E,_,x,0,_,_,_ ), 96 , 85 , 7041 , 323, 128), // #1134 + INST(Vmaxpd , VexRvm_Lx , V(660F00,5F,_,x,I,1,4,FV ), 0 , 103, 0 , 7052 , 324, 124), // #1135 + INST(Vmaxph , VexRvm_Lx , E(00MAP5,5F,_,_,_,0,4,FV ), 0 , 104, 0 , 7059 , 325, 125), // #1136 + INST(Vmaxps , VexRvm_Lx , V(000F00,5F,_,x,I,0,4,FV ), 0 , 105, 0 , 7066 , 326, 124), // #1137 + INST(Vmaxsd , VexRvm , V(F20F00,5F,_,I,I,1,3,T1S), 0 , 106, 0 , 7073 , 327, 124), // #1138 + INST(Vmaxsh , VexRvm , E(F3MAP5,5F,_,_,_,0,1,T1S), 0 , 107, 0 , 7080 , 254, 127), // #1139 + INST(Vmaxss , VexRvm , V(F30F00,5F,_,I,I,0,2,T1S), 0 , 108, 0 , 7087 , 258, 124), // #1140 + INST(Vmcall , X86Op , O(000F01,C1,_,_,_,_,_,_ ), 0 , 21 , 0 , 7094 , 30 , 58 ), // #1141 + INST(Vmclear , X86M_Only , O(660F00,C7,6,_,_,_,_,_ ), 0 , 26 , 0 , 7101 , 32 , 58 ), // #1142 + INST(Vmfunc , X86Op , O(000F01,D4,_,_,_,_,_,_ ), 0 , 21 , 0 , 7109 , 30 , 58 ), // #1143 + INST(Vminpd , VexRvm_Lx , V(660F00,5D,_,x,I,1,4,FV ), 0 , 103, 0 , 7116 , 324, 124), // #1144 + INST(Vminph , VexRvm_Lx , E(00MAP5,5D,_,_,_,0,4,FV ), 0 , 104, 0 , 7123 , 325, 125), // #1145 + INST(Vminps , VexRvm_Lx , V(000F00,5D,_,x,I,0,4,FV ), 0 , 105, 0 , 7130 , 326, 124), // #1146 + INST(Vminsd , VexRvm , V(F20F00,5D,_,I,I,1,3,T1S), 0 , 106, 0 , 7137 , 327, 124), // #1147 + INST(Vminsh , VexRvm , E(F3MAP5,5D,_,_,_,0,1,T1S), 0 , 107, 0 , 7144 , 254, 127), // #1148 + INST(Vminss , VexRvm , V(F30F00,5D,_,I,I,0,2,T1S), 0 , 108, 0 , 7151 , 258, 124), // #1149 + INST(Vmlaunch , X86Op , O(000F01,C2,_,_,_,_,_,_ ), 0 , 21 , 0 , 7158 , 30 , 58 ), // #1150 + INST(Vmload , X86Op_xAX , O(000F01,DA,_,_,_,_,_,_ ), 0 , 21 , 0 , 7167 , 328, 22 ), // #1151 + INST(Vmmcall , X86Op , O(000F01,D9,_,_,_,_,_,_ ), 0 , 21 , 0 , 7174 , 30 , 22 ), // #1152 + INST(Vmovapd , VexRmMr_Lx , V(660F00,28,_,x,I,1,4,FVM), V(660F00,29,_,x,I,1,4,FVM), 103, 86 , 7182 , 329, 124), // #1153 + INST(Vmovaps , VexRmMr_Lx , V(000F00,28,_,x,I,0,4,FVM), V(000F00,29,_,x,I,0,4,FVM), 105, 87 , 7190 , 329, 124), // #1154 + INST(Vmovd , VexMovdMovq , V(660F00,6E,_,0,0,0,2,T1S), V(660F00,7E,_,0,0,0,2,T1S), 196, 88 , 7198 , 330, 126), // #1155 + INST(Vmovddup , VexRm_Lx , V(F20F00,12,_,x,I,1,3,DUP), 0 , 197, 0 , 7204 , 331, 124), // #1156 + INST(Vmovdqa , VexRmMr_Lx , V(660F00,6F,_,x,I,_,_,_ ), V(660F00,7F,_,x,I,_,_,_ ), 69 , 89 , 7213 , 332, 128), // #1157 + INST(Vmovdqa32 , VexRmMr_Lx , E(660F00,6F,_,x,_,0,4,FVM), E(660F00,7F,_,x,_,0,4,FVM), 198, 90 , 7221 , 333, 131), // #1158 + INST(Vmovdqa64 , VexRmMr_Lx , E(660F00,6F,_,x,_,1,4,FVM), E(660F00,7F,_,x,_,1,4,FVM), 135, 91 , 7231 , 333, 131), // #1159 + INST(Vmovdqu , VexRmMr_Lx , V(F30F00,6F,_,x,I,_,_,_ ), V(F30F00,7F,_,x,I,_,_,_ ), 199, 92 , 7241 , 332, 128), // #1160 + INST(Vmovdqu16 , VexRmMr_Lx , E(F20F00,6F,_,x,_,1,4,FVM), E(F20F00,7F,_,x,_,1,4,FVM), 166, 93 , 7249 , 333, 139), // #1161 + INST(Vmovdqu32 , VexRmMr_Lx , E(F30F00,6F,_,x,_,0,4,FVM), E(F30F00,7F,_,x,_,0,4,FVM), 200, 94 , 7259 , 333, 131), // #1162 + INST(Vmovdqu64 , VexRmMr_Lx , E(F30F00,6F,_,x,_,1,4,FVM), E(F30F00,7F,_,x,_,1,4,FVM), 149, 95 , 7269 , 333, 131), // #1163 + INST(Vmovdqu8 , VexRmMr_Lx , E(F20F00,6F,_,x,_,0,4,FVM), E(F20F00,7F,_,x,_,0,4,FVM), 164, 96 , 7279 , 333, 139), // #1164 + INST(Vmovhlps , VexRvm , V(000F00,12,_,0,I,0,_,_ ), 0 , 72 , 0 , 7288 , 334, 126), // #1165 + INST(Vmovhpd , VexRvmMr , V(660F00,16,_,0,I,1,3,T1S), V(660F00,17,_,0,I,1,3,T1S), 125, 97 , 7297 , 335, 126), // #1166 + INST(Vmovhps , VexRvmMr , V(000F00,16,_,0,I,0,3,T2 ), V(000F00,17,_,0,I,0,3,T2 ), 201, 98 , 7305 , 335, 126), // #1167 + INST(Vmovlhps , VexRvm , V(000F00,16,_,0,I,0,_,_ ), 0 , 72 , 0 , 7313 , 334, 126), // #1168 + INST(Vmovlpd , VexRvmMr , V(660F00,12,_,0,I,1,3,T1S), V(660F00,13,_,0,I,1,3,T1S), 125, 99 , 7322 , 335, 126), // #1169 + INST(Vmovlps , VexRvmMr , V(000F00,12,_,0,I,0,3,T2 ), V(000F00,13,_,0,I,0,3,T2 ), 201, 100, 7330 , 335, 126), // #1170 + INST(Vmovmskpd , VexRm_Lx , V(660F00,50,_,x,I,_,_,_ ), 0 , 69 , 0 , 7338 , 336, 128), // #1171 + INST(Vmovmskps , VexRm_Lx , V(000F00,50,_,x,I,_,_,_ ), 0 , 72 , 0 , 7348 , 336, 128), // #1172 + INST(Vmovntdq , VexMr_Lx , V(660F00,E7,_,x,I,0,4,FVM), 0 , 144, 0 , 7358 , 337, 124), // #1173 + INST(Vmovntdqa , VexRm_Lx , V(660F38,2A,_,x,I,0,4,FVM), 0 , 110, 0 , 7367 , 338, 135), // #1174 + INST(Vmovntpd , VexMr_Lx , V(660F00,2B,_,x,I,1,4,FVM), 0 , 103, 0 , 7377 , 337, 124), // #1175 + INST(Vmovntps , VexMr_Lx , V(000F00,2B,_,x,I,0,4,FVM), 0 , 105, 0 , 7386 , 337, 124), // #1176 + INST(Vmovq , VexMovdMovq , V(660F00,6E,_,0,I,1,3,T1S), V(660F00,7E,_,0,I,1,3,T1S), 125, 101, 7395 , 339, 126), // #1177 + INST(Vmovsd , VexMovssMovsd , V(F20F00,10,_,I,I,1,3,T1S), V(F20F00,11,_,I,I,1,3,T1S), 106, 102, 7401 , 340, 126), // #1178 + INST(Vmovsh , VexMovssMovsd , E(F3MAP5,10,_,I,_,0,1,T1S), E(F3MAP5,11,_,I,_,0,1,T1S), 107, 103, 7408 , 341, 127), // #1179 + INST(Vmovshdup , VexRm_Lx , V(F30F00,16,_,x,I,0,4,FVM), 0 , 161, 0 , 7415 , 342, 124), // #1180 + INST(Vmovsldup , VexRm_Lx , V(F30F00,12,_,x,I,0,4,FVM), 0 , 161, 0 , 7425 , 342, 124), // #1181 + INST(Vmovss , VexMovssMovsd , V(F30F00,10,_,I,I,0,2,T1S), V(F30F00,11,_,I,I,0,2,T1S), 108, 104, 7435 , 343, 126), // #1182 + INST(Vmovupd , VexRmMr_Lx , V(660F00,10,_,x,I,1,4,FVM), V(660F00,11,_,x,I,1,4,FVM), 103, 105, 7442 , 329, 124), // #1183 + INST(Vmovups , VexRmMr_Lx , V(000F00,10,_,x,I,0,4,FVM), V(000F00,11,_,x,I,0,4,FVM), 105, 106, 7450 , 329, 124), // #1184 + INST(Vmovw , VexMovdMovq , E(66MAP5,6E,_,0,_,I,1,T1S), E(66MAP5,7E,_,0,_,I,1,T1S), 202, 107, 7458 , 344, 127), // #1185 + INST(Vmpsadbw , VexRvmi_Lx , V(660F3A,42,_,x,I,_,_,_ ), 0 , 73 , 0 , 7464 , 214, 148), // #1186 + INST(Vmptrld , X86M_Only , O(000F00,C7,6,_,_,_,_,_ ), 0 , 80 , 0 , 7473 , 32 , 58 ), // #1187 + INST(Vmptrst , X86M_Only , O(000F00,C7,7,_,_,_,_,_ ), 0 , 22 , 0 , 7481 , 32 , 58 ), // #1188 + INST(Vmread , X86Mr_NoSize , O(000F00,78,_,_,_,_,_,_ ), 0 , 4 , 0 , 7489 , 345, 58 ), // #1189 + INST(Vmresume , X86Op , O(000F01,C3,_,_,_,_,_,_ ), 0 , 21 , 0 , 7496 , 30 , 58 ), // #1190 + INST(Vmrun , X86Op_xAX , O(000F01,D8,_,_,_,_,_,_ ), 0 , 21 , 0 , 7505 , 328, 22 ), // #1191 + INST(Vmsave , X86Op_xAX , O(000F01,DB,_,_,_,_,_,_ ), 0 , 21 , 0 , 7511 , 328, 22 ), // #1192 + INST(Vmulpd , VexRvm_Lx , V(660F00,59,_,x,I,1,4,FV ), 0 , 103, 0 , 7518 , 196, 124), // #1193 + INST(Vmulph , VexRvm_Lx , E(00MAP5,59,_,_,_,0,4,FV ), 0 , 104, 0 , 7525 , 197, 125), // #1194 + INST(Vmulps , VexRvm_Lx , V(000F00,59,_,x,I,0,4,FV ), 0 , 105, 0 , 7532 , 198, 124), // #1195 + INST(Vmulsd , VexRvm , V(F20F00,59,_,I,I,1,3,T1S), 0 , 106, 0 , 7539 , 199, 126), // #1196 + INST(Vmulsh , VexRvm , E(F3MAP5,59,_,_,_,0,1,T1S), 0 , 107, 0 , 7546 , 200, 127), // #1197 + INST(Vmulss , VexRvm , V(F30F00,59,_,I,I,0,2,T1S), 0 , 108, 0 , 7553 , 201, 126), // #1198 + INST(Vmwrite , X86Rm_NoSize , O(000F00,79,_,_,_,_,_,_ ), 0 , 4 , 0 , 7560 , 346, 58 ), // #1199 + INST(Vmxon , X86M_Only , O(F30F00,C7,6,_,_,_,_,_ ), 0 , 24 , 0 , 7568 , 32 , 58 ), // #1200 + INST(Vorpd , VexRvm_Lx , V(660F00,56,_,x,I,1,4,FV ), 0 , 103, 0 , 7574 , 210, 132), // #1201 + INST(Vorps , VexRvm_Lx , V(000F00,56,_,x,I,0,4,FV ), 0 , 105, 0 , 7580 , 211, 132), // #1202 + INST(Vp2intersectd , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,0,4,FV ), 0 , 131, 0 , 7586 , 347, 149), // #1203 + INST(Vp2intersectq , VexRvm_Lx_2xK , E(F20F38,68,_,_,_,1,4,FV ), 0 , 203, 0 , 7600 , 348, 149), // #1204 + INST(Vp4dpwssd , VexRm_T1_4X , E(F20F38,52,_,2,_,0,4,T4X), 0 , 101, 0 , 7614 , 194, 150), // #1205 + INST(Vp4dpwssds , VexRm_T1_4X , E(F20F38,53,_,2,_,0,4,T4X), 0 , 101, 0 , 7624 , 194, 150), // #1206 + INST(Vpabsb , VexRm_Lx , V(660F38,1C,_,x,I,_,4,FVM), 0 , 110, 0 , 7635 , 342, 151), // #1207 + INST(Vpabsd , VexRm_Lx , V(660F38,1E,_,x,I,0,4,FV ), 0 , 110, 0 , 7642 , 349, 135), // #1208 + INST(Vpabsq , VexRm_Lx , E(660F38,1F,_,x,_,1,4,FV ), 0 , 113, 0 , 7649 , 350, 131), // #1209 + INST(Vpabsw , VexRm_Lx , V(660F38,1D,_,x,I,_,4,FVM), 0 , 110, 0 , 7656 , 342, 151), // #1210 + INST(Vpackssdw , VexRvm_Lx , V(660F00,6B,_,x,I,0,4,FV ), 0 , 144, 0 , 7663 , 209, 151), // #1211 + INST(Vpacksswb , VexRvm_Lx , V(660F00,63,_,x,I,I,4,FVM), 0 , 144, 0 , 7673 , 315, 151), // #1212 + INST(Vpackusdw , VexRvm_Lx , V(660F38,2B,_,x,I,0,4,FV ), 0 , 110, 0 , 7683 , 209, 151), // #1213 + INST(Vpackuswb , VexRvm_Lx , V(660F00,67,_,x,I,I,4,FVM), 0 , 144, 0 , 7693 , 315, 151), // #1214 + INST(Vpaddb , VexRvm_Lx , V(660F00,FC,_,x,I,I,4,FVM), 0 , 144, 0 , 7703 , 315, 151), // #1215 + INST(Vpaddd , VexRvm_Lx , V(660F00,FE,_,x,I,0,4,FV ), 0 , 144, 0 , 7710 , 209, 135), // #1216 + INST(Vpaddq , VexRvm_Lx , V(660F00,D4,_,x,I,1,4,FV ), 0 , 103, 0 , 7717 , 208, 135), // #1217 + INST(Vpaddsb , VexRvm_Lx , V(660F00,EC,_,x,I,I,4,FVM), 0 , 144, 0 , 7724 , 315, 151), // #1218 + INST(Vpaddsw , VexRvm_Lx , V(660F00,ED,_,x,I,I,4,FVM), 0 , 144, 0 , 7732 , 315, 151), // #1219 + INST(Vpaddusb , VexRvm_Lx , V(660F00,DC,_,x,I,I,4,FVM), 0 , 144, 0 , 7740 , 315, 151), // #1220 + INST(Vpaddusw , VexRvm_Lx , V(660F00,DD,_,x,I,I,4,FVM), 0 , 144, 0 , 7749 , 315, 151), // #1221 + INST(Vpaddw , VexRvm_Lx , V(660F00,FD,_,x,I,I,4,FVM), 0 , 144, 0 , 7758 , 315, 151), // #1222 + INST(Vpalignr , VexRvmi_Lx , V(660F3A,0F,_,x,I,I,4,FVM), 0 , 204, 0 , 7765 , 314, 151), // #1223 + INST(Vpand , VexRvm_Lx , V(660F00,DB,_,x,I,_,_,_ ), 0 , 69 , 0 , 7774 , 351, 148), // #1224 + INST(Vpandd , VexRvm_Lx , E(660F00,DB,_,x,_,0,4,FV ), 0 , 198, 0 , 7780 , 352, 131), // #1225 + INST(Vpandn , VexRvm_Lx , V(660F00,DF,_,x,I,_,_,_ ), 0 , 69 , 0 , 7787 , 353, 148), // #1226 + INST(Vpandnd , VexRvm_Lx , E(660F00,DF,_,x,_,0,4,FV ), 0 , 198, 0 , 7794 , 354, 131), // #1227 + INST(Vpandnq , VexRvm_Lx , E(660F00,DF,_,x,_,1,4,FV ), 0 , 135, 0 , 7802 , 355, 131), // #1228 + INST(Vpandq , VexRvm_Lx , E(660F00,DB,_,x,_,1,4,FV ), 0 , 135, 0 , 7810 , 356, 131), // #1229 + INST(Vpavgb , VexRvm_Lx , V(660F00,E0,_,x,I,I,4,FVM), 0 , 144, 0 , 7817 , 315, 151), // #1230 + INST(Vpavgw , VexRvm_Lx , V(660F00,E3,_,x,I,I,4,FVM), 0 , 144, 0 , 7824 , 315, 151), // #1231 + INST(Vpblendd , VexRvmi_Lx , V(660F3A,02,_,x,0,_,_,_ ), 0 , 73 , 0 , 7831 , 214, 134), // #1232 + INST(Vpblendmb , VexRvm_Lx , E(660F38,66,_,x,_,0,4,FVM), 0 , 114, 0 , 7840 , 357, 139), // #1233 + INST(Vpblendmd , VexRvm_Lx , E(660F38,64,_,x,_,0,4,FV ), 0 , 114, 0 , 7850 , 213, 131), // #1234 + INST(Vpblendmq , VexRvm_Lx , E(660F38,64,_,x,_,1,4,FV ), 0 , 113, 0 , 7860 , 212, 131), // #1235 + INST(Vpblendmw , VexRvm_Lx , E(660F38,66,_,x,_,1,4,FVM), 0 , 113, 0 , 7870 , 357, 139), // #1236 + INST(Vpblendvb , VexRvmr_Lx , V(660F3A,4C,_,x,0,_,_,_ ), 0 , 73 , 0 , 7880 , 215, 148), // #1237 + INST(Vpblendw , VexRvmi_Lx , V(660F3A,0E,_,x,I,_,_,_ ), 0 , 73 , 0 , 7890 , 214, 148), // #1238 + INST(Vpbroadcastb , VexRm_Lx_Bcst , V(660F38,78,_,x,0,0,0,T1S), E(660F38,7A,_,x,0,0,0,T1S), 96 , 108, 7899 , 358, 152), // #1239 + INST(Vpbroadcastd , VexRm_Lx_Bcst , V(660F38,58,_,x,0,0,2,T1S), E(660F38,7C,_,x,0,0,0,T1S), 122, 109, 7912 , 359, 145), // #1240 + INST(Vpbroadcastmb2q , VexRm_Lx , E(F30F38,2A,_,x,_,1,_,_ ), 0 , 205, 0 , 7925 , 360, 153), // #1241 + INST(Vpbroadcastmw2d , VexRm_Lx , E(F30F38,3A,_,x,_,0,_,_ ), 0 , 206, 0 , 7941 , 360, 153), // #1242 + INST(Vpbroadcastq , VexRm_Lx_Bcst , V(660F38,59,_,x,0,1,3,T1S), E(660F38,7C,_,x,0,1,0,T1S), 121, 110, 7957 , 361, 145), // #1243 + INST(Vpbroadcastw , VexRm_Lx_Bcst , V(660F38,79,_,x,0,0,1,T1S), E(660F38,7B,_,x,0,0,0,T1S), 207, 111, 7970 , 362, 152), // #1244 + INST(Vpclmulqdq , VexRvmi_Lx , V(660F3A,44,_,x,I,_,4,FVM), 0 , 204, 0 , 7983 , 363, 154), // #1245 + INST(Vpcmov , VexRvrmRvmr_Lx , V(XOP_M8,A2,_,x,x,_,_,_ ), 0 , 208, 0 , 7994 , 289, 144), // #1246 + INST(Vpcmpb , VexRvmi_Lx , E(660F3A,3F,_,x,_,0,4,FVM), 0 , 111, 0 , 8001 , 364, 139), // #1247 + INST(Vpcmpd , VexRvmi_Lx , E(660F3A,1F,_,x,_,0,4,FV ), 0 , 111, 0 , 8008 , 365, 131), // #1248 + INST(Vpcmpeqb , VexRvm_Lx_KEvex , V(660F00,74,_,x,I,I,4,FV ), 0 , 144, 0 , 8015 , 366, 151), // #1249 + INST(Vpcmpeqd , VexRvm_Lx_KEvex , V(660F00,76,_,x,I,0,4,FVM), 0 , 144, 0 , 8024 , 367, 135), // #1250 + INST(Vpcmpeqq , VexRvm_Lx_KEvex , V(660F38,29,_,x,I,1,4,FVM), 0 , 209, 0 , 8033 , 368, 135), // #1251 + INST(Vpcmpeqw , VexRvm_Lx_KEvex , V(660F00,75,_,x,I,I,4,FV ), 0 , 144, 0 , 8042 , 366, 151), // #1252 + INST(Vpcmpestri , VexRmi , V(660F3A,61,_,0,I,_,_,_ ), 0 , 73 , 0 , 8051 , 369, 155), // #1253 + INST(Vpcmpestrm , VexRmi , V(660F3A,60,_,0,I,_,_,_ ), 0 , 73 , 0 , 8062 , 370, 155), // #1254 + INST(Vpcmpgtb , VexRvm_Lx_KEvex , V(660F00,64,_,x,I,I,4,FV ), 0 , 144, 0 , 8073 , 366, 151), // #1255 + INST(Vpcmpgtd , VexRvm_Lx_KEvex , V(660F00,66,_,x,I,0,4,FVM), 0 , 144, 0 , 8082 , 367, 135), // #1256 + INST(Vpcmpgtq , VexRvm_Lx_KEvex , V(660F38,37,_,x,I,1,4,FVM), 0 , 209, 0 , 8091 , 368, 135), // #1257 + INST(Vpcmpgtw , VexRvm_Lx_KEvex , V(660F00,65,_,x,I,I,4,FV ), 0 , 144, 0 , 8100 , 366, 151), // #1258 + INST(Vpcmpistri , VexRmi , V(660F3A,63,_,0,I,_,_,_ ), 0 , 73 , 0 , 8109 , 371, 155), // #1259 + INST(Vpcmpistrm , VexRmi , V(660F3A,62,_,0,I,_,_,_ ), 0 , 73 , 0 , 8120 , 372, 155), // #1260 + INST(Vpcmpq , VexRvmi_Lx , E(660F3A,1F,_,x,_,1,4,FV ), 0 , 112, 0 , 8131 , 373, 131), // #1261 + INST(Vpcmpub , VexRvmi_Lx , E(660F3A,3E,_,x,_,0,4,FVM), 0 , 111, 0 , 8138 , 364, 139), // #1262 + INST(Vpcmpud , VexRvmi_Lx , E(660F3A,1E,_,x,_,0,4,FV ), 0 , 111, 0 , 8146 , 365, 131), // #1263 + INST(Vpcmpuq , VexRvmi_Lx , E(660F3A,1E,_,x,_,1,4,FV ), 0 , 112, 0 , 8154 , 373, 131), // #1264 + INST(Vpcmpuw , VexRvmi_Lx , E(660F3A,3E,_,x,_,1,4,FVM), 0 , 112, 0 , 8162 , 373, 139), // #1265 + INST(Vpcmpw , VexRvmi_Lx , E(660F3A,3F,_,x,_,1,4,FVM), 0 , 112, 0 , 8170 , 373, 139), // #1266 + INST(Vpcomb , VexRvmi , V(XOP_M8,CC,_,0,0,_,_,_ ), 0 , 208, 0 , 8177 , 276, 144), // #1267 + INST(Vpcomd , VexRvmi , V(XOP_M8,CE,_,0,0,_,_,_ ), 0 , 208, 0 , 8184 , 276, 144), // #1268 + INST(Vpcompressb , VexMr_Lx , E(660F38,63,_,x,_,0,0,T1S), 0 , 210, 0 , 8191 , 232, 156), // #1269 + INST(Vpcompressd , VexMr_Lx , E(660F38,8B,_,x,_,0,2,T1S), 0 , 129, 0 , 8203 , 232, 131), // #1270 + INST(Vpcompressq , VexMr_Lx , E(660F38,8B,_,x,_,1,3,T1S), 0 , 128, 0 , 8215 , 232, 131), // #1271 + INST(Vpcompressw , VexMr_Lx , E(660F38,63,_,x,_,1,1,T1S), 0 , 211, 0 , 8227 , 232, 156), // #1272 + INST(Vpcomq , VexRvmi , V(XOP_M8,CF,_,0,0,_,_,_ ), 0 , 208, 0 , 8239 , 276, 144), // #1273 + INST(Vpcomub , VexRvmi , V(XOP_M8,EC,_,0,0,_,_,_ ), 0 , 208, 0 , 8246 , 276, 144), // #1274 + INST(Vpcomud , VexRvmi , V(XOP_M8,EE,_,0,0,_,_,_ ), 0 , 208, 0 , 8254 , 276, 144), // #1275 + INST(Vpcomuq , VexRvmi , V(XOP_M8,EF,_,0,0,_,_,_ ), 0 , 208, 0 , 8262 , 276, 144), // #1276 + INST(Vpcomuw , VexRvmi , V(XOP_M8,ED,_,0,0,_,_,_ ), 0 , 208, 0 , 8270 , 276, 144), // #1277 + INST(Vpcomw , VexRvmi , V(XOP_M8,CD,_,0,0,_,_,_ ), 0 , 208, 0 , 8278 , 276, 144), // #1278 + INST(Vpconflictd , VexRm_Lx , E(660F38,C4,_,x,_,0,4,FV ), 0 , 114, 0 , 8285 , 374, 153), // #1279 + INST(Vpconflictq , VexRm_Lx , E(660F38,C4,_,x,_,1,4,FV ), 0 , 113, 0 , 8297 , 374, 153), // #1280 + INST(Vpdpbusd , VexRvm_Lx , V(660F38,50,_,x,_,0,4,FV ), 0 , 110, 0 , 8309 , 375, 157), // #1281 + INST(Vpdpbusds , VexRvm_Lx , V(660F38,51,_,x,_,0,4,FV ), 0 , 110, 0 , 8318 , 375, 157), // #1282 + INST(Vpdpwssd , VexRvm_Lx , V(660F38,52,_,x,_,0,4,FV ), 0 , 110, 0 , 8328 , 375, 157), // #1283 + INST(Vpdpwssds , VexRvm_Lx , V(660F38,53,_,x,_,0,4,FV ), 0 , 110, 0 , 8337 , 375, 157), // #1284 + INST(Vperm2f128 , VexRvmi , V(660F3A,06,_,1,0,_,_,_ ), 0 , 172, 0 , 8347 , 376, 128), // #1285 + INST(Vperm2i128 , VexRvmi , V(660F3A,46,_,1,0,_,_,_ ), 0 , 172, 0 , 8358 , 376, 134), // #1286 + INST(Vpermb , VexRvm_Lx , E(660F38,8D,_,x,_,0,4,FVM), 0 , 114, 0 , 8369 , 357, 158), // #1287 + INST(Vpermd , VexRvm_Lx , V(660F38,36,_,x,0,0,4,FV ), 0 , 110, 0 , 8376 , 377, 145), // #1288 + INST(Vpermi2b , VexRvm_Lx , E(660F38,75,_,x,_,0,4,FVM), 0 , 114, 0 , 8383 , 357, 158), // #1289 + INST(Vpermi2d , VexRvm_Lx , E(660F38,76,_,x,_,0,4,FV ), 0 , 114, 0 , 8392 , 213, 131), // #1290 + INST(Vpermi2pd , VexRvm_Lx , E(660F38,77,_,x,_,1,4,FV ), 0 , 113, 0 , 8401 , 212, 131), // #1291 + INST(Vpermi2ps , VexRvm_Lx , E(660F38,77,_,x,_,0,4,FV ), 0 , 114, 0 , 8411 , 213, 131), // #1292 + INST(Vpermi2q , VexRvm_Lx , E(660F38,76,_,x,_,1,4,FV ), 0 , 113, 0 , 8421 , 212, 131), // #1293 + INST(Vpermi2w , VexRvm_Lx , E(660F38,75,_,x,_,1,4,FVM), 0 , 113, 0 , 8430 , 357, 139), // #1294 + INST(Vpermil2pd , VexRvrmiRvmri_Lx , V(660F3A,49,_,x,x,_,_,_ ), 0 , 73 , 0 , 8439 , 378, 144), // #1295 + INST(Vpermil2ps , VexRvrmiRvmri_Lx , V(660F3A,48,_,x,x,_,_,_ ), 0 , 73 , 0 , 8450 , 378, 144), // #1296 + INST(Vpermilpd , VexRvmRmi_Lx , V(660F38,0D,_,x,0,1,4,FV ), V(660F3A,05,_,x,0,1,4,FV ), 209, 112, 8461 , 379, 124), // #1297 + INST(Vpermilps , VexRvmRmi_Lx , V(660F38,0C,_,x,0,0,4,FV ), V(660F3A,04,_,x,0,0,4,FV ), 110, 113, 8471 , 380, 124), // #1298 + INST(Vpermpd , VexRvmRmi_Lx , E(660F38,16,_,x,1,1,4,FV ), V(660F3A,01,_,x,1,1,4,FV ), 212, 114, 8481 , 381, 145), // #1299 + INST(Vpermps , VexRvm_Lx , V(660F38,16,_,x,0,0,4,FV ), 0 , 110, 0 , 8489 , 377, 145), // #1300 + INST(Vpermq , VexRvmRmi_Lx , E(660F38,36,_,x,_,1,4,FV ), V(660F3A,00,_,x,1,1,4,FV ), 113, 115, 8497 , 381, 145), // #1301 + INST(Vpermt2b , VexRvm_Lx , E(660F38,7D,_,x,_,0,4,FVM), 0 , 114, 0 , 8504 , 357, 158), // #1302 + INST(Vpermt2d , VexRvm_Lx , E(660F38,7E,_,x,_,0,4,FV ), 0 , 114, 0 , 8513 , 213, 131), // #1303 + INST(Vpermt2pd , VexRvm_Lx , E(660F38,7F,_,x,_,1,4,FV ), 0 , 113, 0 , 8522 , 212, 131), // #1304 + INST(Vpermt2ps , VexRvm_Lx , E(660F38,7F,_,x,_,0,4,FV ), 0 , 114, 0 , 8532 , 213, 131), // #1305 + INST(Vpermt2q , VexRvm_Lx , E(660F38,7E,_,x,_,1,4,FV ), 0 , 113, 0 , 8542 , 212, 131), // #1306 + INST(Vpermt2w , VexRvm_Lx , E(660F38,7D,_,x,_,1,4,FVM), 0 , 113, 0 , 8551 , 357, 139), // #1307 + INST(Vpermw , VexRvm_Lx , E(660F38,8D,_,x,_,1,4,FVM), 0 , 113, 0 , 8560 , 357, 139), // #1308 + INST(Vpexpandb , VexRm_Lx , E(660F38,62,_,x,_,0,0,T1S), 0 , 210, 0 , 8567 , 279, 156), // #1309 + INST(Vpexpandd , VexRm_Lx , E(660F38,89,_,x,_,0,2,T1S), 0 , 129, 0 , 8577 , 279, 131), // #1310 + INST(Vpexpandq , VexRm_Lx , E(660F38,89,_,x,_,1,3,T1S), 0 , 128, 0 , 8587 , 279, 131), // #1311 + INST(Vpexpandw , VexRm_Lx , E(660F38,62,_,x,_,1,1,T1S), 0 , 211, 0 , 8597 , 279, 156), // #1312 + INST(Vpextrb , VexMri , V(660F3A,14,_,0,0,I,0,T1S), 0 , 73 , 0 , 8607 , 382, 159), // #1313 + INST(Vpextrd , VexMri , V(660F3A,16,_,0,0,0,2,T1S), 0 , 177, 0 , 8615 , 283, 160), // #1314 + INST(Vpextrq , VexMri , V(660F3A,16,_,0,1,1,3,T1S), 0 , 213, 0 , 8623 , 383, 160), // #1315 + INST(Vpextrw , VexMri_Vpextrw , V(660F3A,15,_,0,0,I,1,T1S), 0 , 214, 0 , 8631 , 384, 159), // #1316 + INST(Vpgatherdd , VexRmvRm_VM , V(660F38,90,_,x,0,_,_,_ ), E(660F38,90,_,x,_,0,2,T1S), 96 , 116, 8639 , 302, 145), // #1317 + INST(Vpgatherdq , VexRmvRm_VM , V(660F38,90,_,x,1,_,_,_ ), E(660F38,90,_,x,_,1,3,T1S), 189, 117, 8650 , 301, 145), // #1318 + INST(Vpgatherqd , VexRmvRm_VM , V(660F38,91,_,x,0,_,_,_ ), E(660F38,91,_,x,_,0,2,T1S), 96 , 118, 8661 , 307, 145), // #1319 + INST(Vpgatherqq , VexRmvRm_VM , V(660F38,91,_,x,1,_,_,_ ), E(660F38,91,_,x,_,1,3,T1S), 189, 119, 8672 , 306, 145), // #1320 + INST(Vphaddbd , VexRm , V(XOP_M9,C2,_,0,0,_,_,_ ), 0 , 79 , 0 , 8683 , 204, 144), // #1321 + INST(Vphaddbq , VexRm , V(XOP_M9,C3,_,0,0,_,_,_ ), 0 , 79 , 0 , 8692 , 204, 144), // #1322 + INST(Vphaddbw , VexRm , V(XOP_M9,C1,_,0,0,_,_,_ ), 0 , 79 , 0 , 8701 , 204, 144), // #1323 + INST(Vphaddd , VexRvm_Lx , V(660F38,02,_,x,I,_,_,_ ), 0 , 96 , 0 , 8710 , 202, 148), // #1324 + INST(Vphadddq , VexRm , V(XOP_M9,CB,_,0,0,_,_,_ ), 0 , 79 , 0 , 8718 , 204, 144), // #1325 + INST(Vphaddsw , VexRvm_Lx , V(660F38,03,_,x,I,_,_,_ ), 0 , 96 , 0 , 8727 , 202, 148), // #1326 + INST(Vphaddubd , VexRm , V(XOP_M9,D2,_,0,0,_,_,_ ), 0 , 79 , 0 , 8736 , 204, 144), // #1327 + INST(Vphaddubq , VexRm , V(XOP_M9,D3,_,0,0,_,_,_ ), 0 , 79 , 0 , 8746 , 204, 144), // #1328 + INST(Vphaddubw , VexRm , V(XOP_M9,D1,_,0,0,_,_,_ ), 0 , 79 , 0 , 8756 , 204, 144), // #1329 + INST(Vphaddudq , VexRm , V(XOP_M9,DB,_,0,0,_,_,_ ), 0 , 79 , 0 , 8766 , 204, 144), // #1330 + INST(Vphadduwd , VexRm , V(XOP_M9,D6,_,0,0,_,_,_ ), 0 , 79 , 0 , 8776 , 204, 144), // #1331 + INST(Vphadduwq , VexRm , V(XOP_M9,D7,_,0,0,_,_,_ ), 0 , 79 , 0 , 8786 , 204, 144), // #1332 + INST(Vphaddw , VexRvm_Lx , V(660F38,01,_,x,I,_,_,_ ), 0 , 96 , 0 , 8796 , 202, 148), // #1333 + INST(Vphaddwd , VexRm , V(XOP_M9,C6,_,0,0,_,_,_ ), 0 , 79 , 0 , 8804 , 204, 144), // #1334 + INST(Vphaddwq , VexRm , V(XOP_M9,C7,_,0,0,_,_,_ ), 0 , 79 , 0 , 8813 , 204, 144), // #1335 + INST(Vphminposuw , VexRm , V(660F38,41,_,0,I,_,_,_ ), 0 , 96 , 0 , 8822 , 204, 128), // #1336 + INST(Vphsubbw , VexRm , V(XOP_M9,E1,_,0,0,_,_,_ ), 0 , 79 , 0 , 8834 , 204, 144), // #1337 + INST(Vphsubd , VexRvm_Lx , V(660F38,06,_,x,I,_,_,_ ), 0 , 96 , 0 , 8843 , 202, 148), // #1338 + INST(Vphsubdq , VexRm , V(XOP_M9,E3,_,0,0,_,_,_ ), 0 , 79 , 0 , 8851 , 204, 144), // #1339 + INST(Vphsubsw , VexRvm_Lx , V(660F38,07,_,x,I,_,_,_ ), 0 , 96 , 0 , 8860 , 202, 148), // #1340 + INST(Vphsubw , VexRvm_Lx , V(660F38,05,_,x,I,_,_,_ ), 0 , 96 , 0 , 8869 , 202, 148), // #1341 + INST(Vphsubwd , VexRm , V(XOP_M9,E2,_,0,0,_,_,_ ), 0 , 79 , 0 , 8877 , 204, 144), // #1342 + INST(Vpinsrb , VexRvmi , V(660F3A,20,_,0,0,I,0,T1S), 0 , 73 , 0 , 8886 , 385, 159), // #1343 + INST(Vpinsrd , VexRvmi , V(660F3A,22,_,0,0,0,2,T1S), 0 , 177, 0 , 8894 , 386, 160), // #1344 + INST(Vpinsrq , VexRvmi , V(660F3A,22,_,0,1,1,3,T1S), 0 , 213, 0 , 8902 , 387, 160), // #1345 + INST(Vpinsrw , VexRvmi , V(660F00,C4,_,0,0,I,1,T1S), 0 , 215, 0 , 8910 , 388, 159), // #1346 + INST(Vplzcntd , VexRm_Lx , E(660F38,44,_,x,_,0,4,FV ), 0 , 114, 0 , 8918 , 374, 153), // #1347 + INST(Vplzcntq , VexRm_Lx , E(660F38,44,_,x,_,1,4,FV ), 0 , 113, 0 , 8927 , 350, 153), // #1348 + INST(Vpmacsdd , VexRvmr , V(XOP_M8,9E,_,0,0,_,_,_ ), 0 , 208, 0 , 8936 , 389, 144), // #1349 + INST(Vpmacsdqh , VexRvmr , V(XOP_M8,9F,_,0,0,_,_,_ ), 0 , 208, 0 , 8945 , 389, 144), // #1350 + INST(Vpmacsdql , VexRvmr , V(XOP_M8,97,_,0,0,_,_,_ ), 0 , 208, 0 , 8955 , 389, 144), // #1351 + INST(Vpmacssdd , VexRvmr , V(XOP_M8,8E,_,0,0,_,_,_ ), 0 , 208, 0 , 8965 , 389, 144), // #1352 + INST(Vpmacssdqh , VexRvmr , V(XOP_M8,8F,_,0,0,_,_,_ ), 0 , 208, 0 , 8975 , 389, 144), // #1353 + INST(Vpmacssdql , VexRvmr , V(XOP_M8,87,_,0,0,_,_,_ ), 0 , 208, 0 , 8986 , 389, 144), // #1354 + INST(Vpmacsswd , VexRvmr , V(XOP_M8,86,_,0,0,_,_,_ ), 0 , 208, 0 , 8997 , 389, 144), // #1355 + INST(Vpmacssww , VexRvmr , V(XOP_M8,85,_,0,0,_,_,_ ), 0 , 208, 0 , 9007 , 389, 144), // #1356 + INST(Vpmacswd , VexRvmr , V(XOP_M8,96,_,0,0,_,_,_ ), 0 , 208, 0 , 9017 , 389, 144), // #1357 + INST(Vpmacsww , VexRvmr , V(XOP_M8,95,_,0,0,_,_,_ ), 0 , 208, 0 , 9026 , 389, 144), // #1358 + INST(Vpmadcsswd , VexRvmr , V(XOP_M8,A6,_,0,0,_,_,_ ), 0 , 208, 0 , 9035 , 389, 144), // #1359 + INST(Vpmadcswd , VexRvmr , V(XOP_M8,B6,_,0,0,_,_,_ ), 0 , 208, 0 , 9046 , 389, 144), // #1360 + INST(Vpmadd52huq , VexRvm_Lx , E(660F38,B5,_,x,_,1,4,FV ), 0 , 113, 0 , 9056 , 212, 161), // #1361 + INST(Vpmadd52luq , VexRvm_Lx , E(660F38,B4,_,x,_,1,4,FV ), 0 , 113, 0 , 9068 , 212, 161), // #1362 + INST(Vpmaddubsw , VexRvm_Lx , V(660F38,04,_,x,I,I,4,FVM), 0 , 110, 0 , 9080 , 315, 151), // #1363 + INST(Vpmaddwd , VexRvm_Lx , V(660F00,F5,_,x,I,I,4,FVM), 0 , 144, 0 , 9091 , 315, 151), // #1364 + INST(Vpmaskmovd , VexRvmMvr_Lx , V(660F38,8C,_,x,0,_,_,_ ), V(660F38,8E,_,x,0,_,_,_ ), 96 , 120, 9100 , 323, 134), // #1365 + INST(Vpmaskmovq , VexRvmMvr_Lx , V(660F38,8C,_,x,1,_,_,_ ), V(660F38,8E,_,x,1,_,_,_ ), 189, 121, 9111 , 323, 134), // #1366 + INST(Vpmaxsb , VexRvm_Lx , V(660F38,3C,_,x,I,I,4,FVM), 0 , 110, 0 , 9122 , 390, 151), // #1367 + INST(Vpmaxsd , VexRvm_Lx , V(660F38,3D,_,x,I,0,4,FV ), 0 , 110, 0 , 9130 , 211, 135), // #1368 + INST(Vpmaxsq , VexRvm_Lx , E(660F38,3D,_,x,_,1,4,FV ), 0 , 113, 0 , 9138 , 212, 131), // #1369 + INST(Vpmaxsw , VexRvm_Lx , V(660F00,EE,_,x,I,I,4,FVM), 0 , 144, 0 , 9146 , 390, 151), // #1370 + INST(Vpmaxub , VexRvm_Lx , V(660F00,DE,_,x,I,I,4,FVM), 0 , 144, 0 , 9154 , 390, 151), // #1371 + INST(Vpmaxud , VexRvm_Lx , V(660F38,3F,_,x,I,0,4,FV ), 0 , 110, 0 , 9162 , 211, 135), // #1372 + INST(Vpmaxuq , VexRvm_Lx , E(660F38,3F,_,x,_,1,4,FV ), 0 , 113, 0 , 9170 , 212, 131), // #1373 + INST(Vpmaxuw , VexRvm_Lx , V(660F38,3E,_,x,I,I,4,FVM), 0 , 110, 0 , 9178 , 390, 151), // #1374 + INST(Vpminsb , VexRvm_Lx , V(660F38,38,_,x,I,I,4,FVM), 0 , 110, 0 , 9186 , 390, 151), // #1375 + INST(Vpminsd , VexRvm_Lx , V(660F38,39,_,x,I,0,4,FV ), 0 , 110, 0 , 9194 , 211, 135), // #1376 + INST(Vpminsq , VexRvm_Lx , E(660F38,39,_,x,_,1,4,FV ), 0 , 113, 0 , 9202 , 212, 131), // #1377 + INST(Vpminsw , VexRvm_Lx , V(660F00,EA,_,x,I,I,4,FVM), 0 , 144, 0 , 9210 , 390, 151), // #1378 + INST(Vpminub , VexRvm_Lx , V(660F00,DA,_,x,I,_,4,FVM), 0 , 144, 0 , 9218 , 390, 151), // #1379 + INST(Vpminud , VexRvm_Lx , V(660F38,3B,_,x,I,0,4,FV ), 0 , 110, 0 , 9226 , 211, 135), // #1380 + INST(Vpminuq , VexRvm_Lx , E(660F38,3B,_,x,_,1,4,FV ), 0 , 113, 0 , 9234 , 212, 131), // #1381 + INST(Vpminuw , VexRvm_Lx , V(660F38,3A,_,x,I,_,4,FVM), 0 , 110, 0 , 9242 , 390, 151), // #1382 + INST(Vpmovb2m , VexRm_Lx , E(F30F38,29,_,x,_,0,_,_ ), 0 , 206, 0 , 9250 , 391, 139), // #1383 + INST(Vpmovd2m , VexRm_Lx , E(F30F38,39,_,x,_,0,_,_ ), 0 , 206, 0 , 9259 , 391, 133), // #1384 + INST(Vpmovdb , VexMr_Lx , E(F30F38,31,_,x,_,0,2,QVM), 0 , 216, 0 , 9268 , 392, 131), // #1385 + INST(Vpmovdw , VexMr_Lx , E(F30F38,33,_,x,_,0,3,HVM), 0 , 217, 0 , 9276 , 393, 131), // #1386 + INST(Vpmovm2b , VexRm_Lx , E(F30F38,28,_,x,_,0,_,_ ), 0 , 206, 0 , 9284 , 360, 139), // #1387 + INST(Vpmovm2d , VexRm_Lx , E(F30F38,38,_,x,_,0,_,_ ), 0 , 206, 0 , 9293 , 360, 133), // #1388 + INST(Vpmovm2q , VexRm_Lx , E(F30F38,38,_,x,_,1,_,_ ), 0 , 205, 0 , 9302 , 360, 133), // #1389 + INST(Vpmovm2w , VexRm_Lx , E(F30F38,28,_,x,_,1,_,_ ), 0 , 205, 0 , 9311 , 360, 139), // #1390 + INST(Vpmovmskb , VexRm_Lx , V(660F00,D7,_,x,I,_,_,_ ), 0 , 69 , 0 , 9320 , 336, 148), // #1391 + INST(Vpmovq2m , VexRm_Lx , E(F30F38,39,_,x,_,1,_,_ ), 0 , 205, 0 , 9330 , 391, 133), // #1392 + INST(Vpmovqb , VexMr_Lx , E(F30F38,32,_,x,_,0,1,OVM), 0 , 218, 0 , 9339 , 394, 131), // #1393 + INST(Vpmovqd , VexMr_Lx , E(F30F38,35,_,x,_,0,3,HVM), 0 , 217, 0 , 9347 , 393, 131), // #1394 + INST(Vpmovqw , VexMr_Lx , E(F30F38,34,_,x,_,0,2,QVM), 0 , 216, 0 , 9355 , 392, 131), // #1395 + INST(Vpmovsdb , VexMr_Lx , E(F30F38,21,_,x,_,0,2,QVM), 0 , 216, 0 , 9363 , 392, 131), // #1396 + INST(Vpmovsdw , VexMr_Lx , E(F30F38,23,_,x,_,0,3,HVM), 0 , 217, 0 , 9372 , 393, 131), // #1397 + INST(Vpmovsqb , VexMr_Lx , E(F30F38,22,_,x,_,0,1,OVM), 0 , 218, 0 , 9381 , 394, 131), // #1398 + INST(Vpmovsqd , VexMr_Lx , E(F30F38,25,_,x,_,0,3,HVM), 0 , 217, 0 , 9390 , 393, 131), // #1399 + INST(Vpmovsqw , VexMr_Lx , E(F30F38,24,_,x,_,0,2,QVM), 0 , 216, 0 , 9399 , 392, 131), // #1400 + INST(Vpmovswb , VexMr_Lx , E(F30F38,20,_,x,_,0,3,HVM), 0 , 217, 0 , 9408 , 393, 139), // #1401 + INST(Vpmovsxbd , VexRm_Lx , V(660F38,21,_,x,I,I,2,QVM), 0 , 219, 0 , 9417 , 395, 135), // #1402 + INST(Vpmovsxbq , VexRm_Lx , V(660F38,22,_,x,I,I,1,OVM), 0 , 220, 0 , 9427 , 396, 135), // #1403 + INST(Vpmovsxbw , VexRm_Lx , V(660F38,20,_,x,I,I,3,HVM), 0 , 139, 0 , 9437 , 397, 151), // #1404 + INST(Vpmovsxdq , VexRm_Lx , V(660F38,25,_,x,I,0,3,HVM), 0 , 139, 0 , 9447 , 397, 135), // #1405 + INST(Vpmovsxwd , VexRm_Lx , V(660F38,23,_,x,I,I,3,HVM), 0 , 139, 0 , 9457 , 397, 135), // #1406 + INST(Vpmovsxwq , VexRm_Lx , V(660F38,24,_,x,I,I,2,QVM), 0 , 219, 0 , 9467 , 395, 135), // #1407 + INST(Vpmovusdb , VexMr_Lx , E(F30F38,11,_,x,_,0,2,QVM), 0 , 216, 0 , 9477 , 392, 131), // #1408 + INST(Vpmovusdw , VexMr_Lx , E(F30F38,13,_,x,_,0,3,HVM), 0 , 217, 0 , 9487 , 393, 131), // #1409 + INST(Vpmovusqb , VexMr_Lx , E(F30F38,12,_,x,_,0,1,OVM), 0 , 218, 0 , 9497 , 394, 131), // #1410 + INST(Vpmovusqd , VexMr_Lx , E(F30F38,15,_,x,_,0,3,HVM), 0 , 217, 0 , 9507 , 393, 131), // #1411 + INST(Vpmovusqw , VexMr_Lx , E(F30F38,14,_,x,_,0,2,QVM), 0 , 216, 0 , 9517 , 392, 131), // #1412 + INST(Vpmovuswb , VexMr_Lx , E(F30F38,10,_,x,_,0,3,HVM), 0 , 217, 0 , 9527 , 393, 139), // #1413 + INST(Vpmovw2m , VexRm_Lx , E(F30F38,29,_,x,_,1,_,_ ), 0 , 205, 0 , 9537 , 391, 139), // #1414 + INST(Vpmovwb , VexMr_Lx , E(F30F38,30,_,x,_,0,3,HVM), 0 , 217, 0 , 9546 , 393, 139), // #1415 + INST(Vpmovzxbd , VexRm_Lx , V(660F38,31,_,x,I,I,2,QVM), 0 , 219, 0 , 9554 , 395, 135), // #1416 + INST(Vpmovzxbq , VexRm_Lx , V(660F38,32,_,x,I,I,1,OVM), 0 , 220, 0 , 9564 , 396, 135), // #1417 + INST(Vpmovzxbw , VexRm_Lx , V(660F38,30,_,x,I,I,3,HVM), 0 , 139, 0 , 9574 , 397, 151), // #1418 + INST(Vpmovzxdq , VexRm_Lx , V(660F38,35,_,x,I,0,3,HVM), 0 , 139, 0 , 9584 , 397, 135), // #1419 + INST(Vpmovzxwd , VexRm_Lx , V(660F38,33,_,x,I,I,3,HVM), 0 , 139, 0 , 9594 , 397, 135), // #1420 + INST(Vpmovzxwq , VexRm_Lx , V(660F38,34,_,x,I,I,2,QVM), 0 , 219, 0 , 9604 , 395, 135), // #1421 + INST(Vpmuldq , VexRvm_Lx , V(660F38,28,_,x,I,1,4,FV ), 0 , 209, 0 , 9614 , 208, 135), // #1422 + INST(Vpmulhrsw , VexRvm_Lx , V(660F38,0B,_,x,I,I,4,FVM), 0 , 110, 0 , 9622 , 315, 151), // #1423 + INST(Vpmulhuw , VexRvm_Lx , V(660F00,E4,_,x,I,I,4,FVM), 0 , 144, 0 , 9632 , 315, 151), // #1424 + INST(Vpmulhw , VexRvm_Lx , V(660F00,E5,_,x,I,I,4,FVM), 0 , 144, 0 , 9641 , 315, 151), // #1425 + INST(Vpmulld , VexRvm_Lx , V(660F38,40,_,x,I,0,4,FV ), 0 , 110, 0 , 9649 , 209, 135), // #1426 + INST(Vpmullq , VexRvm_Lx , E(660F38,40,_,x,_,1,4,FV ), 0 , 113, 0 , 9657 , 212, 133), // #1427 + INST(Vpmullw , VexRvm_Lx , V(660F00,D5,_,x,I,I,4,FVM), 0 , 144, 0 , 9665 , 315, 151), // #1428 + INST(Vpmultishiftqb , VexRvm_Lx , E(660F38,83,_,x,_,1,4,FV ), 0 , 113, 0 , 9673 , 212, 158), // #1429 + INST(Vpmuludq , VexRvm_Lx , V(660F00,F4,_,x,I,1,4,FV ), 0 , 103, 0 , 9688 , 208, 135), // #1430 + INST(Vpopcntb , VexRm_Lx , E(660F38,54,_,x,_,0,4,FV ), 0 , 114, 0 , 9697 , 279, 162), // #1431 + INST(Vpopcntd , VexRm_Lx , E(660F38,55,_,x,_,0,4,FVM), 0 , 114, 0 , 9706 , 374, 163), // #1432 + INST(Vpopcntq , VexRm_Lx , E(660F38,55,_,x,_,1,4,FVM), 0 , 113, 0 , 9715 , 350, 163), // #1433 + INST(Vpopcntw , VexRm_Lx , E(660F38,54,_,x,_,1,4,FV ), 0 , 113, 0 , 9724 , 279, 162), // #1434 + INST(Vpor , VexRvm_Lx , V(660F00,EB,_,x,I,_,_,_ ), 0 , 69 , 0 , 9733 , 351, 148), // #1435 + INST(Vpord , VexRvm_Lx , E(660F00,EB,_,x,_,0,4,FV ), 0 , 198, 0 , 9738 , 352, 131), // #1436 + INST(Vporq , VexRvm_Lx , E(660F00,EB,_,x,_,1,4,FV ), 0 , 135, 0 , 9744 , 356, 131), // #1437 + INST(Vpperm , VexRvrmRvmr , V(XOP_M8,A3,_,0,x,_,_,_ ), 0 , 208, 0 , 9750 , 398, 144), // #1438 + INST(Vprold , VexVmi_Lx , E(660F00,72,1,x,_,0,4,FV ), 0 , 221, 0 , 9757 , 399, 131), // #1439 + INST(Vprolq , VexVmi_Lx , E(660F00,72,1,x,_,1,4,FV ), 0 , 222, 0 , 9764 , 400, 131), // #1440 + INST(Vprolvd , VexRvm_Lx , E(660F38,15,_,x,_,0,4,FV ), 0 , 114, 0 , 9771 , 213, 131), // #1441 + INST(Vprolvq , VexRvm_Lx , E(660F38,15,_,x,_,1,4,FV ), 0 , 113, 0 , 9779 , 212, 131), // #1442 + INST(Vprord , VexVmi_Lx , E(660F00,72,0,x,_,0,4,FV ), 0 , 198, 0 , 9787 , 399, 131), // #1443 + INST(Vprorq , VexVmi_Lx , E(660F00,72,0,x,_,1,4,FV ), 0 , 135, 0 , 9794 , 400, 131), // #1444 + INST(Vprorvd , VexRvm_Lx , E(660F38,14,_,x,_,0,4,FV ), 0 , 114, 0 , 9801 , 213, 131), // #1445 + INST(Vprorvq , VexRvm_Lx , E(660F38,14,_,x,_,1,4,FV ), 0 , 113, 0 , 9809 , 212, 131), // #1446 + INST(Vprotb , VexRvmRmvRmi , V(XOP_M9,90,_,0,x,_,_,_ ), V(XOP_M8,C0,_,0,x,_,_,_ ), 79 , 122, 9817 , 401, 144), // #1447 + INST(Vprotd , VexRvmRmvRmi , V(XOP_M9,92,_,0,x,_,_,_ ), V(XOP_M8,C2,_,0,x,_,_,_ ), 79 , 123, 9824 , 401, 144), // #1448 + INST(Vprotq , VexRvmRmvRmi , V(XOP_M9,93,_,0,x,_,_,_ ), V(XOP_M8,C3,_,0,x,_,_,_ ), 79 , 124, 9831 , 401, 144), // #1449 + INST(Vprotw , VexRvmRmvRmi , V(XOP_M9,91,_,0,x,_,_,_ ), V(XOP_M8,C1,_,0,x,_,_,_ ), 79 , 125, 9838 , 401, 144), // #1450 + INST(Vpsadbw , VexRvm_Lx , V(660F00,F6,_,x,I,I,4,FVM), 0 , 144, 0 , 9845 , 203, 151), // #1451 + INST(Vpscatterdd , VexMr_VM , E(660F38,A0,_,x,_,0,2,T1S), 0 , 129, 0 , 9853 , 402, 131), // #1452 + INST(Vpscatterdq , VexMr_VM , E(660F38,A0,_,x,_,1,3,T1S), 0 , 128, 0 , 9865 , 403, 131), // #1453 + INST(Vpscatterqd , VexMr_VM , E(660F38,A1,_,x,_,0,2,T1S), 0 , 129, 0 , 9877 , 404, 131), // #1454 + INST(Vpscatterqq , VexMr_VM , E(660F38,A1,_,x,_,1,3,T1S), 0 , 128, 0 , 9889 , 405, 131), // #1455 + INST(Vpshab , VexRvmRmv , V(XOP_M9,98,_,0,x,_,_,_ ), 0 , 79 , 0 , 9901 , 406, 144), // #1456 + INST(Vpshad , VexRvmRmv , V(XOP_M9,9A,_,0,x,_,_,_ ), 0 , 79 , 0 , 9908 , 406, 144), // #1457 + INST(Vpshaq , VexRvmRmv , V(XOP_M9,9B,_,0,x,_,_,_ ), 0 , 79 , 0 , 9915 , 406, 144), // #1458 + INST(Vpshaw , VexRvmRmv , V(XOP_M9,99,_,0,x,_,_,_ ), 0 , 79 , 0 , 9922 , 406, 144), // #1459 + INST(Vpshlb , VexRvmRmv , V(XOP_M9,94,_,0,x,_,_,_ ), 0 , 79 , 0 , 9929 , 406, 144), // #1460 + INST(Vpshld , VexRvmRmv , V(XOP_M9,96,_,0,x,_,_,_ ), 0 , 79 , 0 , 9936 , 406, 144), // #1461 + INST(Vpshldd , VexRvmi_Lx , E(660F3A,71,_,x,_,0,4,FV ), 0 , 111, 0 , 9943 , 206, 156), // #1462 + INST(Vpshldq , VexRvmi_Lx , E(660F3A,71,_,x,_,1,4,FV ), 0 , 112, 0 , 9951 , 207, 156), // #1463 + INST(Vpshldvd , VexRvm_Lx , E(660F38,71,_,x,_,0,4,FV ), 0 , 114, 0 , 9959 , 213, 156), // #1464 + INST(Vpshldvq , VexRvm_Lx , E(660F38,71,_,x,_,1,4,FV ), 0 , 113, 0 , 9968 , 212, 156), // #1465 + INST(Vpshldvw , VexRvm_Lx , E(660F38,70,_,x,_,1,4,FVM), 0 , 113, 0 , 9977 , 357, 156), // #1466 + INST(Vpshldw , VexRvmi_Lx , E(660F3A,70,_,x,_,1,4,FVM), 0 , 112, 0 , 9986 , 275, 156), // #1467 + INST(Vpshlq , VexRvmRmv , V(XOP_M9,97,_,0,x,_,_,_ ), 0 , 79 , 0 , 9994 , 406, 144), // #1468 + INST(Vpshlw , VexRvmRmv , V(XOP_M9,95,_,0,x,_,_,_ ), 0 , 79 , 0 , 10001, 406, 144), // #1469 + INST(Vpshrdd , VexRvmi_Lx , E(660F3A,73,_,x,_,0,4,FV ), 0 , 111, 0 , 10008, 206, 156), // #1470 + INST(Vpshrdq , VexRvmi_Lx , E(660F3A,73,_,x,_,1,4,FV ), 0 , 112, 0 , 10016, 207, 156), // #1471 + INST(Vpshrdvd , VexRvm_Lx , E(660F38,73,_,x,_,0,4,FV ), 0 , 114, 0 , 10024, 213, 156), // #1472 + INST(Vpshrdvq , VexRvm_Lx , E(660F38,73,_,x,_,1,4,FV ), 0 , 113, 0 , 10033, 212, 156), // #1473 + INST(Vpshrdvw , VexRvm_Lx , E(660F38,72,_,x,_,1,4,FVM), 0 , 113, 0 , 10042, 357, 156), // #1474 + INST(Vpshrdw , VexRvmi_Lx , E(660F3A,72,_,x,_,1,4,FVM), 0 , 112, 0 , 10051, 275, 156), // #1475 + INST(Vpshufb , VexRvm_Lx , V(660F38,00,_,x,I,I,4,FVM), 0 , 110, 0 , 10059, 315, 151), // #1476 + INST(Vpshufbitqmb , VexRvm_Lx , E(660F38,8F,_,x,0,0,4,FVM), 0 , 114, 0 , 10067, 407, 162), // #1477 + INST(Vpshufd , VexRmi_Lx , V(660F00,70,_,x,I,0,4,FV ), 0 , 144, 0 , 10080, 408, 135), // #1478 + INST(Vpshufhw , VexRmi_Lx , V(F30F00,70,_,x,I,I,4,FVM), 0 , 161, 0 , 10088, 409, 151), // #1479 + INST(Vpshuflw , VexRmi_Lx , V(F20F00,70,_,x,I,I,4,FVM), 0 , 223, 0 , 10097, 409, 151), // #1480 + INST(Vpsignb , VexRvm_Lx , V(660F38,08,_,x,I,_,_,_ ), 0 , 96 , 0 , 10106, 202, 148), // #1481 + INST(Vpsignd , VexRvm_Lx , V(660F38,0A,_,x,I,_,_,_ ), 0 , 96 , 0 , 10114, 202, 148), // #1482 + INST(Vpsignw , VexRvm_Lx , V(660F38,09,_,x,I,_,_,_ ), 0 , 96 , 0 , 10122, 202, 148), // #1483 + INST(Vpslld , VexRvmVmi_Lx_MEvex , V(660F00,F2,_,x,I,0,4,128), V(660F00,72,6,x,I,0,4,FV ), 224, 126, 10130, 410, 135), // #1484 + INST(Vpslldq , VexVmi_Lx_MEvex , V(660F00,73,7,x,I,I,4,FVM), 0 , 225, 0 , 10137, 411, 151), // #1485 + INST(Vpsllq , VexRvmVmi_Lx_MEvex , V(660F00,F3,_,x,I,1,4,128), V(660F00,73,6,x,I,1,4,FV ), 226, 127, 10145, 412, 135), // #1486 + INST(Vpsllvd , VexRvm_Lx , V(660F38,47,_,x,0,0,4,FV ), 0 , 110, 0 , 10152, 209, 145), // #1487 + INST(Vpsllvq , VexRvm_Lx , V(660F38,47,_,x,1,1,4,FV ), 0 , 182, 0 , 10160, 208, 145), // #1488 + INST(Vpsllvw , VexRvm_Lx , E(660F38,12,_,x,_,1,4,FVM), 0 , 113, 0 , 10168, 357, 139), // #1489 + INST(Vpsllw , VexRvmVmi_Lx_MEvex , V(660F00,F1,_,x,I,I,4,128), V(660F00,71,6,x,I,I,4,FVM), 224, 128, 10176, 413, 151), // #1490 + INST(Vpsrad , VexRvmVmi_Lx_MEvex , V(660F00,E2,_,x,I,0,4,128), V(660F00,72,4,x,I,0,4,FV ), 224, 129, 10183, 410, 135), // #1491 + INST(Vpsraq , VexRvmVmi_Lx_MEvex , E(660F00,E2,_,x,_,1,4,128), E(660F00,72,4,x,_,1,4,FV ), 227, 130, 10190, 414, 131), // #1492 + INST(Vpsravd , VexRvm_Lx , V(660F38,46,_,x,0,0,4,FV ), 0 , 110, 0 , 10197, 209, 145), // #1493 + INST(Vpsravq , VexRvm_Lx , E(660F38,46,_,x,_,1,4,FV ), 0 , 113, 0 , 10205, 212, 131), // #1494 + INST(Vpsravw , VexRvm_Lx , E(660F38,11,_,x,_,1,4,FVM), 0 , 113, 0 , 10213, 357, 139), // #1495 + INST(Vpsraw , VexRvmVmi_Lx_MEvex , V(660F00,E1,_,x,I,I,4,128), V(660F00,71,4,x,I,I,4,FVM), 224, 131, 10221, 413, 151), // #1496 + INST(Vpsrld , VexRvmVmi_Lx_MEvex , V(660F00,D2,_,x,I,0,4,128), V(660F00,72,2,x,I,0,4,FV ), 224, 132, 10228, 410, 135), // #1497 + INST(Vpsrldq , VexVmi_Lx_MEvex , V(660F00,73,3,x,I,I,4,FVM), 0 , 228, 0 , 10235, 411, 151), // #1498 + INST(Vpsrlq , VexRvmVmi_Lx_MEvex , V(660F00,D3,_,x,I,1,4,128), V(660F00,73,2,x,I,1,4,FV ), 226, 133, 10243, 412, 135), // #1499 + INST(Vpsrlvd , VexRvm_Lx , V(660F38,45,_,x,0,0,4,FV ), 0 , 110, 0 , 10250, 209, 145), // #1500 + INST(Vpsrlvq , VexRvm_Lx , V(660F38,45,_,x,1,1,4,FV ), 0 , 182, 0 , 10258, 208, 145), // #1501 + INST(Vpsrlvw , VexRvm_Lx , E(660F38,10,_,x,_,1,4,FVM), 0 , 113, 0 , 10266, 357, 139), // #1502 + INST(Vpsrlw , VexRvmVmi_Lx_MEvex , V(660F00,D1,_,x,I,I,4,128), V(660F00,71,2,x,I,I,4,FVM), 224, 134, 10274, 413, 151), // #1503 + INST(Vpsubb , VexRvm_Lx , V(660F00,F8,_,x,I,I,4,FVM), 0 , 144, 0 , 10281, 415, 151), // #1504 + INST(Vpsubd , VexRvm_Lx , V(660F00,FA,_,x,I,0,4,FV ), 0 , 144, 0 , 10288, 416, 135), // #1505 + INST(Vpsubq , VexRvm_Lx , V(660F00,FB,_,x,I,1,4,FV ), 0 , 103, 0 , 10295, 417, 135), // #1506 + INST(Vpsubsb , VexRvm_Lx , V(660F00,E8,_,x,I,I,4,FVM), 0 , 144, 0 , 10302, 415, 151), // #1507 + INST(Vpsubsw , VexRvm_Lx , V(660F00,E9,_,x,I,I,4,FVM), 0 , 144, 0 , 10310, 415, 151), // #1508 + INST(Vpsubusb , VexRvm_Lx , V(660F00,D8,_,x,I,I,4,FVM), 0 , 144, 0 , 10318, 415, 151), // #1509 + INST(Vpsubusw , VexRvm_Lx , V(660F00,D9,_,x,I,I,4,FVM), 0 , 144, 0 , 10327, 415, 151), // #1510 + INST(Vpsubw , VexRvm_Lx , V(660F00,F9,_,x,I,I,4,FVM), 0 , 144, 0 , 10336, 415, 151), // #1511 + INST(Vpternlogd , VexRvmi_Lx , E(660F3A,25,_,x,_,0,4,FV ), 0 , 111, 0 , 10343, 206, 131), // #1512 + INST(Vpternlogq , VexRvmi_Lx , E(660F3A,25,_,x,_,1,4,FV ), 0 , 112, 0 , 10354, 207, 131), // #1513 + INST(Vptest , VexRm_Lx , V(660F38,17,_,x,I,_,_,_ ), 0 , 96 , 0 , 10365, 298, 155), // #1514 + INST(Vptestmb , VexRvm_Lx , E(660F38,26,_,x,_,0,4,FVM), 0 , 114, 0 , 10372, 407, 139), // #1515 + INST(Vptestmd , VexRvm_Lx , E(660F38,27,_,x,_,0,4,FV ), 0 , 114, 0 , 10381, 418, 131), // #1516 + INST(Vptestmq , VexRvm_Lx , E(660F38,27,_,x,_,1,4,FV ), 0 , 113, 0 , 10390, 419, 131), // #1517 + INST(Vptestmw , VexRvm_Lx , E(660F38,26,_,x,_,1,4,FVM), 0 , 113, 0 , 10399, 407, 139), // #1518 + INST(Vptestnmb , VexRvm_Lx , E(F30F38,26,_,x,_,0,4,FVM), 0 , 132, 0 , 10408, 407, 139), // #1519 + INST(Vptestnmd , VexRvm_Lx , E(F30F38,27,_,x,_,0,4,FV ), 0 , 132, 0 , 10418, 418, 131), // #1520 + INST(Vptestnmq , VexRvm_Lx , E(F30F38,27,_,x,_,1,4,FV ), 0 , 229, 0 , 10428, 419, 131), // #1521 + INST(Vptestnmw , VexRvm_Lx , E(F30F38,26,_,x,_,1,4,FVM), 0 , 229, 0 , 10438, 407, 139), // #1522 + INST(Vpunpckhbw , VexRvm_Lx , V(660F00,68,_,x,I,I,4,FVM), 0 , 144, 0 , 10448, 315, 151), // #1523 + INST(Vpunpckhdq , VexRvm_Lx , V(660F00,6A,_,x,I,0,4,FV ), 0 , 144, 0 , 10459, 209, 135), // #1524 + INST(Vpunpckhqdq , VexRvm_Lx , V(660F00,6D,_,x,I,1,4,FV ), 0 , 103, 0 , 10470, 208, 135), // #1525 + INST(Vpunpckhwd , VexRvm_Lx , V(660F00,69,_,x,I,I,4,FVM), 0 , 144, 0 , 10482, 315, 151), // #1526 + INST(Vpunpcklbw , VexRvm_Lx , V(660F00,60,_,x,I,I,4,FVM), 0 , 144, 0 , 10493, 315, 151), // #1527 + INST(Vpunpckldq , VexRvm_Lx , V(660F00,62,_,x,I,0,4,FV ), 0 , 144, 0 , 10504, 209, 135), // #1528 + INST(Vpunpcklqdq , VexRvm_Lx , V(660F00,6C,_,x,I,1,4,FV ), 0 , 103, 0 , 10515, 208, 135), // #1529 + INST(Vpunpcklwd , VexRvm_Lx , V(660F00,61,_,x,I,I,4,FVM), 0 , 144, 0 , 10527, 315, 151), // #1530 + INST(Vpxor , VexRvm_Lx , V(660F00,EF,_,x,I,_,_,_ ), 0 , 69 , 0 , 10538, 353, 148), // #1531 + INST(Vpxord , VexRvm_Lx , E(660F00,EF,_,x,_,0,4,FV ), 0 , 198, 0 , 10544, 354, 131), // #1532 + INST(Vpxorq , VexRvm_Lx , E(660F00,EF,_,x,_,1,4,FV ), 0 , 135, 0 , 10551, 355, 131), // #1533 + INST(Vrangepd , VexRvmi_Lx , E(660F3A,50,_,x,_,1,4,FV ), 0 , 112, 0 , 10558, 285, 133), // #1534 + INST(Vrangeps , VexRvmi_Lx , E(660F3A,50,_,x,_,0,4,FV ), 0 , 111, 0 , 10567, 286, 133), // #1535 + INST(Vrangesd , VexRvmi , E(660F3A,51,_,I,_,1,3,T1S), 0 , 180, 0 , 10576, 287, 66 ), // #1536 + INST(Vrangess , VexRvmi , E(660F3A,51,_,I,_,0,2,T1S), 0 , 181, 0 , 10585, 288, 66 ), // #1537 + INST(Vrcp14pd , VexRm_Lx , E(660F38,4C,_,x,_,1,4,FV ), 0 , 113, 0 , 10594, 350, 131), // #1538 + INST(Vrcp14ps , VexRm_Lx , E(660F38,4C,_,x,_,0,4,FV ), 0 , 114, 0 , 10603, 374, 131), // #1539 + INST(Vrcp14sd , VexRvm , E(660F38,4D,_,I,_,1,3,T1S), 0 , 128, 0 , 10612, 420, 68 ), // #1540 + INST(Vrcp14ss , VexRvm , E(660F38,4D,_,I,_,0,2,T1S), 0 , 129, 0 , 10621, 421, 68 ), // #1541 + INST(Vrcp28pd , VexRm , E(660F38,CA,_,2,_,1,4,FV ), 0 , 170, 0 , 10630, 277, 140), // #1542 + INST(Vrcp28ps , VexRm , E(660F38,CA,_,2,_,0,4,FV ), 0 , 171, 0 , 10639, 278, 140), // #1543 + INST(Vrcp28sd , VexRvm , E(660F38,CB,_,I,_,1,3,T1S), 0 , 128, 0 , 10648, 308, 140), // #1544 + INST(Vrcp28ss , VexRvm , E(660F38,CB,_,I,_,0,2,T1S), 0 , 129, 0 , 10657, 309, 140), // #1545 + INST(Vrcpph , VexRm_Lx , E(66MAP6,4C,_,_,_,0,4,FV ), 0 , 183, 0 , 10666, 422, 127), // #1546 + INST(Vrcpps , VexRm_Lx , V(000F00,53,_,x,I,_,_,_ ), 0 , 72 , 0 , 10673, 298, 128), // #1547 + INST(Vrcpsh , VexRvm , E(66MAP6,4D,_,_,_,0,1,T1S), 0 , 185, 0 , 10680, 423, 127), // #1548 + INST(Vrcpss , VexRvm , V(F30F00,53,_,I,I,_,_,_ ), 0 , 199, 0 , 10687, 424, 128), // #1549 + INST(Vreducepd , VexRmi_Lx , E(660F3A,56,_,x,_,1,4,FV ), 0 , 112, 0 , 10694, 400, 133), // #1550 + INST(Vreduceph , VexRmi_Lx , E(000F3A,56,_,_,_,0,4,FV ), 0 , 123, 0 , 10704, 311, 125), // #1551 + INST(Vreduceps , VexRmi_Lx , E(660F3A,56,_,x,_,0,4,FV ), 0 , 111, 0 , 10714, 399, 133), // #1552 + INST(Vreducesd , VexRvmi , E(660F3A,57,_,I,_,1,3,T1S), 0 , 180, 0 , 10724, 425, 66 ), // #1553 + INST(Vreducesh , VexRvmi , E(000F3A,57,_,_,_,0,1,T1S), 0 , 188, 0 , 10734, 313, 127), // #1554 + INST(Vreducess , VexRvmi , E(660F3A,57,_,I,_,0,2,T1S), 0 , 181, 0 , 10744, 426, 66 ), // #1555 + INST(Vrndscalepd , VexRmi_Lx , E(660F3A,09,_,x,_,1,4,FV ), 0 , 112, 0 , 10754, 310, 131), // #1556 + INST(Vrndscaleph , VexRmi_Lx , E(000F3A,08,_,_,_,0,4,FV ), 0 , 123, 0 , 10766, 311, 125), // #1557 + INST(Vrndscaleps , VexRmi_Lx , E(660F3A,08,_,x,_,0,4,FV ), 0 , 111, 0 , 10778, 312, 131), // #1558 + INST(Vrndscalesd , VexRvmi , E(660F3A,0B,_,I,_,1,3,T1S), 0 , 180, 0 , 10790, 287, 68 ), // #1559 + INST(Vrndscalesh , VexRvmi , E(000F3A,0A,_,_,_,0,1,T1S), 0 , 188, 0 , 10802, 313, 127), // #1560 + INST(Vrndscaless , VexRvmi , E(660F3A,0A,_,I,_,0,2,T1S), 0 , 181, 0 , 10814, 288, 68 ), // #1561 + INST(Vroundpd , VexRmi_Lx , V(660F3A,09,_,x,I,_,_,_ ), 0 , 73 , 0 , 10826, 427, 128), // #1562 + INST(Vroundps , VexRmi_Lx , V(660F3A,08,_,x,I,_,_,_ ), 0 , 73 , 0 , 10835, 427, 128), // #1563 + INST(Vroundsd , VexRvmi , V(660F3A,0B,_,I,I,_,_,_ ), 0 , 73 , 0 , 10844, 428, 128), // #1564 + INST(Vroundss , VexRvmi , V(660F3A,0A,_,I,I,_,_,_ ), 0 , 73 , 0 , 10853, 429, 128), // #1565 + INST(Vrsqrt14pd , VexRm_Lx , E(660F38,4E,_,x,_,1,4,FV ), 0 , 113, 0 , 10862, 350, 131), // #1566 + INST(Vrsqrt14ps , VexRm_Lx , E(660F38,4E,_,x,_,0,4,FV ), 0 , 114, 0 , 10873, 374, 131), // #1567 + INST(Vrsqrt14sd , VexRvm , E(660F38,4F,_,I,_,1,3,T1S), 0 , 128, 0 , 10884, 420, 68 ), // #1568 + INST(Vrsqrt14ss , VexRvm , E(660F38,4F,_,I,_,0,2,T1S), 0 , 129, 0 , 10895, 421, 68 ), // #1569 + INST(Vrsqrt28pd , VexRm , E(660F38,CC,_,2,_,1,4,FV ), 0 , 170, 0 , 10906, 277, 140), // #1570 + INST(Vrsqrt28ps , VexRm , E(660F38,CC,_,2,_,0,4,FV ), 0 , 171, 0 , 10917, 278, 140), // #1571 + INST(Vrsqrt28sd , VexRvm , E(660F38,CD,_,I,_,1,3,T1S), 0 , 128, 0 , 10928, 308, 140), // #1572 + INST(Vrsqrt28ss , VexRvm , E(660F38,CD,_,I,_,0,2,T1S), 0 , 129, 0 , 10939, 309, 140), // #1573 + INST(Vrsqrtph , VexRm_Lx , E(66MAP6,4E,_,_,_,0,4,FV ), 0 , 183, 0 , 10950, 422, 125), // #1574 + INST(Vrsqrtps , VexRm_Lx , V(000F00,52,_,x,I,_,_,_ ), 0 , 72 , 0 , 10959, 298, 128), // #1575 + INST(Vrsqrtsh , VexRvm , E(66MAP6,4F,_,_,_,0,1,T1S), 0 , 185, 0 , 10968, 423, 127), // #1576 + INST(Vrsqrtss , VexRvm , V(F30F00,52,_,I,I,_,_,_ ), 0 , 199, 0 , 10977, 424, 128), // #1577 + INST(Vscalefpd , VexRvm_Lx , E(660F38,2C,_,x,_,1,4,FV ), 0 , 113, 0 , 10986, 430, 131), // #1578 + INST(Vscalefph , VexRvm_Lx , E(66MAP6,2C,_,_,_,0,4,FV ), 0 , 183, 0 , 10996, 197, 125), // #1579 + INST(Vscalefps , VexRvm_Lx , E(660F38,2C,_,x,_,0,4,FV ), 0 , 114, 0 , 11006, 284, 131), // #1580 + INST(Vscalefsd , VexRvm , E(660F38,2D,_,I,_,1,3,T1S), 0 , 128, 0 , 11016, 251, 68 ), // #1581 + INST(Vscalefsh , VexRvm , E(66MAP6,2D,_,_,_,0,1,T1S), 0 , 185, 0 , 11026, 200, 127), // #1582 + INST(Vscalefss , VexRvm , E(660F38,2D,_,I,_,0,2,T1S), 0 , 129, 0 , 11036, 259, 68 ), // #1583 + INST(Vscatterdpd , VexMr_VM , E(660F38,A2,_,x,_,1,3,T1S), 0 , 128, 0 , 11046, 403, 131), // #1584 + INST(Vscatterdps , VexMr_VM , E(660F38,A2,_,x,_,0,2,T1S), 0 , 129, 0 , 11058, 402, 131), // #1585 + INST(Vscatterpf0dpd , VexM_VM , E(660F38,C6,5,2,_,1,3,T1S), 0 , 230, 0 , 11070, 303, 146), // #1586 + INST(Vscatterpf0dps , VexM_VM , E(660F38,C6,5,2,_,0,2,T1S), 0 , 231, 0 , 11085, 304, 146), // #1587 + INST(Vscatterpf0qpd , VexM_VM , E(660F38,C7,5,2,_,1,3,T1S), 0 , 230, 0 , 11100, 305, 146), // #1588 + INST(Vscatterpf0qps , VexM_VM , E(660F38,C7,5,2,_,0,2,T1S), 0 , 231, 0 , 11115, 305, 146), // #1589 + INST(Vscatterpf1dpd , VexM_VM , E(660F38,C6,6,2,_,1,3,T1S), 0 , 232, 0 , 11130, 303, 146), // #1590 + INST(Vscatterpf1dps , VexM_VM , E(660F38,C6,6,2,_,0,2,T1S), 0 , 233, 0 , 11145, 304, 146), // #1591 + INST(Vscatterpf1qpd , VexM_VM , E(660F38,C7,6,2,_,1,3,T1S), 0 , 232, 0 , 11160, 305, 146), // #1592 + INST(Vscatterpf1qps , VexM_VM , E(660F38,C7,6,2,_,0,2,T1S), 0 , 233, 0 , 11175, 305, 146), // #1593 + INST(Vscatterqpd , VexMr_VM , E(660F38,A3,_,x,_,1,3,T1S), 0 , 128, 0 , 11190, 405, 131), // #1594 + INST(Vscatterqps , VexMr_VM , E(660F38,A3,_,x,_,0,2,T1S), 0 , 129, 0 , 11202, 404, 131), // #1595 + INST(Vshuff32x4 , VexRvmi_Lx , E(660F3A,23,_,x,_,0,4,FV ), 0 , 111, 0 , 11214, 431, 131), // #1596 + INST(Vshuff64x2 , VexRvmi_Lx , E(660F3A,23,_,x,_,1,4,FV ), 0 , 112, 0 , 11225, 432, 131), // #1597 + INST(Vshufi32x4 , VexRvmi_Lx , E(660F3A,43,_,x,_,0,4,FV ), 0 , 111, 0 , 11236, 431, 131), // #1598 + INST(Vshufi64x2 , VexRvmi_Lx , E(660F3A,43,_,x,_,1,4,FV ), 0 , 112, 0 , 11247, 432, 131), // #1599 + INST(Vshufpd , VexRvmi_Lx , V(660F00,C6,_,x,I,1,4,FV ), 0 , 103, 0 , 11258, 433, 124), // #1600 + INST(Vshufps , VexRvmi_Lx , V(000F00,C6,_,x,I,0,4,FV ), 0 , 105, 0 , 11266, 434, 124), // #1601 + INST(Vsqrtpd , VexRm_Lx , V(660F00,51,_,x,I,1,4,FV ), 0 , 103, 0 , 11274, 435, 124), // #1602 + INST(Vsqrtph , VexRm_Lx , E(00MAP5,51,_,_,_,0,4,FV ), 0 , 104, 0 , 11282, 246, 125), // #1603 + INST(Vsqrtps , VexRm_Lx , V(000F00,51,_,x,I,0,4,FV ), 0 , 105, 0 , 11290, 235, 124), // #1604 + INST(Vsqrtsd , VexRvm , V(F20F00,51,_,I,I,1,3,T1S), 0 , 106, 0 , 11298, 199, 126), // #1605 + INST(Vsqrtsh , VexRvm , E(F3MAP5,51,_,_,_,0,1,T1S), 0 , 107, 0 , 11306, 200, 127), // #1606 + INST(Vsqrtss , VexRvm , V(F30F00,51,_,I,I,0,2,T1S), 0 , 108, 0 , 11314, 201, 126), // #1607 + INST(Vstmxcsr , VexM , V(000F00,AE,3,0,I,_,_,_ ), 0 , 234, 0 , 11322, 321, 128), // #1608 + INST(Vsubpd , VexRvm_Lx , V(660F00,5C,_,x,I,1,4,FV ), 0 , 103, 0 , 11331, 196, 124), // #1609 + INST(Vsubph , VexRvm_Lx , E(00MAP5,5C,_,_,_,0,4,FV ), 0 , 104, 0 , 11338, 197, 125), // #1610 + INST(Vsubps , VexRvm_Lx , V(000F00,5C,_,x,I,0,4,FV ), 0 , 105, 0 , 11345, 198, 124), // #1611 + INST(Vsubsd , VexRvm , V(F20F00,5C,_,I,I,1,3,T1S), 0 , 106, 0 , 11352, 199, 126), // #1612 + INST(Vsubsh , VexRvm , E(F3MAP5,5C,_,_,_,0,1,T1S), 0 , 107, 0 , 11359, 200, 127), // #1613 + INST(Vsubss , VexRvm , V(F30F00,5C,_,I,I,0,2,T1S), 0 , 108, 0 , 11366, 201, 126), // #1614 + INST(Vtestpd , VexRm_Lx , V(660F38,0F,_,x,0,_,_,_ ), 0 , 96 , 0 , 11373, 298, 155), // #1615 + INST(Vtestps , VexRm_Lx , V(660F38,0E,_,x,0,_,_,_ ), 0 , 96 , 0 , 11381, 298, 155), // #1616 + INST(Vucomisd , VexRm , V(660F00,2E,_,I,I,1,3,T1S), 0 , 125, 0 , 11389, 229, 136), // #1617 + INST(Vucomish , VexRm , E(00MAP5,2E,_,_,_,0,1,T1S), 0 , 126, 0 , 11398, 230, 127), // #1618 + INST(Vucomiss , VexRm , V(000F00,2E,_,I,I,0,2,T1S), 0 , 127, 0 , 11407, 231, 136), // #1619 + INST(Vunpckhpd , VexRvm_Lx , V(660F00,15,_,x,I,1,4,FV ), 0 , 103, 0 , 11416, 208, 124), // #1620 + INST(Vunpckhps , VexRvm_Lx , V(000F00,15,_,x,I,0,4,FV ), 0 , 105, 0 , 11426, 209, 124), // #1621 + INST(Vunpcklpd , VexRvm_Lx , V(660F00,14,_,x,I,1,4,FV ), 0 , 103, 0 , 11436, 208, 124), // #1622 + INST(Vunpcklps , VexRvm_Lx , V(000F00,14,_,x,I,0,4,FV ), 0 , 105, 0 , 11446, 209, 124), // #1623 + INST(Vxorpd , VexRvm_Lx , V(660F00,57,_,x,I,1,4,FV ), 0 , 103, 0 , 11456, 417, 132), // #1624 + INST(Vxorps , VexRvm_Lx , V(000F00,57,_,x,I,0,4,FV ), 0 , 105, 0 , 11463, 416, 132), // #1625 + INST(Vzeroall , VexOp , V(000F00,77,_,1,I,_,_,_ ), 0 , 68 , 0 , 11470, 436, 128), // #1626 + INST(Vzeroupper , VexOp , V(000F00,77,_,0,I,_,_,_ ), 0 , 72 , 0 , 11479, 436, 128), // #1627 + INST(Wbinvd , X86Op , O(000F00,09,_,_,_,_,_,_ ), 0 , 4 , 0 , 11490, 30 , 0 ), // #1628 + INST(Wbnoinvd , X86Op , O(F30F00,09,_,_,_,_,_,_ ), 0 , 6 , 0 , 11497, 30 , 164), // #1629 + INST(Wrfsbase , X86M , O(F30F00,AE,2,_,x,_,_,_ ), 0 , 235, 0 , 11506, 173, 104), // #1630 + INST(Wrgsbase , X86M , O(F30F00,AE,3,_,x,_,_,_ ), 0 , 236, 0 , 11515, 173, 104), // #1631 + INST(Wrmsr , X86Op , O(000F00,30,_,_,_,_,_,_ ), 0 , 4 , 0 , 11524, 174, 105), // #1632 + INST(Wrssd , X86Mr , O(000F38,F6,_,_,_,_,_,_ ), 0 , 83 , 0 , 11530, 437, 56 ), // #1633 + INST(Wrssq , X86Mr , O(000F38,F6,_,_,1,_,_,_ ), 0 , 237, 0 , 11536, 438, 56 ), // #1634 + INST(Wrussd , X86Mr , O(660F38,F5,_,_,_,_,_,_ ), 0 , 2 , 0 , 11542, 437, 56 ), // #1635 + INST(Wrussq , X86Mr , O(660F38,F5,_,_,1,_,_,_ ), 0 , 238, 0 , 11549, 438, 56 ), // #1636 + INST(Xabort , X86Op_Mod11RM_I8 , O(000000,C6,7,_,_,_,_,_ ), 0 , 27 , 0 , 11556, 80 , 165), // #1637 + INST(Xadd , X86Xadd , O(000F00,C0,_,_,x,_,_,_ ), 0 , 4 , 0 , 11563, 439, 38 ), // #1638 + INST(Xbegin , X86JmpRel , O(000000,C7,7,_,_,_,_,_ ), 0 , 27 , 0 , 11568, 440, 165), // #1639 + INST(Xchg , X86Xchg , O(000000,86,_,_,x,_,_,_ ), 0 , 0 , 0 , 462 , 441, 0 ), // #1640 + INST(Xend , X86Op , O(000F01,D5,_,_,_,_,_,_ ), 0 , 21 , 0 , 11575, 30 , 165), // #1641 + INST(Xgetbv , X86Op , O(000F01,D0,_,_,_,_,_,_ ), 0 , 21 , 0 , 11580, 174, 166), // #1642 + INST(Xlatb , X86Op , O(000000,D7,_,_,_,_,_,_ ), 0 , 0 , 0 , 11587, 30 , 0 ), // #1643 + INST(Xor , X86Arith , O(000000,30,6,_,x,_,_,_ ), 0 , 32 , 0 , 10540, 179, 1 ), // #1644 + INST(Xorpd , ExtRm , O(660F00,57,_,_,_,_,_,_ ), 0 , 3 , 0 , 11457, 151, 4 ), // #1645 + INST(Xorps , ExtRm , O(000F00,57,_,_,_,_,_,_ ), 0 , 4 , 0 , 11464, 151, 5 ), // #1646 + INST(Xresldtrk , X86Op , O(F20F01,E9,_,_,_,_,_,_ ), 0 , 92 , 0 , 11593, 30 , 167), // #1647 + INST(Xrstor , X86M_Only_EDX_EAX , O(000F00,AE,5,_,_,_,_,_ ), 0 , 77 , 0 , 1164 , 442, 166), // #1648 + INST(Xrstor64 , X86M_Only_EDX_EAX , O(000F00,AE,5,_,1,_,_,_ ), 0 , 239, 0 , 1172 , 443, 166), // #1649 + INST(Xrstors , X86M_Only_EDX_EAX , O(000F00,C7,3,_,_,_,_,_ ), 0 , 78 , 0 , 11603, 442, 168), // #1650 + INST(Xrstors64 , X86M_Only_EDX_EAX , O(000F00,C7,3,_,1,_,_,_ ), 0 , 240, 0 , 11611, 443, 168), // #1651 + INST(Xsave , X86M_Only_EDX_EAX , O(000F00,AE,4,_,_,_,_,_ ), 0 , 97 , 0 , 1182 , 442, 166), // #1652 + INST(Xsave64 , X86M_Only_EDX_EAX , O(000F00,AE,4,_,1,_,_,_ ), 0 , 241, 0 , 1189 , 443, 166), // #1653 + INST(Xsavec , X86M_Only_EDX_EAX , O(000F00,C7,4,_,_,_,_,_ ), 0 , 97 , 0 , 11621, 442, 169), // #1654 + INST(Xsavec64 , X86M_Only_EDX_EAX , O(000F00,C7,4,_,1,_,_,_ ), 0 , 241, 0 , 11628, 443, 169), // #1655 + INST(Xsaveopt , X86M_Only_EDX_EAX , O(000F00,AE,6,_,_,_,_,_ ), 0 , 80 , 0 , 11637, 442, 170), // #1656 + INST(Xsaveopt64 , X86M_Only_EDX_EAX , O(000F00,AE,6,_,1,_,_,_ ), 0 , 242, 0 , 11646, 443, 170), // #1657 + INST(Xsaves , X86M_Only_EDX_EAX , O(000F00,C7,5,_,_,_,_,_ ), 0 , 77 , 0 , 11657, 442, 168), // #1658 + INST(Xsaves64 , X86M_Only_EDX_EAX , O(000F00,C7,5,_,1,_,_,_ ), 0 , 239, 0 , 11664, 443, 168), // #1659 + INST(Xsetbv , X86Op , O(000F01,D1,_,_,_,_,_,_ ), 0 , 21 , 0 , 11673, 174, 166), // #1660 + INST(Xsusldtrk , X86Op , O(F20F01,E8,_,_,_,_,_,_ ), 0 , 92 , 0 , 11680, 30 , 167), // #1661 + INST(Xtest , X86Op , O(000F01,D6,_,_,_,_,_,_ ), 0 , 21 , 0 , 11690, 30 , 171) // #1662 // ${InstInfo:End} }; #undef NAME_DATA_INDEX #undef INST -// ============================================================================ -// [asmjit::x86::InstDB - Opcode Tables] -// ============================================================================ +// x86::InstDB - Opcode Tables +// =========================== // ${MainOpcodeTable:Begin} // ------------------- Automatically generated, do not edit ------------------- const uint32_t InstDB::_mainOpcodeTable[] = { - O(000000,00,0,0,0,0,0,_ ), // #0 [ref=56x] - O(000000,00,2,0,0,0,0,_ ), // #1 [ref=4x] - O(660F38,00,0,0,0,0,0,_ ), // #2 [ref=43x] - O(660F00,00,0,0,0,0,0,_ ), // #3 [ref=38x] - O(000F00,00,0,0,0,0,0,_ ), // #4 [ref=231x] - O(F20F00,00,0,0,0,0,0,_ ), // #5 [ref=24x] - O(F30F00,00,0,0,0,0,0,_ ), // #6 [ref=29x] - O(F30F38,00,0,0,0,0,0,_ ), // #7 [ref=2x] - O(660F3A,00,0,0,0,0,0,_ ), // #8 [ref=22x] - O(000000,00,4,0,0,0,0,_ ), // #9 [ref=5x] - V(000F38,00,0,0,0,0,0,_ ), // #10 [ref=6x] - V(XOP_M9,00,1,0,0,0,0,_ ), // #11 [ref=3x] - V(XOP_M9,00,6,0,0,0,0,_ ), // #12 [ref=2x] - V(XOP_M9,00,5,0,0,0,0,_ ), // #13 [ref=1x] - V(XOP_M9,00,3,0,0,0,0,_ ), // #14 [ref=1x] - V(XOP_M9,00,2,0,0,0,0,_ ), // #15 [ref=1x] - V(000F38,00,3,0,0,0,0,_ ), // #16 [ref=1x] - V(000F38,00,2,0,0,0,0,_ ), // #17 [ref=1x] - V(000F38,00,1,0,0,0,0,_ ), // #18 [ref=1x] - O(660000,00,0,0,0,0,0,_ ), // #19 [ref=7x] - O(000000,00,0,0,1,0,0,_ ), // #20 [ref=3x] - O(000F01,00,0,0,0,0,0,_ ), // #21 [ref=29x] - O(000F00,00,7,0,0,0,0,_ ), // #22 [ref=5x] - O(660F00,00,7,0,0,0,0,_ ), // #23 [ref=1x] - O(F30F00,00,6,0,0,0,0,_ ), // #24 [ref=4x] - O(F30F01,00,0,0,0,0,0,_ ), // #25 [ref=9x] - O(660F00,00,6,0,0,0,0,_ ), // #26 [ref=3x] - O(000000,00,7,0,0,0,0,_ ), // #27 [ref=5x] - O(000F00,00,1,0,1,0,0,_ ), // #28 [ref=2x] - O(000F00,00,1,0,0,0,0,_ ), // #29 [ref=6x] - O(F20F38,00,0,0,0,0,0,_ ), // #30 [ref=2x] - O(000000,00,1,0,0,0,0,_ ), // #31 [ref=3x] - O(000000,00,6,0,0,0,0,_ ), // #32 [ref=3x] - O(F30F00,00,7,0,0,0,0,3 ), // #33 [ref=1x] - O(F30F00,00,7,0,0,0,0,2 ), // #34 [ref=1x] - O_FPU(00,D900,_) , // #35 [ref=29x] - O_FPU(00,C000,0) , // #36 [ref=1x] - O_FPU(00,DE00,_) , // #37 [ref=7x] - O_FPU(00,0000,4) , // #38 [ref=4x] - O_FPU(00,0000,6) , // #39 [ref=4x] - O_FPU(9B,DB00,_) , // #40 [ref=2x] - O_FPU(00,DA00,_) , // #41 [ref=5x] - O_FPU(00,DB00,_) , // #42 [ref=8x] - O_FPU(00,D000,2) , // #43 [ref=1x] - O_FPU(00,DF00,_) , // #44 [ref=2x] - O_FPU(00,D800,3) , // #45 [ref=1x] - O_FPU(00,F000,6) , // #46 [ref=1x] - O_FPU(00,F800,7) , // #47 [ref=1x] - O_FPU(00,DD00,_) , // #48 [ref=3x] - O_FPU(00,0000,0) , // #49 [ref=3x] - O_FPU(00,0000,2) , // #50 [ref=3x] - O_FPU(00,0000,3) , // #51 [ref=3x] - O_FPU(00,0000,7) , // #52 [ref=3x] - O_FPU(00,0000,1) , // #53 [ref=2x] - O_FPU(00,0000,5) , // #54 [ref=2x] - O_FPU(00,C800,1) , // #55 [ref=1x] - O_FPU(9B,0000,6) , // #56 [ref=2x] - O_FPU(9B,0000,7) , // #57 [ref=2x] - O_FPU(00,E000,4) , // #58 [ref=1x] - O_FPU(00,E800,5) , // #59 [ref=1x] - O_FPU(00,0000,_) , // #60 [ref=1x] - O(000F00,00,0,0,1,0,0,_ ), // #61 [ref=3x] - O(F30F3A,00,0,0,0,0,0,_ ), // #62 [ref=1x] - O(000000,00,5,0,0,0,0,_ ), // #63 [ref=4x] - O(F30F00,00,5,0,0,0,0,_ ), // #64 [ref=2x] - O(F30F00,00,5,0,1,0,0,_ ), // #65 [ref=1x] - V(660F00,00,0,1,0,0,0,_ ), // #66 [ref=7x] - V(660F00,00,0,1,1,0,0,_ ), // #67 [ref=6x] - V(000F00,00,0,1,1,0,0,_ ), // #68 [ref=7x] - V(000F00,00,0,1,0,0,0,_ ), // #69 [ref=8x] - V(660F00,00,0,0,0,0,0,_ ), // #70 [ref=15x] - V(660F00,00,0,0,1,0,0,_ ), // #71 [ref=4x] - V(000F00,00,0,0,1,0,0,_ ), // #72 [ref=4x] - V(000F00,00,0,0,0,0,0,_ ), // #73 [ref=10x] - V(660F3A,00,0,0,0,0,0,_ ), // #74 [ref=45x] - V(660F3A,00,0,0,1,0,0,_ ), // #75 [ref=4x] - O(000000,00,3,0,0,0,0,_ ), // #76 [ref=4x] - O(000F00,00,2,0,0,0,0,_ ), // #77 [ref=5x] - O(000F00,00,5,0,0,0,0,_ ), // #78 [ref=4x] - O(000F00,00,3,0,0,0,0,_ ), // #79 [ref=5x] - V(XOP_M9,00,0,0,0,0,0,_ ), // #80 [ref=32x] - O(000F00,00,6,0,0,0,0,_ ), // #81 [ref=5x] - V(XOP_MA,00,0,0,0,0,0,_ ), // #82 [ref=1x] - V(XOP_MA,00,1,0,0,0,0,_ ), // #83 [ref=1x] - O(000F38,00,0,0,0,0,0,_ ), // #84 [ref=24x] - V(F20F38,00,0,0,0,0,0,_ ), // #85 [ref=6x] - O(000F3A,00,0,0,0,0,0,_ ), // #86 [ref=4x] - O(F30000,00,0,0,0,0,0,_ ), // #87 [ref=1x] - O(000F0F,00,0,0,0,0,0,_ ), // #88 [ref=26x] - V(F30F38,00,0,0,0,0,0,_ ), // #89 [ref=5x] - O(000F3A,00,0,0,1,0,0,_ ), // #90 [ref=1x] - O(660F3A,00,0,0,1,0,0,_ ), // #91 [ref=1x] - O(F30F00,00,4,0,0,0,0,_ ), // #92 [ref=1x] - O(F20F01,00,0,0,0,0,0,_ ), // #93 [ref=4x] - O(F30F00,00,1,0,0,0,0,_ ), // #94 [ref=3x] - O(F30F00,00,7,0,0,0,0,_ ), // #95 [ref=1x] - V(F20F3A,00,0,0,0,0,0,_ ), // #96 [ref=1x] - V(660F38,00,0,0,0,0,0,_ ), // #97 [ref=25x] - O(000F00,00,4,0,0,0,0,_ ), // #98 [ref=4x] - V(XOP_M9,00,7,0,0,0,0,_ ), // #99 [ref=1x] - V(XOP_M9,00,4,0,0,0,0,_ ), // #100 [ref=1x] - O(F20F00,00,6,0,0,0,0,_ ), // #101 [ref=1x] - E(F20F38,00,0,2,0,0,4,T4X), // #102 [ref=4x] - E(F20F38,00,0,0,0,0,4,T4X), // #103 [ref=2x] - V(660F00,00,0,0,0,1,4,FV ), // #104 [ref=22x] - V(000F00,00,0,0,0,0,4,FV ), // #105 [ref=16x] - V(F20F00,00,0,0,0,1,3,T1S), // #106 [ref=10x] - V(F30F00,00,0,0,0,0,2,T1S), // #107 [ref=10x] - V(F20F00,00,0,0,0,0,0,_ ), // #108 [ref=4x] - V(660F38,00,0,0,0,0,4,FVM), // #109 [ref=14x] - E(660F3A,00,0,0,0,0,4,FV ), // #110 [ref=14x] - E(660F3A,00,0,0,0,1,4,FV ), // #111 [ref=14x] - E(660F38,00,0,0,0,1,4,FV ), // #112 [ref=29x] - E(660F38,00,0,0,0,0,4,FV ), // #113 [ref=18x] - V(660F38,00,0,1,0,0,0,_ ), // #114 [ref=2x] - E(660F38,00,0,0,0,0,3,T2 ), // #115 [ref=2x] - E(660F38,00,0,0,0,0,4,T4 ), // #116 [ref=2x] - E(660F38,00,0,2,0,0,5,T8 ), // #117 [ref=2x] - E(660F38,00,0,0,0,1,4,T2 ), // #118 [ref=2x] - E(660F38,00,0,2,0,1,5,T4 ), // #119 [ref=2x] - V(660F38,00,0,0,0,1,3,T1S), // #120 [ref=2x] - V(660F38,00,0,0,0,0,2,T1S), // #121 [ref=14x] - V(660F00,00,0,0,0,1,3,T1S), // #122 [ref=5x] - V(000F00,00,0,0,0,0,2,T1S), // #123 [ref=2x] - E(660F38,00,0,0,0,1,3,T1S), // #124 [ref=14x] - E(660F38,00,0,0,0,0,2,T1S), // #125 [ref=14x] - V(F30F00,00,0,0,0,0,3,HV ), // #126 [ref=1x] - E(F20F38,00,0,0,0,0,4,FV ), // #127 [ref=2x] - E(F30F38,00,0,0,0,0,4,FV ), // #128 [ref=3x] - V(F20F00,00,0,0,0,1,4,FV ), // #129 [ref=1x] - E(660F00,00,0,0,0,1,4,FV ), // #130 [ref=9x] - E(000F00,00,0,0,0,1,4,FV ), // #131 [ref=3x] - V(660F38,00,0,0,0,0,3,HVM), // #132 [ref=7x] - V(660F00,00,0,0,0,0,4,FV ), // #133 [ref=11x] - V(000F00,00,0,0,0,0,3,HV ), // #134 [ref=1x] - V(660F3A,00,0,0,0,0,3,HVM), // #135 [ref=1x] - E(660F00,00,0,0,0,0,3,HV ), // #136 [ref=4x] - E(000F00,00,0,0,0,0,4,FV ), // #137 [ref=2x] - E(F30F00,00,0,0,0,1,4,FV ), // #138 [ref=2x] - V(F20F00,00,0,0,0,0,3,T1F), // #139 [ref=2x] - E(F20F00,00,0,0,0,0,3,T1F), // #140 [ref=2x] - V(F20F00,00,0,0,0,0,2,T1W), // #141 [ref=1x] - V(F30F00,00,0,0,0,0,2,T1W), // #142 [ref=1x] - V(F30F00,00,0,0,0,0,2,T1F), // #143 [ref=2x] - E(F30F00,00,0,0,0,0,2,T1F), // #144 [ref=2x] - V(F30F00,00,0,0,0,0,4,FV ), // #145 [ref=1x] - E(F30F00,00,0,0,0,0,3,HV ), // #146 [ref=1x] - E(F20F00,00,0,0,0,0,4,FV ), // #147 [ref=1x] - E(F20F00,00,0,0,0,1,4,FV ), // #148 [ref=1x] - E(F20F00,00,0,0,0,0,2,T1W), // #149 [ref=1x] - E(F30F00,00,0,0,0,0,2,T1W), // #150 [ref=1x] - E(660F3A,00,0,0,0,0,4,FVM), // #151 [ref=3x] - E(660F38,00,0,2,0,1,4,FV ), // #152 [ref=3x] - E(660F38,00,0,2,0,0,4,FV ), // #153 [ref=3x] - V(660F3A,00,0,1,0,0,0,_ ), // #154 [ref=6x] - E(660F3A,00,0,0,0,0,4,T4 ), // #155 [ref=4x] - E(660F3A,00,0,2,0,0,5,T8 ), // #156 [ref=4x] - E(660F3A,00,0,0,0,1,4,T2 ), // #157 [ref=4x] - E(660F3A,00,0,2,0,1,5,T4 ), // #158 [ref=4x] - V(660F3A,00,0,0,0,0,2,T1S), // #159 [ref=4x] - E(660F3A,00,0,0,0,1,3,T1S), // #160 [ref=6x] - E(660F3A,00,0,0,0,0,2,T1S), // #161 [ref=6x] - V(660F38,00,0,0,1,1,4,FV ), // #162 [ref=20x] - V(660F38,00,0,0,0,0,4,FV ), // #163 [ref=36x] - V(660F38,00,0,0,1,1,3,T1S), // #164 [ref=12x] - V(660F38,00,0,0,1,0,0,_ ), // #165 [ref=5x] - E(660F38,00,1,2,0,1,3,T1S), // #166 [ref=2x] - E(660F38,00,1,2,0,0,2,T1S), // #167 [ref=2x] - E(660F38,00,2,2,0,1,3,T1S), // #168 [ref=2x] - E(660F38,00,2,2,0,0,2,T1S), // #169 [ref=2x] - V(660F3A,00,0,0,1,1,4,FV ), // #170 [ref=2x] - V(000F00,00,2,0,0,0,0,_ ), // #171 [ref=1x] - V(660F00,00,0,0,0,1,4,FVM), // #172 [ref=3x] - V(000F00,00,0,0,0,0,4,FVM), // #173 [ref=3x] - V(660F00,00,0,0,0,0,2,T1S), // #174 [ref=1x] - V(F20F00,00,0,0,0,1,3,DUP), // #175 [ref=1x] - E(660F00,00,0,0,0,0,4,FVM), // #176 [ref=1x] - E(660F00,00,0,0,0,1,4,FVM), // #177 [ref=1x] - V(F30F00,00,0,0,0,0,0,_ ), // #178 [ref=3x] - E(F20F00,00,0,0,0,1,4,FVM), // #179 [ref=1x] - E(F30F00,00,0,0,0,0,4,FVM), // #180 [ref=1x] - E(F30F00,00,0,0,0,1,4,FVM), // #181 [ref=1x] - E(F20F00,00,0,0,0,0,4,FVM), // #182 [ref=1x] - V(000F00,00,0,0,0,0,3,T2 ), // #183 [ref=2x] - V(660F00,00,0,0,0,0,4,FVM), // #184 [ref=32x] - V(F30F00,00,0,0,0,0,4,FVM), // #185 [ref=3x] - E(F20F38,00,0,0,0,1,4,FV ), // #186 [ref=1x] - V(660F3A,00,0,0,0,0,4,FVM), // #187 [ref=2x] - E(660F00,00,0,0,0,0,4,FV ), // #188 [ref=5x] - E(660F38,00,0,0,0,0,4,FVM), // #189 [ref=7x] - E(660F38,00,0,0,0,1,4,FVM), // #190 [ref=11x] - V(660F38,00,0,0,0,0,0,T1S), // #191 [ref=1x] - E(F30F38,00,0,0,0,1,0,_ ), // #192 [ref=5x] - E(F30F38,00,0,0,0,0,0,_ ), // #193 [ref=5x] - V(660F38,00,0,0,0,0,1,T1S), // #194 [ref=1x] - V(XOP_M8,00,0,0,0,0,0,_ ), // #195 [ref=22x] - V(660F38,00,0,0,0,1,4,FVM), // #196 [ref=2x] - E(660F3A,00,0,0,0,1,4,FVM), // #197 [ref=4x] - E(660F38,00,0,0,0,0,0,T1S), // #198 [ref=2x] - E(660F38,00,0,0,0,1,1,T1S), // #199 [ref=2x] - V(660F38,00,0,0,0,1,4,FV ), // #200 [ref=2x] - E(660F38,00,0,0,1,1,4,FV ), // #201 [ref=1x] - V(660F3A,00,0,0,0,0,0,T1S), // #202 [ref=2x] - V(660F3A,00,0,0,1,1,3,T1S), // #203 [ref=2x] - V(660F3A,00,0,0,0,0,1,T1S), // #204 [ref=1x] - V(660F00,00,0,0,0,0,1,T1S), // #205 [ref=1x] - E(F30F38,00,0,0,0,0,2,QVM), // #206 [ref=6x] - E(F30F38,00,0,0,0,0,3,HVM), // #207 [ref=9x] - E(F30F38,00,0,0,0,0,1,OVM), // #208 [ref=3x] - V(660F38,00,0,0,0,0,2,QVM), // #209 [ref=4x] - V(660F38,00,0,0,0,0,1,OVM), // #210 [ref=2x] - E(660F00,00,1,0,0,0,4,FV ), // #211 [ref=1x] - E(660F00,00,1,0,0,1,4,FV ), // #212 [ref=1x] - V(F20F00,00,0,0,0,0,4,FVM), // #213 [ref=1x] - V(660F00,00,0,0,0,0,4,128), // #214 [ref=6x] - V(660F00,00,7,0,0,0,4,FVM), // #215 [ref=1x] - V(660F00,00,0,0,0,1,4,128), // #216 [ref=2x] - E(660F00,00,0,0,0,1,4,128), // #217 [ref=1x] - V(660F00,00,3,0,0,0,4,FVM), // #218 [ref=1x] - E(F30F38,00,0,0,0,0,4,FVM), // #219 [ref=1x] - E(F30F38,00,0,0,0,1,4,FV ), // #220 [ref=1x] - E(F30F38,00,0,0,0,1,4,FVM), // #221 [ref=1x] - E(660F38,00,5,2,0,1,3,T1S), // #222 [ref=2x] - E(660F38,00,5,2,0,0,2,T1S), // #223 [ref=2x] - E(660F38,00,6,2,0,1,3,T1S), // #224 [ref=2x] - E(660F38,00,6,2,0,0,2,T1S), // #225 [ref=2x] - V(000F00,00,3,0,0,0,0,_ ), // #226 [ref=1x] - O(F30F00,00,2,0,0,0,0,_ ), // #227 [ref=1x] - O(F30F00,00,3,0,0,0,0,_ ), // #228 [ref=1x] - O(000F38,00,0,0,1,0,0,_ ), // #229 [ref=1x] - O(660F38,00,0,0,1,0,0,_ ), // #230 [ref=1x] - O(000F00,00,5,0,1,0,0,_ ), // #231 [ref=2x] - O(000F00,00,3,0,1,0,0,_ ), // #232 [ref=1x] - O(000F00,00,4,0,1,0,0,_ ), // #233 [ref=2x] - O(000F00,00,6,0,1,0,0,_ ) // #234 [ref=1x] + O(000000,00,0,0,0,0,0,0 ), // #0 [ref=56x] + O(000000,00,2,0,0,0,0,0 ), // #1 [ref=4x] + O(660F38,00,0,0,0,0,0,0 ), // #2 [ref=43x] + O(660F00,00,0,0,0,0,0,0 ), // #3 [ref=38x] + O(000F00,00,0,0,0,0,0,0 ), // #4 [ref=231x] + O(F20F00,00,0,0,0,0,0,0 ), // #5 [ref=24x] + O(F30F00,00,0,0,0,0,0,0 ), // #6 [ref=29x] + O(F30F38,00,0,0,0,0,0,0 ), // #7 [ref=2x] + O(660F3A,00,0,0,0,0,0,0 ), // #8 [ref=22x] + O(000000,00,4,0,0,0,0,0 ), // #9 [ref=5x] + V(000F38,00,0,0,0,0,0,None), // #10 [ref=6x] + V(XOP_M9,00,1,0,0,0,0,None), // #11 [ref=3x] + V(XOP_M9,00,6,0,0,0,0,None), // #12 [ref=2x] + V(XOP_M9,00,5,0,0,0,0,None), // #13 [ref=1x] + V(XOP_M9,00,3,0,0,0,0,None), // #14 [ref=1x] + V(XOP_M9,00,2,0,0,0,0,None), // #15 [ref=1x] + V(000F38,00,3,0,0,0,0,None), // #16 [ref=1x] + V(000F38,00,2,0,0,0,0,None), // #17 [ref=1x] + V(000F38,00,1,0,0,0,0,None), // #18 [ref=1x] + O(660000,00,0,0,0,0,0,0 ), // #19 [ref=7x] + O(000000,00,0,0,1,0,0,0 ), // #20 [ref=3x] + O(000F01,00,0,0,0,0,0,0 ), // #21 [ref=29x] + O(000F00,00,7,0,0,0,0,0 ), // #22 [ref=5x] + O(660F00,00,7,0,0,0,0,0 ), // #23 [ref=1x] + O(F30F00,00,6,0,0,0,0,0 ), // #24 [ref=4x] + O(F30F01,00,0,0,0,0,0,0 ), // #25 [ref=9x] + O(660F00,00,6,0,0,0,0,0 ), // #26 [ref=3x] + O(000000,00,7,0,0,0,0,0 ), // #27 [ref=5x] + O(000F00,00,1,0,1,0,0,0 ), // #28 [ref=2x] + O(000F00,00,1,0,0,0,0,0 ), // #29 [ref=6x] + O(F20F38,00,0,0,0,0,0,0 ), // #30 [ref=2x] + O(000000,00,1,0,0,0,0,0 ), // #31 [ref=3x] + O(000000,00,6,0,0,0,0,0 ), // #32 [ref=3x] + O(F30F00,00,7,0,0,0,0,3 ), // #33 [ref=1x] + O(F30F00,00,7,0,0,0,0,2 ), // #34 [ref=1x] + O_FPU(00,D900,0) , // #35 [ref=29x] + O_FPU(00,C000,0) , // #36 [ref=1x] + O_FPU(00,DE00,0) , // #37 [ref=7x] + O_FPU(00,0000,4) , // #38 [ref=4x] + O_FPU(00,0000,6) , // #39 [ref=4x] + O_FPU(9B,DB00,0) , // #40 [ref=2x] + O_FPU(00,DA00,0) , // #41 [ref=5x] + O_FPU(00,DB00,0) , // #42 [ref=8x] + O_FPU(00,D000,2) , // #43 [ref=1x] + O_FPU(00,DF00,0) , // #44 [ref=2x] + O_FPU(00,D800,3) , // #45 [ref=1x] + O_FPU(00,F000,6) , // #46 [ref=1x] + O_FPU(00,F800,7) , // #47 [ref=1x] + O_FPU(00,DD00,0) , // #48 [ref=3x] + O_FPU(00,0000,0) , // #49 [ref=4x] + O_FPU(00,0000,2) , // #50 [ref=3x] + O_FPU(00,0000,3) , // #51 [ref=3x] + O_FPU(00,0000,7) , // #52 [ref=3x] + O_FPU(00,0000,1) , // #53 [ref=2x] + O_FPU(00,0000,5) , // #54 [ref=2x] + O_FPU(00,C800,1) , // #55 [ref=1x] + O_FPU(9B,0000,6) , // #56 [ref=2x] + O_FPU(9B,0000,7) , // #57 [ref=2x] + O_FPU(00,E000,4) , // #58 [ref=1x] + O_FPU(00,E800,5) , // #59 [ref=1x] + O(000F00,00,0,0,1,0,0,0 ), // #60 [ref=3x] + O(F30F3A,00,0,0,0,0,0,0 ), // #61 [ref=1x] + O(000000,00,5,0,0,0,0,0 ), // #62 [ref=4x] + O(F30F00,00,5,0,0,0,0,0 ), // #63 [ref=2x] + O(F30F00,00,5,0,1,0,0,0 ), // #64 [ref=1x] + V(660F00,00,0,1,0,0,0,None), // #65 [ref=7x] + V(660F00,00,0,1,1,0,0,None), // #66 [ref=6x] + V(000F00,00,0,1,1,0,0,None), // #67 [ref=7x] + V(000F00,00,0,1,0,0,0,None), // #68 [ref=8x] + V(660F00,00,0,0,0,0,0,None), // #69 [ref=15x] + V(660F00,00,0,0,1,0,0,None), // #70 [ref=4x] + V(000F00,00,0,0,1,0,0,None), // #71 [ref=4x] + V(000F00,00,0,0,0,0,0,None), // #72 [ref=10x] + V(660F3A,00,0,0,0,0,0,None), // #73 [ref=47x] + V(660F3A,00,0,0,1,0,0,None), // #74 [ref=4x] + O(000000,00,3,0,0,0,0,0 ), // #75 [ref=4x] + O(000F00,00,2,0,0,0,0,0 ), // #76 [ref=5x] + O(000F00,00,5,0,0,0,0,0 ), // #77 [ref=4x] + O(000F00,00,3,0,0,0,0,0 ), // #78 [ref=5x] + V(XOP_M9,00,0,0,0,0,0,None), // #79 [ref=32x] + O(000F00,00,6,0,0,0,0,0 ), // #80 [ref=5x] + V(XOP_MA,00,0,0,0,0,0,None), // #81 [ref=1x] + V(XOP_MA,00,1,0,0,0,0,None), // #82 [ref=1x] + O(000F38,00,0,0,0,0,0,0 ), // #83 [ref=24x] + V(F20F38,00,0,0,0,0,0,None), // #84 [ref=6x] + O(000F3A,00,0,0,0,0,0,0 ), // #85 [ref=4x] + O(F30000,00,0,0,0,0,0,0 ), // #86 [ref=1x] + O(000F0F,00,0,0,0,0,0,0 ), // #87 [ref=26x] + V(F30F38,00,0,0,0,0,0,None), // #88 [ref=5x] + O(000F3A,00,0,0,1,0,0,0 ), // #89 [ref=1x] + O(660F3A,00,0,0,1,0,0,0 ), // #90 [ref=1x] + O(F30F00,00,4,0,0,0,0,0 ), // #91 [ref=1x] + O(F20F01,00,0,0,0,0,0,0 ), // #92 [ref=4x] + O(F30F00,00,1,0,0,0,0,0 ), // #93 [ref=3x] + O(F30F00,00,7,0,0,0,0,0 ), // #94 [ref=1x] + V(F20F3A,00,0,0,0,0,0,None), // #95 [ref=1x] + V(660F38,00,0,0,0,0,0,None), // #96 [ref=26x] + O(000F00,00,4,0,0,0,0,0 ), // #97 [ref=4x] + V(XOP_M9,00,7,0,0,0,0,None), // #98 [ref=1x] + V(XOP_M9,00,4,0,0,0,0,None), // #99 [ref=1x] + O(F20F00,00,6,0,0,0,0,0 ), // #100 [ref=1x] + E(F20F38,00,0,2,0,0,4,None), // #101 [ref=4x] + E(F20F38,00,0,0,0,0,4,None), // #102 [ref=2x] + V(660F00,00,0,0,0,1,4,ByLL), // #103 [ref=25x] + E(00MAP5,00,0,0,0,0,4,ByLL), // #104 [ref=10x] + V(000F00,00,0,0,0,0,4,ByLL), // #105 [ref=19x] + V(F20F00,00,0,0,0,1,3,None), // #106 [ref=10x] + E(F3MAP5,00,0,0,0,0,1,None), // #107 [ref=13x] + V(F30F00,00,0,0,0,0,2,None), // #108 [ref=12x] + V(F20F00,00,0,0,0,0,0,None), // #109 [ref=4x] + V(660F38,00,0,0,0,0,4,ByLL), // #110 [ref=50x] + E(660F3A,00,0,0,0,0,4,ByLL), // #111 [ref=17x] + E(660F3A,00,0,0,0,1,4,ByLL), // #112 [ref=18x] + E(660F38,00,0,0,0,1,4,ByLL), // #113 [ref=40x] + E(660F38,00,0,0,0,0,4,ByLL), // #114 [ref=25x] + V(660F38,00,0,1,0,0,0,None), // #115 [ref=2x] + E(660F38,00,0,0,0,0,3,None), // #116 [ref=2x] + E(660F38,00,0,0,0,0,4,None), // #117 [ref=2x] + E(660F38,00,0,2,0,0,5,None), // #118 [ref=2x] + E(660F38,00,0,0,0,1,4,None), // #119 [ref=2x] + E(660F38,00,0,2,0,1,5,None), // #120 [ref=2x] + V(660F38,00,0,0,0,1,3,None), // #121 [ref=2x] + V(660F38,00,0,0,0,0,2,None), // #122 [ref=14x] + E(000F3A,00,0,0,0,0,4,ByLL), // #123 [ref=5x] + E(F30F3A,00,0,0,0,0,1,None), // #124 [ref=1x] + V(660F00,00,0,0,0,1,3,None), // #125 [ref=5x] + E(00MAP5,00,0,0,0,0,1,None), // #126 [ref=2x] + V(000F00,00,0,0,0,0,2,None), // #127 [ref=2x] + E(660F38,00,0,0,0,1,3,None), // #128 [ref=14x] + E(660F38,00,0,0,0,0,2,None), // #129 [ref=14x] + V(F30F00,00,0,0,0,0,3,ByLL), // #130 [ref=1x] + E(F20F38,00,0,0,0,0,4,ByLL), // #131 [ref=2x] + E(F30F38,00,0,0,0,0,4,ByLL), // #132 [ref=4x] + V(F20F00,00,0,0,0,1,4,ByLL), // #133 [ref=1x] + E(66MAP5,00,0,0,0,1,4,ByLL), // #134 [ref=1x] + E(660F00,00,0,0,0,1,4,ByLL), // #135 [ref=10x] + E(000F00,00,0,0,0,1,4,ByLL), // #136 [ref=3x] + E(66MAP5,00,0,0,0,0,3,ByLL), // #137 [ref=1x] + E(00MAP5,00,0,0,0,0,2,ByLL), // #138 [ref=1x] + V(660F38,00,0,0,0,0,3,ByLL), // #139 [ref=7x] + E(66MAP6,00,0,0,0,0,3,ByLL), // #140 [ref=1x] + E(66MAP5,00,0,0,0,0,2,ByLL), // #141 [ref=4x] + E(00MAP5,00,0,0,0,0,3,ByLL), // #142 [ref=2x] + E(66MAP5,00,0,0,0,0,4,ByLL), // #143 [ref=3x] + V(660F00,00,0,0,0,0,4,ByLL), // #144 [ref=43x] + V(000F00,00,0,0,0,0,3,ByLL), // #145 [ref=1x] + V(660F3A,00,0,0,0,0,3,ByLL), // #146 [ref=1x] + E(660F00,00,0,0,0,0,3,ByLL), // #147 [ref=4x] + E(000F00,00,0,0,0,0,4,ByLL), // #148 [ref=2x] + E(F30F00,00,0,0,0,1,4,ByLL), // #149 [ref=3x] + E(00MAP5,00,0,0,0,1,4,ByLL), // #150 [ref=1x] + E(F2MAP5,00,0,0,0,1,3,None), // #151 [ref=1x] + V(F20F00,00,0,0,0,0,3,None), // #152 [ref=2x] + E(F20F00,00,0,0,0,0,3,None), // #153 [ref=2x] + E(00MAP6,00,0,0,0,0,1,None), // #154 [ref=1x] + V(F20F00,00,0,0,0,0,2,T1W ), // #155 [ref=1x] + E(F3MAP5,00,0,0,0,0,2,T1W ), // #156 [ref=2x] + V(F30F00,00,0,0,0,0,2,T1W ), // #157 [ref=1x] + E(00MAP5,00,0,0,0,0,2,None), // #158 [ref=1x] + E(F30F00,00,0,0,0,0,2,None), // #159 [ref=2x] + E(F3MAP5,00,0,0,0,0,3,ByLL), // #160 [ref=1x] + V(F30F00,00,0,0,0,0,4,ByLL), // #161 [ref=4x] + E(F30F00,00,0,0,0,0,3,ByLL), // #162 [ref=1x] + E(F2MAP5,00,0,0,0,0,4,ByLL), // #163 [ref=2x] + E(F20F00,00,0,0,0,0,4,ByLL), // #164 [ref=2x] + E(F2MAP5,00,0,0,0,1,4,ByLL), // #165 [ref=1x] + E(F20F00,00,0,0,0,1,4,ByLL), // #166 [ref=2x] + E(F20F00,00,0,0,0,0,2,T1W ), // #167 [ref=1x] + E(F30F00,00,0,0,0,0,2,T1W ), // #168 [ref=1x] + E(F3MAP5,00,0,0,0,0,4,ByLL), // #169 [ref=1x] + E(660F38,00,0,2,0,1,4,ByLL), // #170 [ref=3x] + E(660F38,00,0,2,0,0,4,ByLL), // #171 [ref=3x] + V(660F3A,00,0,1,0,0,0,None), // #172 [ref=6x] + E(660F3A,00,0,0,0,0,4,None), // #173 [ref=4x] + E(660F3A,00,0,2,0,0,5,None), // #174 [ref=4x] + E(660F3A,00,0,0,0,1,4,None), // #175 [ref=4x] + E(660F3A,00,0,2,0,1,5,None), // #176 [ref=4x] + V(660F3A,00,0,0,0,0,2,None), // #177 [ref=4x] + E(F2MAP6,00,0,0,0,0,4,ByLL), // #178 [ref=2x] + E(F2MAP6,00,0,0,0,0,2,None), // #179 [ref=2x] + E(660F3A,00,0,0,0,1,3,None), // #180 [ref=6x] + E(660F3A,00,0,0,0,0,2,None), // #181 [ref=6x] + V(660F38,00,0,0,1,1,4,ByLL), // #182 [ref=20x] + E(66MAP6,00,0,0,0,0,4,ByLL), // #183 [ref=22x] + V(660F38,00,0,0,1,1,3,None), // #184 [ref=12x] + E(66MAP6,00,0,0,0,0,1,None), // #185 [ref=16x] + E(F3MAP6,00,0,0,0,0,4,ByLL), // #186 [ref=2x] + E(F3MAP6,00,0,0,0,0,2,None), // #187 [ref=2x] + E(000F3A,00,0,0,0,0,1,None), // #188 [ref=4x] + V(660F38,00,0,0,1,0,0,None), // #189 [ref=5x] + E(660F38,00,1,2,0,1,3,None), // #190 [ref=2x] + E(660F38,00,1,2,0,0,2,None), // #191 [ref=2x] + E(660F38,00,2,2,0,1,3,None), // #192 [ref=2x] + E(660F38,00,2,2,0,0,2,None), // #193 [ref=2x] + V(660F3A,00,0,0,1,1,4,ByLL), // #194 [ref=2x] + V(000F00,00,2,0,0,0,0,None), // #195 [ref=1x] + V(660F00,00,0,0,0,0,2,None), // #196 [ref=1x] + V(F20F00,00,0,0,0,1,3,DUP ), // #197 [ref=1x] + E(660F00,00,0,0,0,0,4,ByLL), // #198 [ref=6x] + V(F30F00,00,0,0,0,0,0,None), // #199 [ref=3x] + E(F30F00,00,0,0,0,0,4,ByLL), // #200 [ref=1x] + V(000F00,00,0,0,0,0,3,None), // #201 [ref=2x] + E(66MAP5,00,0,0,0,0,1,None), // #202 [ref=1x] + E(F20F38,00,0,0,0,1,4,ByLL), // #203 [ref=1x] + V(660F3A,00,0,0,0,0,4,ByLL), // #204 [ref=2x] + E(F30F38,00,0,0,0,1,0,None), // #205 [ref=5x] + E(F30F38,00,0,0,0,0,0,None), // #206 [ref=5x] + V(660F38,00,0,0,0,0,1,None), // #207 [ref=1x] + V(XOP_M8,00,0,0,0,0,0,None), // #208 [ref=22x] + V(660F38,00,0,0,0,1,4,ByLL), // #209 [ref=4x] + E(660F38,00,0,0,0,0,0,None), // #210 [ref=2x] + E(660F38,00,0,0,0,1,1,None), // #211 [ref=2x] + E(660F38,00,0,0,1,1,4,ByLL), // #212 [ref=1x] + V(660F3A,00,0,0,1,1,3,None), // #213 [ref=2x] + V(660F3A,00,0,0,0,0,1,None), // #214 [ref=1x] + V(660F00,00,0,0,0,0,1,None), // #215 [ref=1x] + E(F30F38,00,0,0,0,0,2,ByLL), // #216 [ref=6x] + E(F30F38,00,0,0,0,0,3,ByLL), // #217 [ref=9x] + E(F30F38,00,0,0,0,0,1,ByLL), // #218 [ref=3x] + V(660F38,00,0,0,0,0,2,ByLL), // #219 [ref=4x] + V(660F38,00,0,0,0,0,1,ByLL), // #220 [ref=2x] + E(660F00,00,1,0,0,0,4,ByLL), // #221 [ref=1x] + E(660F00,00,1,0,0,1,4,ByLL), // #222 [ref=1x] + V(F20F00,00,0,0,0,0,4,ByLL), // #223 [ref=1x] + V(660F00,00,0,0,0,0,4,None), // #224 [ref=6x] + V(660F00,00,7,0,0,0,4,ByLL), // #225 [ref=1x] + V(660F00,00,0,0,0,1,4,None), // #226 [ref=2x] + E(660F00,00,0,0,0,1,4,None), // #227 [ref=1x] + V(660F00,00,3,0,0,0,4,ByLL), // #228 [ref=1x] + E(F30F38,00,0,0,0,1,4,ByLL), // #229 [ref=2x] + E(660F38,00,5,2,0,1,3,None), // #230 [ref=2x] + E(660F38,00,5,2,0,0,2,None), // #231 [ref=2x] + E(660F38,00,6,2,0,1,3,None), // #232 [ref=2x] + E(660F38,00,6,2,0,0,2,None), // #233 [ref=2x] + V(000F00,00,3,0,0,0,0,None), // #234 [ref=1x] + O(F30F00,00,2,0,0,0,0,0 ), // #235 [ref=1x] + O(F30F00,00,3,0,0,0,0,0 ), // #236 [ref=1x] + O(000F38,00,0,0,1,0,0,0 ), // #237 [ref=1x] + O(660F38,00,0,0,1,0,0,0 ), // #238 [ref=1x] + O(000F00,00,5,0,1,0,0,0 ), // #239 [ref=2x] + O(000F00,00,3,0,1,0,0,0 ), // #240 [ref=1x] + O(000F00,00,4,0,1,0,0,0 ), // #241 [ref=2x] + O(000F00,00,6,0,1,0,0,0 ) // #242 [ref=1x] }; // ---------------------------------------------------------------------------- // ${MainOpcodeTable:End} @@ -1905,140 +1996,141 @@ const uint32_t InstDB::_mainOpcodeTable[] = { // ${AltOpcodeTable:Begin} // ------------------- Automatically generated, do not edit ------------------- const uint32_t InstDB::_altOpcodeTable[] = { - 0 , // #0 [ref=1410x] - O(660F00,1B,_,_,_,_,_,_ ), // #1 [ref=1x] - O(000F00,BA,4,_,x,_,_,_ ), // #2 [ref=1x] - O(000F00,BA,7,_,x,_,_,_ ), // #3 [ref=1x] - O(000F00,BA,6,_,x,_,_,_ ), // #4 [ref=1x] - O(000F00,BA,5,_,x,_,_,_ ), // #5 [ref=1x] - O(000000,48,_,_,x,_,_,_ ), // #6 [ref=1x] - O(660F00,78,0,_,_,_,_,_ ), // #7 [ref=1x] - O_FPU(00,00DF,5) , // #8 [ref=1x] - O_FPU(00,00DF,7) , // #9 [ref=1x] - O_FPU(00,00DD,1) , // #10 [ref=1x] - O_FPU(00,00DB,5) , // #11 [ref=1x] - O_FPU(00,DFE0,_) , // #12 [ref=1x] - O(000000,DB,7,_,_,_,_,_ ), // #13 [ref=1x] - O_FPU(9B,DFE0,_) , // #14 [ref=1x] - O(000000,E4,_,_,_,_,_,_ ), // #15 [ref=1x] - O(000000,40,_,_,x,_,_,_ ), // #16 [ref=1x] - O(F20F00,78,_,_,_,_,_,_ ), // #17 [ref=1x] - O(000000,77,_,_,_,_,_,_ ), // #18 [ref=2x] - O(000000,73,_,_,_,_,_,_ ), // #19 [ref=3x] - O(000000,72,_,_,_,_,_,_ ), // #20 [ref=3x] - O(000000,76,_,_,_,_,_,_ ), // #21 [ref=2x] - O(000000,74,_,_,_,_,_,_ ), // #22 [ref=2x] - O(000000,E3,_,_,_,_,_,_ ), // #23 [ref=1x] - O(000000,7F,_,_,_,_,_,_ ), // #24 [ref=2x] - O(000000,7D,_,_,_,_,_,_ ), // #25 [ref=2x] - O(000000,7C,_,_,_,_,_,_ ), // #26 [ref=2x] - O(000000,7E,_,_,_,_,_,_ ), // #27 [ref=2x] - O(000000,EB,_,_,_,_,_,_ ), // #28 [ref=1x] - O(000000,75,_,_,_,_,_,_ ), // #29 [ref=2x] - O(000000,71,_,_,_,_,_,_ ), // #30 [ref=1x] - O(000000,7B,_,_,_,_,_,_ ), // #31 [ref=2x] - O(000000,79,_,_,_,_,_,_ ), // #32 [ref=1x] - O(000000,70,_,_,_,_,_,_ ), // #33 [ref=1x] - O(000000,7A,_,_,_,_,_,_ ), // #34 [ref=2x] - O(000000,78,_,_,_,_,_,_ ), // #35 [ref=1x] - V(660F00,92,_,0,0,_,_,_ ), // #36 [ref=1x] - V(F20F00,92,_,0,0,_,_,_ ), // #37 [ref=1x] - V(F20F00,92,_,0,1,_,_,_ ), // #38 [ref=1x] - V(000F00,92,_,0,0,_,_,_ ), // #39 [ref=1x] - O(000000,9A,_,_,_,_,_,_ ), // #40 [ref=1x] - O(000000,EA,_,_,_,_,_,_ ), // #41 [ref=1x] - O(000000,E2,_,_,_,_,_,_ ), // #42 [ref=1x] - O(000000,E1,_,_,_,_,_,_ ), // #43 [ref=1x] - O(000000,E0,_,_,_,_,_,_ ), // #44 [ref=1x] - O(660F00,29,_,_,_,_,_,_ ), // #45 [ref=1x] - O(000F00,29,_,_,_,_,_,_ ), // #46 [ref=1x] - O(000F38,F1,_,_,x,_,_,_ ), // #47 [ref=1x] - O(000F00,7E,_,_,_,_,_,_ ), // #48 [ref=1x] - O(660F00,7F,_,_,_,_,_,_ ), // #49 [ref=1x] - O(F30F00,7F,_,_,_,_,_,_ ), // #50 [ref=1x] - O(660F00,17,_,_,_,_,_,_ ), // #51 [ref=1x] - O(000F00,17,_,_,_,_,_,_ ), // #52 [ref=1x] - O(660F00,13,_,_,_,_,_,_ ), // #53 [ref=1x] - O(000F00,13,_,_,_,_,_,_ ), // #54 [ref=1x] - O(660F00,E7,_,_,_,_,_,_ ), // #55 [ref=1x] - O(660F00,2B,_,_,_,_,_,_ ), // #56 [ref=1x] - O(000F00,2B,_,_,_,_,_,_ ), // #57 [ref=1x] - O(000F00,E7,_,_,_,_,_,_ ), // #58 [ref=1x] - O(F20F00,2B,_,_,_,_,_,_ ), // #59 [ref=1x] - O(F30F00,2B,_,_,_,_,_,_ ), // #60 [ref=1x] - O(000F00,7E,_,_,x,_,_,_ ), // #61 [ref=1x] - O(F20F00,11,_,_,_,_,_,_ ), // #62 [ref=1x] - O(F30F00,11,_,_,_,_,_,_ ), // #63 [ref=1x] - O(660F00,11,_,_,_,_,_,_ ), // #64 [ref=1x] - O(000F00,11,_,_,_,_,_,_ ), // #65 [ref=1x] - O(000000,E6,_,_,_,_,_,_ ), // #66 [ref=1x] - O(000F3A,15,_,_,_,_,_,_ ), // #67 [ref=1x] - O(000000,58,_,_,_,_,_,_ ), // #68 [ref=1x] - O(000F00,72,6,_,_,_,_,_ ), // #69 [ref=1x] - O(660F00,73,7,_,_,_,_,_ ), // #70 [ref=1x] - O(000F00,73,6,_,_,_,_,_ ), // #71 [ref=1x] - O(000F00,71,6,_,_,_,_,_ ), // #72 [ref=1x] - O(000F00,72,4,_,_,_,_,_ ), // #73 [ref=1x] - O(000F00,71,4,_,_,_,_,_ ), // #74 [ref=1x] - O(000F00,72,2,_,_,_,_,_ ), // #75 [ref=1x] - O(660F00,73,3,_,_,_,_,_ ), // #76 [ref=1x] - O(000F00,73,2,_,_,_,_,_ ), // #77 [ref=1x] - O(000F00,71,2,_,_,_,_,_ ), // #78 [ref=1x] - O(000000,50,_,_,_,_,_,_ ), // #79 [ref=1x] - O(000000,F6,_,_,x,_,_,_ ), // #80 [ref=1x] - E(660F38,92,_,x,_,1,3,T1S), // #81 [ref=1x] - E(660F38,92,_,x,_,0,2,T1S), // #82 [ref=1x] - E(660F38,93,_,x,_,1,3,T1S), // #83 [ref=1x] - E(660F38,93,_,x,_,0,2,T1S), // #84 [ref=1x] - V(660F38,2F,_,x,0,_,_,_ ), // #85 [ref=1x] - V(660F38,2E,_,x,0,_,_,_ ), // #86 [ref=1x] - V(660F00,29,_,x,I,1,4,FVM), // #87 [ref=1x] - V(000F00,29,_,x,I,0,4,FVM), // #88 [ref=1x] - V(660F00,7E,_,0,0,0,2,T1S), // #89 [ref=1x] - V(660F00,7F,_,x,I,_,_,_ ), // #90 [ref=1x] - E(660F00,7F,_,x,_,0,4,FVM), // #91 [ref=1x] - E(660F00,7F,_,x,_,1,4,FVM), // #92 [ref=1x] - V(F30F00,7F,_,x,I,_,_,_ ), // #93 [ref=1x] - E(F20F00,7F,_,x,_,1,4,FVM), // #94 [ref=1x] - E(F30F00,7F,_,x,_,0,4,FVM), // #95 [ref=1x] - E(F30F00,7F,_,x,_,1,4,FVM), // #96 [ref=1x] - E(F20F00,7F,_,x,_,0,4,FVM), // #97 [ref=1x] - V(660F00,17,_,0,I,1,3,T1S), // #98 [ref=1x] - V(000F00,17,_,0,I,0,3,T2 ), // #99 [ref=1x] - V(660F00,13,_,0,I,1,3,T1S), // #100 [ref=1x] - V(000F00,13,_,0,I,0,3,T2 ), // #101 [ref=1x] - V(660F00,7E,_,0,I,1,3,T1S), // #102 [ref=1x] - V(F20F00,11,_,I,I,1,3,T1S), // #103 [ref=1x] - V(F30F00,11,_,I,I,0,2,T1S), // #104 [ref=1x] - V(660F00,11,_,x,I,1,4,FVM), // #105 [ref=1x] - V(000F00,11,_,x,I,0,4,FVM), // #106 [ref=1x] - E(660F38,7A,_,x,0,0,0,T1S), // #107 [ref=1x] - E(660F38,7C,_,x,0,0,0,T1S), // #108 [ref=1x] - E(660F38,7C,_,x,0,1,0,T1S), // #109 [ref=1x] - E(660F38,7B,_,x,0,0,0,T1S), // #110 [ref=1x] - V(660F3A,05,_,x,0,1,4,FV ), // #111 [ref=1x] - V(660F3A,04,_,x,0,0,4,FV ), // #112 [ref=1x] - V(660F3A,01,_,x,1,1,4,FV ), // #113 [ref=1x] - V(660F3A,00,_,x,1,1,4,FV ), // #114 [ref=1x] - E(660F38,90,_,x,_,0,2,T1S), // #115 [ref=1x] - E(660F38,90,_,x,_,1,3,T1S), // #116 [ref=1x] - E(660F38,91,_,x,_,0,2,T1S), // #117 [ref=1x] - E(660F38,91,_,x,_,1,3,T1S), // #118 [ref=1x] - V(660F38,8E,_,x,0,_,_,_ ), // #119 [ref=1x] - V(660F38,8E,_,x,1,_,_,_ ), // #120 [ref=1x] - V(XOP_M8,C0,_,0,x,_,_,_ ), // #121 [ref=1x] - V(XOP_M8,C2,_,0,x,_,_,_ ), // #122 [ref=1x] - V(XOP_M8,C3,_,0,x,_,_,_ ), // #123 [ref=1x] - V(XOP_M8,C1,_,0,x,_,_,_ ), // #124 [ref=1x] - V(660F00,72,6,x,I,0,4,FV ), // #125 [ref=1x] - V(660F00,73,6,x,I,1,4,FV ), // #126 [ref=1x] - V(660F00,71,6,x,I,I,4,FVM), // #127 [ref=1x] - V(660F00,72,4,x,I,0,4,FV ), // #128 [ref=1x] - E(660F00,72,4,x,_,1,4,FV ), // #129 [ref=1x] - V(660F00,71,4,x,I,I,4,FVM), // #130 [ref=1x] - V(660F00,72,2,x,I,0,4,FV ), // #131 [ref=1x] - V(660F00,73,2,x,I,1,4,FV ), // #132 [ref=1x] - V(660F00,71,2,x,I,I,4,FVM) // #133 [ref=1x] + O(000000,00,0,0,0,0,0,0 ), // #0 [ref=1514x] + O(660F00,1B,0,0,0,0,0,0 ), // #1 [ref=1x] + O(000F00,BA,4,0,0,0,0,0 ), // #2 [ref=1x] + O(000F00,BA,7,0,0,0,0,0 ), // #3 [ref=1x] + O(000F00,BA,6,0,0,0,0,0 ), // #4 [ref=1x] + O(000F00,BA,5,0,0,0,0,0 ), // #5 [ref=1x] + O(000000,48,0,0,0,0,0,0 ), // #6 [ref=1x] + O(660F00,78,0,0,0,0,0,0 ), // #7 [ref=1x] + O_FPU(00,00DF,5) , // #8 [ref=1x] + O_FPU(00,00DF,7) , // #9 [ref=1x] + O_FPU(00,00DD,1) , // #10 [ref=1x] + O_FPU(00,00DB,5) , // #11 [ref=1x] + O_FPU(00,DFE0,0) , // #12 [ref=1x] + O(000000,DB,7,0,0,0,0,0 ), // #13 [ref=1x] + O_FPU(9B,DFE0,0) , // #14 [ref=1x] + O(000000,E4,0,0,0,0,0,0 ), // #15 [ref=1x] + O(000000,40,0,0,0,0,0,0 ), // #16 [ref=1x] + O(F20F00,78,0,0,0,0,0,0 ), // #17 [ref=1x] + O(000000,77,0,0,0,0,0,0 ), // #18 [ref=2x] + O(000000,73,0,0,0,0,0,0 ), // #19 [ref=3x] + O(000000,72,0,0,0,0,0,0 ), // #20 [ref=3x] + O(000000,76,0,0,0,0,0,0 ), // #21 [ref=2x] + O(000000,74,0,0,0,0,0,0 ), // #22 [ref=2x] + O(000000,E3,0,0,0,0,0,0 ), // #23 [ref=1x] + O(000000,7F,0,0,0,0,0,0 ), // #24 [ref=2x] + O(000000,7D,0,0,0,0,0,0 ), // #25 [ref=2x] + O(000000,7C,0,0,0,0,0,0 ), // #26 [ref=2x] + O(000000,7E,0,0,0,0,0,0 ), // #27 [ref=2x] + O(000000,EB,0,0,0,0,0,0 ), // #28 [ref=1x] + O(000000,75,0,0,0,0,0,0 ), // #29 [ref=2x] + O(000000,71,0,0,0,0,0,0 ), // #30 [ref=1x] + O(000000,7B,0,0,0,0,0,0 ), // #31 [ref=2x] + O(000000,79,0,0,0,0,0,0 ), // #32 [ref=1x] + O(000000,70,0,0,0,0,0,0 ), // #33 [ref=1x] + O(000000,7A,0,0,0,0,0,0 ), // #34 [ref=2x] + O(000000,78,0,0,0,0,0,0 ), // #35 [ref=1x] + V(660F00,92,0,0,0,0,0,None), // #36 [ref=1x] + V(F20F00,92,0,0,0,0,0,None), // #37 [ref=1x] + V(F20F00,92,0,0,1,0,0,None), // #38 [ref=1x] + V(000F00,92,0,0,0,0,0,None), // #39 [ref=1x] + O(000000,9A,0,0,0,0,0,0 ), // #40 [ref=1x] + O(000000,EA,0,0,0,0,0,0 ), // #41 [ref=1x] + O(000000,E2,0,0,0,0,0,0 ), // #42 [ref=1x] + O(000000,E1,0,0,0,0,0,0 ), // #43 [ref=1x] + O(000000,E0,0,0,0,0,0,0 ), // #44 [ref=1x] + O(660F00,29,0,0,0,0,0,0 ), // #45 [ref=1x] + O(000F00,29,0,0,0,0,0,0 ), // #46 [ref=1x] + O(000F38,F1,0,0,0,0,0,0 ), // #47 [ref=1x] + O(000F00,7E,0,0,0,0,0,0 ), // #48 [ref=2x] + O(660F00,7F,0,0,0,0,0,0 ), // #49 [ref=1x] + O(F30F00,7F,0,0,0,0,0,0 ), // #50 [ref=1x] + O(660F00,17,0,0,0,0,0,0 ), // #51 [ref=1x] + O(000F00,17,0,0,0,0,0,0 ), // #52 [ref=1x] + O(660F00,13,0,0,0,0,0,0 ), // #53 [ref=1x] + O(000F00,13,0,0,0,0,0,0 ), // #54 [ref=1x] + O(660F00,E7,0,0,0,0,0,0 ), // #55 [ref=1x] + O(660F00,2B,0,0,0,0,0,0 ), // #56 [ref=1x] + O(000F00,2B,0,0,0,0,0,0 ), // #57 [ref=1x] + O(000F00,E7,0,0,0,0,0,0 ), // #58 [ref=1x] + O(F20F00,2B,0,0,0,0,0,0 ), // #59 [ref=1x] + O(F30F00,2B,0,0,0,0,0,0 ), // #60 [ref=1x] + O(F20F00,11,0,0,0,0,0,0 ), // #61 [ref=1x] + O(F30F00,11,0,0,0,0,0,0 ), // #62 [ref=1x] + O(660F00,11,0,0,0,0,0,0 ), // #63 [ref=1x] + O(000F00,11,0,0,0,0,0,0 ), // #64 [ref=1x] + O(000000,E6,0,0,0,0,0,0 ), // #65 [ref=1x] + O(000F3A,15,0,0,0,0,0,0 ), // #66 [ref=1x] + O(000000,58,0,0,0,0,0,0 ), // #67 [ref=1x] + O(000F00,72,6,0,0,0,0,0 ), // #68 [ref=1x] + O(660F00,73,7,0,0,0,0,0 ), // #69 [ref=1x] + O(000F00,73,6,0,0,0,0,0 ), // #70 [ref=1x] + O(000F00,71,6,0,0,0,0,0 ), // #71 [ref=1x] + O(000F00,72,4,0,0,0,0,0 ), // #72 [ref=1x] + O(000F00,71,4,0,0,0,0,0 ), // #73 [ref=1x] + O(000F00,72,2,0,0,0,0,0 ), // #74 [ref=1x] + O(660F00,73,3,0,0,0,0,0 ), // #75 [ref=1x] + O(000F00,73,2,0,0,0,0,0 ), // #76 [ref=1x] + O(000F00,71,2,0,0,0,0,0 ), // #77 [ref=1x] + O(000000,50,0,0,0,0,0,0 ), // #78 [ref=1x] + O(000000,F6,0,0,0,0,0,0 ), // #79 [ref=1x] + E(660F38,92,0,0,0,1,3,None), // #80 [ref=1x] + E(660F38,92,0,0,0,0,2,None), // #81 [ref=1x] + E(660F38,93,0,0,0,1,3,None), // #82 [ref=1x] + E(660F38,93,0,0,0,0,2,None), // #83 [ref=1x] + V(660F38,2F,0,0,0,0,0,None), // #84 [ref=1x] + V(660F38,2E,0,0,0,0,0,None), // #85 [ref=1x] + V(660F00,29,0,0,0,1,4,ByLL), // #86 [ref=1x] + V(000F00,29,0,0,0,0,4,ByLL), // #87 [ref=1x] + V(660F00,7E,0,0,0,0,2,None), // #88 [ref=1x] + V(660F00,7F,0,0,0,0,0,None), // #89 [ref=1x] + E(660F00,7F,0,0,0,0,4,ByLL), // #90 [ref=1x] + E(660F00,7F,0,0,0,1,4,ByLL), // #91 [ref=1x] + V(F30F00,7F,0,0,0,0,0,None), // #92 [ref=1x] + E(F20F00,7F,0,0,0,1,4,ByLL), // #93 [ref=1x] + E(F30F00,7F,0,0,0,0,4,ByLL), // #94 [ref=1x] + E(F30F00,7F,0,0,0,1,4,ByLL), // #95 [ref=1x] + E(F20F00,7F,0,0,0,0,4,ByLL), // #96 [ref=1x] + V(660F00,17,0,0,0,1,3,None), // #97 [ref=1x] + V(000F00,17,0,0,0,0,3,None), // #98 [ref=1x] + V(660F00,13,0,0,0,1,3,None), // #99 [ref=1x] + V(000F00,13,0,0,0,0,3,None), // #100 [ref=1x] + V(660F00,7E,0,0,0,1,3,None), // #101 [ref=1x] + V(F20F00,11,0,0,0,1,3,None), // #102 [ref=1x] + E(F3MAP5,11,0,0,0,0,1,None), // #103 [ref=1x] + V(F30F00,11,0,0,0,0,2,None), // #104 [ref=1x] + V(660F00,11,0,0,0,1,4,ByLL), // #105 [ref=1x] + V(000F00,11,0,0,0,0,4,ByLL), // #106 [ref=1x] + E(66MAP5,7E,0,0,0,0,1,None), // #107 [ref=1x] + E(660F38,7A,0,0,0,0,0,None), // #108 [ref=1x] + E(660F38,7C,0,0,0,0,0,None), // #109 [ref=1x] + E(660F38,7C,0,0,0,1,0,None), // #110 [ref=1x] + E(660F38,7B,0,0,0,0,0,None), // #111 [ref=1x] + V(660F3A,05,0,0,0,1,4,ByLL), // #112 [ref=1x] + V(660F3A,04,0,0,0,0,4,ByLL), // #113 [ref=1x] + V(660F3A,01,0,0,1,1,4,ByLL), // #114 [ref=1x] + V(660F3A,00,0,0,1,1,4,ByLL), // #115 [ref=1x] + E(660F38,90,0,0,0,0,2,None), // #116 [ref=1x] + E(660F38,90,0,0,0,1,3,None), // #117 [ref=1x] + E(660F38,91,0,0,0,0,2,None), // #118 [ref=1x] + E(660F38,91,0,0,0,1,3,None), // #119 [ref=1x] + V(660F38,8E,0,0,0,0,0,None), // #120 [ref=1x] + V(660F38,8E,0,0,1,0,0,None), // #121 [ref=1x] + V(XOP_M8,C0,0,0,0,0,0,None), // #122 [ref=1x] + V(XOP_M8,C2,0,0,0,0,0,None), // #123 [ref=1x] + V(XOP_M8,C3,0,0,0,0,0,None), // #124 [ref=1x] + V(XOP_M8,C1,0,0,0,0,0,None), // #125 [ref=1x] + V(660F00,72,6,0,0,0,4,ByLL), // #126 [ref=1x] + V(660F00,73,6,0,0,1,4,ByLL), // #127 [ref=1x] + V(660F00,71,6,0,0,0,4,ByLL), // #128 [ref=1x] + V(660F00,72,4,0,0,0,4,ByLL), // #129 [ref=1x] + E(660F00,72,4,0,0,1,4,ByLL), // #130 [ref=1x] + V(660F00,71,4,0,0,0,4,ByLL), // #131 [ref=1x] + V(660F00,72,2,0,0,0,4,ByLL), // #132 [ref=1x] + V(660F00,73,2,0,0,1,4,ByLL), // #133 [ref=1x] + V(660F00,71,2,0,0,0,4,ByLL) // #134 [ref=1x] }; // ---------------------------------------------------------------------------- // ${AltOpcodeTable:End} @@ -2048,450 +2140,475 @@ const uint32_t InstDB::_altOpcodeTable[] = { #undef E #undef O_FPU -// ============================================================================ -// [asmjit::x86::InstDB - CommonInfoTableA] -// ============================================================================ +// x86::InstDB - CommonInfoTable +// ============================= // ${InstCommonTable:Begin} // ------------------- Automatically generated, do not edit ------------------- -#define F(VAL) InstDB::kFlag##VAL -#define X(VAL) InstDB::kAvx512Flag##VAL -#define CONTROL(VAL) Inst::kControl##VAL -#define SINGLE_REG(VAL) InstDB::kSingleReg##VAL +#define F(VAL) uint32_t(InstDB::InstFlags::k##VAL) +#define X(VAL) uint32_t(InstDB::Avx512Flags::k##VAL) +#define CONTROL_FLOW(VAL) uint8_t(InstControlFlow::k##VAL) +#define SAME_REG_HINT(VAL) uint8_t(InstSameRegHint::k##VAL) const InstDB::CommonInfo InstDB::_commonInfoTable[] = { - { 0 , 0 , 0 , 0 , CONTROL(None) , SINGLE_REG(None)}, // #0 [ref=1x] - { 0 , 0 , 376, 1 , CONTROL(None) , SINGLE_REG(None)}, // #1 [ref=4x] - { 0 , 0 , 377, 1 , CONTROL(None) , SINGLE_REG(None)}, // #2 [ref=2x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL(None) , SINGLE_REG(None)}, // #3 [ref=2x] - { 0 , 0 , 180, 2 , CONTROL(None) , SINGLE_REG(None)}, // #4 [ref=2x] - { F(Vec) , 0 , 79 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #5 [ref=54x] - { F(Vec) , 0 , 106, 1 , CONTROL(None) , SINGLE_REG(None)}, // #6 [ref=19x] - { F(Vec) , 0 , 257, 1 , CONTROL(None) , SINGLE_REG(None)}, // #7 [ref=16x] - { F(Vec) , 0 , 215, 1 , CONTROL(None) , SINGLE_REG(None)}, // #8 [ref=20x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 28 , 11, CONTROL(None) , SINGLE_REG(RO) }, // #9 [ref=1x] - { F(Vex) , 0 , 272, 2 , CONTROL(None) , SINGLE_REG(None)}, // #10 [ref=3x] - { F(Vec) , 0 , 79 , 1 , CONTROL(None) , SINGLE_REG(RO) }, // #11 [ref=12x] - { 0 , 0 , 378, 1 , CONTROL(None) , SINGLE_REG(None)}, // #12 [ref=1x] - { F(Vex) , 0 , 274, 2 , CONTROL(None) , SINGLE_REG(None)}, // #13 [ref=5x] - { F(Vex) , 0 , 180, 2 , CONTROL(None) , SINGLE_REG(None)}, // #14 [ref=12x] - { F(Vec) , 0 , 379, 1 , CONTROL(None) , SINGLE_REG(None)}, // #15 [ref=4x] - { 0 , 0 , 276, 2 , CONTROL(None) , SINGLE_REG(None)}, // #16 [ref=3x] - { F(Mib) , 0 , 380, 1 , CONTROL(None) , SINGLE_REG(None)}, // #17 [ref=1x] - { 0 , 0 , 381, 1 , CONTROL(None) , SINGLE_REG(None)}, // #18 [ref=1x] - { 0 , 0 , 278, 2 , CONTROL(None) , SINGLE_REG(None)}, // #19 [ref=1x] - { F(Mib) , 0 , 382, 1 , CONTROL(None) , SINGLE_REG(None)}, // #20 [ref=1x] - { 0 , 0 , 280, 2 , CONTROL(None) , SINGLE_REG(None)}, // #21 [ref=1x] - { 0 , 0 , 179, 3 , CONTROL(None) , SINGLE_REG(None)}, // #22 [ref=35x] - { 0 , 0 , 383, 1 , CONTROL(None) , SINGLE_REG(None)}, // #23 [ref=3x] - { 0 , 0 , 123, 4 , CONTROL(None) , SINGLE_REG(None)}, // #24 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 123, 4 , CONTROL(None) , SINGLE_REG(None)}, // #25 [ref=3x] - { F(Rep)|F(RepIgnored) , 0 , 282, 2 , CONTROL(Call) , SINGLE_REG(None)}, // #26 [ref=1x] - { 0 , 0 , 384, 1 , CONTROL(None) , SINGLE_REG(None)}, // #27 [ref=1x] - { 0 , 0 , 385, 1 , CONTROL(None) , SINGLE_REG(None)}, // #28 [ref=2x] - { 0 , 0 , 359, 1 , CONTROL(None) , SINGLE_REG(None)}, // #29 [ref=1x] - { 0 , 0 , 108, 1 , CONTROL(None) , SINGLE_REG(None)}, // #30 [ref=83x] - { 0 , 0 , 386, 1 , CONTROL(None) , SINGLE_REG(None)}, // #31 [ref=11x] - { 0 , 0 , 387, 1 , CONTROL(None) , SINGLE_REG(None)}, // #32 [ref=6x] - { 0 , 0 , 388, 1 , CONTROL(None) , SINGLE_REG(None)}, // #33 [ref=13x] - { 0 , 0 , 389, 1 , CONTROL(None) , SINGLE_REG(None)}, // #34 [ref=1x] - { 0 , 0 , 16 , 12, CONTROL(None) , SINGLE_REG(None)}, // #35 [ref=1x] - { F(Rep) , 0 , 127, 4 , CONTROL(None) , SINGLE_REG(None)}, // #36 [ref=1x] - { F(Vec) , 0 , 390, 1 , CONTROL(None) , SINGLE_REG(None)}, // #37 [ref=2x] - { F(Vec) , 0 , 391, 1 , CONTROL(None) , SINGLE_REG(None)}, // #38 [ref=3x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 131, 4 , CONTROL(None) , SINGLE_REG(None)}, // #39 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 392, 1 , CONTROL(None) , SINGLE_REG(None)}, // #40 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 393, 1 , CONTROL(None) , SINGLE_REG(None)}, // #41 [ref=1x] - { 0 , 0 , 394, 1 , CONTROL(None) , SINGLE_REG(None)}, // #42 [ref=1x] - { 0 , 0 , 395, 1 , CONTROL(None) , SINGLE_REG(None)}, // #43 [ref=1x] - { 0 , 0 , 284, 2 , CONTROL(None) , SINGLE_REG(None)}, // #44 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 396, 1 , CONTROL(None) , SINGLE_REG(None)}, // #45 [ref=2x] - { F(Mmx)|F(Vec) , 0 , 397, 1 , CONTROL(None) , SINGLE_REG(None)}, // #46 [ref=2x] - { F(Mmx)|F(Vec) , 0 , 398, 1 , CONTROL(None) , SINGLE_REG(None)}, // #47 [ref=2x] - { F(Vec) , 0 , 399, 1 , CONTROL(None) , SINGLE_REG(None)}, // #48 [ref=2x] - { F(Vec) , 0 , 400, 1 , CONTROL(None) , SINGLE_REG(None)}, // #49 [ref=2x] - { F(Vec) , 0 , 401, 1 , CONTROL(None) , SINGLE_REG(None)}, // #50 [ref=2x] - { 0 , 0 , 402, 1 , CONTROL(None) , SINGLE_REG(None)}, // #51 [ref=1x] - { 0 , 0 , 403, 1 , CONTROL(None) , SINGLE_REG(None)}, // #52 [ref=2x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 286, 2 , CONTROL(None) , SINGLE_REG(None)}, // #53 [ref=2x] - { 0 , 0 , 39 , 4 , CONTROL(None) , SINGLE_REG(None)}, // #54 [ref=3x] - { F(Mmx) , 0 , 108, 1 , CONTROL(None) , SINGLE_REG(None)}, // #55 [ref=1x] - { 0 , 0 , 288, 2 , CONTROL(None) , SINGLE_REG(None)}, // #56 [ref=2x] - { 0 , 0 , 404, 1 , CONTROL(None) , SINGLE_REG(None)}, // #57 [ref=1x] - { F(Vec) , 0 , 405, 1 , CONTROL(None) , SINGLE_REG(None)}, // #58 [ref=2x] - { F(Vec) , 0 , 290, 2 , CONTROL(None) , SINGLE_REG(None)}, // #59 [ref=1x] - { F(FpuM32)|F(FpuM64) , 0 , 182, 3 , CONTROL(None) , SINGLE_REG(None)}, // #60 [ref=6x] - { 0 , 0 , 292, 2 , CONTROL(None) , SINGLE_REG(None)}, // #61 [ref=9x] - { F(FpuM80) , 0 , 406, 1 , CONTROL(None) , SINGLE_REG(None)}, // #62 [ref=2x] - { 0 , 0 , 293, 1 , CONTROL(None) , SINGLE_REG(None)}, // #63 [ref=13x] - { F(FpuM32)|F(FpuM64) , 0 , 294, 2 , CONTROL(None) , SINGLE_REG(None)}, // #64 [ref=2x] - { F(FpuM16)|F(FpuM32) , 0 , 407, 1 , CONTROL(None) , SINGLE_REG(None)}, // #65 [ref=9x] - { F(FpuM16)|F(FpuM32)|F(FpuM64) , 0 , 408, 1 , CONTROL(None) , SINGLE_REG(None)}, // #66 [ref=3x] - { F(FpuM32)|F(FpuM64)|F(FpuM80) , 0 , 409, 1 , CONTROL(None) , SINGLE_REG(None)}, // #67 [ref=2x] - { F(FpuM16) , 0 , 410, 1 , CONTROL(None) , SINGLE_REG(None)}, // #68 [ref=3x] - { 0 , 0 , 411, 1 , CONTROL(None) , SINGLE_REG(None)}, // #69 [ref=13x] - { F(FpuM16) , 0 , 412, 1 , CONTROL(None) , SINGLE_REG(None)}, // #70 [ref=2x] - { F(FpuM32)|F(FpuM64) , 0 , 295, 1 , CONTROL(None) , SINGLE_REG(None)}, // #71 [ref=1x] - { 0 , 0 , 413, 1 , CONTROL(None) , SINGLE_REG(None)}, // #72 [ref=2x] - { 0 , 0 , 414, 1 , CONTROL(None) , SINGLE_REG(None)}, // #73 [ref=1x] - { 0 , 0 , 39 , 10, CONTROL(None) , SINGLE_REG(None)}, // #74 [ref=1x] - { 0 , 0 , 415, 1 , CONTROL(None) , SINGLE_REG(None)}, // #75 [ref=1x] - { 0 , 0 , 416, 1 , CONTROL(None) , SINGLE_REG(None)}, // #76 [ref=2x] - { 0 , 0 , 343, 1 , CONTROL(None) , SINGLE_REG(None)}, // #77 [ref=3x] - { F(Rep) , 0 , 417, 1 , CONTROL(None) , SINGLE_REG(None)}, // #78 [ref=1x] - { F(Vec) , 0 , 296, 2 , CONTROL(None) , SINGLE_REG(None)}, // #79 [ref=1x] - { 0 , 0 , 418, 1 , CONTROL(None) , SINGLE_REG(None)}, // #80 [ref=2x] - { 0 , 0 , 419, 1 , CONTROL(None) , SINGLE_REG(None)}, // #81 [ref=8x] - { 0 , 0 , 298, 2 , CONTROL(None) , SINGLE_REG(None)}, // #82 [ref=3x] - { 0 , 0 , 300, 2 , CONTROL(None) , SINGLE_REG(None)}, // #83 [ref=1x] - { 0 , 0 , 108, 1 , CONTROL(Return) , SINGLE_REG(None)}, // #84 [ref=2x] - { 0 , 0 , 388, 1 , CONTROL(Return) , SINGLE_REG(None)}, // #85 [ref=1x] - { F(Rep)|F(RepIgnored) , 0 , 302, 2 , CONTROL(Branch) , SINGLE_REG(None)}, // #86 [ref=30x] - { F(Rep)|F(RepIgnored) , 0 , 304, 2 , CONTROL(Branch) , SINGLE_REG(None)}, // #87 [ref=1x] - { F(Rep)|F(RepIgnored) , 0 , 306, 2 , CONTROL(Jump) , SINGLE_REG(None)}, // #88 [ref=1x] - { F(Vex) , 0 , 420, 1 , CONTROL(None) , SINGLE_REG(None)}, // #89 [ref=19x] - { F(Vex) , 0 , 308, 2 , CONTROL(None) , SINGLE_REG(None)}, // #90 [ref=1x] - { F(Vex) , 0 , 310, 2 , CONTROL(None) , SINGLE_REG(None)}, // #91 [ref=1x] - { F(Vex) , 0 , 312, 2 , CONTROL(None) , SINGLE_REG(None)}, // #92 [ref=1x] - { F(Vex) , 0 , 314, 2 , CONTROL(None) , SINGLE_REG(None)}, // #93 [ref=1x] - { F(Vex) , 0 , 421, 1 , CONTROL(None) , SINGLE_REG(None)}, // #94 [ref=12x] - { F(Vex) , 0 , 422, 1 , CONTROL(None) , SINGLE_REG(None)}, // #95 [ref=8x] - { F(Vex) , 0 , 420, 1 , CONTROL(None) , SINGLE_REG(WO) }, // #96 [ref=8x] - { 0 , 0 , 423, 1 , CONTROL(None) , SINGLE_REG(None)}, // #97 [ref=2x] - { 0 , 0 , 316, 2 , CONTROL(None) , SINGLE_REG(None)}, // #98 [ref=1x] - { 0 , 0 , 318, 2 , CONTROL(Call) , SINGLE_REG(None)}, // #99 [ref=1x] - { F(Vec) , 0 , 224, 1 , CONTROL(None) , SINGLE_REG(None)}, // #100 [ref=2x] - { 0 , 0 , 424, 1 , CONTROL(None) , SINGLE_REG(None)}, // #101 [ref=2x] - { 0 , 0 , 320, 2 , CONTROL(None) , SINGLE_REG(None)}, // #102 [ref=2x] - { F(Vex) , 0 , 425, 1 , CONTROL(None) , SINGLE_REG(None)}, // #103 [ref=2x] - { 0 , 0 , 426, 1 , CONTROL(None) , SINGLE_REG(None)}, // #104 [ref=1x] - { 0 , 0 , 185, 3 , CONTROL(None) , SINGLE_REG(None)}, // #105 [ref=3x] - { 0 , 0 , 318, 2 , CONTROL(Jump) , SINGLE_REG(None)}, // #106 [ref=1x] - { 0 , 0 , 427, 1 , CONTROL(None) , SINGLE_REG(None)}, // #107 [ref=5x] - { F(Vex) , 0 , 428, 1 , CONTROL(None) , SINGLE_REG(None)}, // #108 [ref=2x] - { F(Rep) , 0 , 135, 4 , CONTROL(None) , SINGLE_REG(None)}, // #109 [ref=1x] - { 0 , 0 , 304, 2 , CONTROL(Branch) , SINGLE_REG(None)}, // #110 [ref=3x] - { 0 , 0 , 322, 2 , CONTROL(None) , SINGLE_REG(None)}, // #111 [ref=1x] - { F(Vex) , 0 , 429, 1 , CONTROL(None) , SINGLE_REG(None)}, // #112 [ref=2x] - { F(Vec) , 0 , 430, 1 , CONTROL(None) , SINGLE_REG(None)}, // #113 [ref=1x] - { F(Mmx) , 0 , 431, 1 , CONTROL(None) , SINGLE_REG(None)}, // #114 [ref=1x] - { 0 , 0 , 432, 1 , CONTROL(None) , SINGLE_REG(None)}, // #115 [ref=2x] - { F(XRelease) , 0 , 0 , 16, CONTROL(None) , SINGLE_REG(None)}, // #116 [ref=1x] - { 0 , 0 , 49 , 9 , CONTROL(None) , SINGLE_REG(None)}, // #117 [ref=1x] - { F(Vec) , 0 , 79 , 2 , CONTROL(None) , SINGLE_REG(None)}, // #118 [ref=6x] - { 0 , 0 , 73 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #119 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 324, 2 , CONTROL(None) , SINGLE_REG(None)}, // #120 [ref=1x] - { 0 , 0 , 433, 1 , CONTROL(None) , SINGLE_REG(None)}, // #121 [ref=1x] - { 0 , 0 , 77 , 2 , CONTROL(None) , SINGLE_REG(None)}, // #122 [ref=2x] - { F(Mmx)|F(Vec) , 0 , 434, 1 , CONTROL(None) , SINGLE_REG(None)}, // #123 [ref=1x] - { F(Vec) , 0 , 291, 1 , CONTROL(None) , SINGLE_REG(None)}, // #124 [ref=2x] - { F(Vec) , 0 , 230, 2 , CONTROL(None) , SINGLE_REG(None)}, // #125 [ref=4x] - { F(Vec) , 0 , 435, 1 , CONTROL(None) , SINGLE_REG(None)}, // #126 [ref=2x] - { F(Vec) , 0 , 80 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #127 [ref=3x] - { F(Mmx) , 0 , 436, 1 , CONTROL(None) , SINGLE_REG(None)}, // #128 [ref=1x] - { F(Vec) , 0 , 107, 1 , CONTROL(None) , SINGLE_REG(None)}, // #129 [ref=1x] - { F(Vec) , 0 , 233, 1 , CONTROL(None) , SINGLE_REG(None)}, // #130 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 103, 5 , CONTROL(None) , SINGLE_REG(None)}, // #131 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 437, 1 , CONTROL(None) , SINGLE_REG(None)}, // #132 [ref=1x] - { F(Rep) , 0 , 139, 4 , CONTROL(None) , SINGLE_REG(None)}, // #133 [ref=1x] - { F(Vec) , 0 , 106, 2 , CONTROL(None) , SINGLE_REG(None)}, // #134 [ref=1x] - { F(Vec) , 0 , 326, 2 , CONTROL(None) , SINGLE_REG(None)}, // #135 [ref=1x] - { 0 , 0 , 328, 2 , CONTROL(None) , SINGLE_REG(None)}, // #136 [ref=2x] - { 0 , 0 , 438, 1 , CONTROL(None) , SINGLE_REG(None)}, // #137 [ref=1x] - { F(Vex) , 0 , 330, 2 , CONTROL(None) , SINGLE_REG(None)}, // #138 [ref=1x] - { 0 , 0 , 439, 1 , CONTROL(None) , SINGLE_REG(None)}, // #139 [ref=1x] - { 0 , 0 , 440, 1 , CONTROL(None) , SINGLE_REG(None)}, // #140 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 287, 1 , CONTROL(None) , SINGLE_REG(None)}, // #141 [ref=2x] - { 0 , 0 , 108, 5 , CONTROL(None) , SINGLE_REG(None)}, // #142 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL(None) , SINGLE_REG(RO) }, // #143 [ref=1x] - { 0 , 0 , 441, 1 , CONTROL(None) , SINGLE_REG(None)}, // #144 [ref=1x] - { F(Rep) , 0 , 442, 1 , CONTROL(None) , SINGLE_REG(None)}, // #145 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 332, 2 , CONTROL(None) , SINGLE_REG(None)}, // #146 [ref=37x] - { F(Mmx)|F(Vec) , 0 , 334, 2 , CONTROL(None) , SINGLE_REG(None)}, // #147 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 332, 2 , CONTROL(None) , SINGLE_REG(RO) }, // #148 [ref=6x] - { F(Mmx)|F(Vec) , 0 , 332, 2 , CONTROL(None) , SINGLE_REG(WO) }, // #149 [ref=16x] - { F(Mmx) , 0 , 332, 1 , CONTROL(None) , SINGLE_REG(None)}, // #150 [ref=26x] - { F(Vec) , 0 , 79 , 1 , CONTROL(None) , SINGLE_REG(WO) }, // #151 [ref=4x] - { F(Vec) , 0 , 443, 1 , CONTROL(None) , SINGLE_REG(None)}, // #152 [ref=1x] - { F(Vec) , 0 , 444, 1 , CONTROL(None) , SINGLE_REG(None)}, // #153 [ref=1x] - { F(Vec) , 0 , 445, 1 , CONTROL(None) , SINGLE_REG(None)}, // #154 [ref=1x] - { F(Vec) , 0 , 446, 1 , CONTROL(None) , SINGLE_REG(None)}, // #155 [ref=1x] - { F(Vec) , 0 , 447, 1 , CONTROL(None) , SINGLE_REG(None)}, // #156 [ref=1x] - { F(Vec) , 0 , 448, 1 , CONTROL(None) , SINGLE_REG(None)}, // #157 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 336, 2 , CONTROL(None) , SINGLE_REG(None)}, // #158 [ref=1x] - { F(Vec) , 0 , 449, 1 , CONTROL(None) , SINGLE_REG(None)}, // #159 [ref=1x] - { F(Vec) , 0 , 450, 1 , CONTROL(None) , SINGLE_REG(None)}, // #160 [ref=1x] - { F(Vec) , 0 , 451, 1 , CONTROL(None) , SINGLE_REG(None)}, // #161 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 452, 1 , CONTROL(None) , SINGLE_REG(None)}, // #162 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 453, 1 , CONTROL(None) , SINGLE_REG(None)}, // #163 [ref=1x] - { F(Vec) , 0 , 260, 1 , CONTROL(None) , SINGLE_REG(None)}, // #164 [ref=2x] - { 0 , 0 , 143, 4 , CONTROL(None) , SINGLE_REG(None)}, // #165 [ref=1x] - { F(Mmx) , 0 , 334, 1 , CONTROL(None) , SINGLE_REG(None)}, // #166 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 338, 2 , CONTROL(None) , SINGLE_REG(None)}, // #167 [ref=8x] - { F(Vec) , 0 , 454, 1 , CONTROL(None) , SINGLE_REG(None)}, // #168 [ref=2x] - { 0 , 0 , 455, 1 , CONTROL(None) , SINGLE_REG(None)}, // #169 [ref=1x] - { F(Mmx)|F(Vec) , 0 , 340, 2 , CONTROL(None) , SINGLE_REG(None)}, // #170 [ref=3x] - { 0 , 0 , 147, 4 , CONTROL(None) , SINGLE_REG(None)}, // #171 [ref=1x] - { 0 , 0 , 456, 1 , CONTROL(None) , SINGLE_REG(None)}, // #172 [ref=8x] - { 0 , 0 , 457, 1 , CONTROL(None) , SINGLE_REG(None)}, // #173 [ref=4x] - { 0 , 0 , 458, 1 , CONTROL(None) , SINGLE_REG(None)}, // #174 [ref=8x] - { 0 , 0 , 342, 2 , CONTROL(None) , SINGLE_REG(None)}, // #175 [ref=1x] - { F(Rep)|F(RepIgnored) , 0 , 344, 2 , CONTROL(Return) , SINGLE_REG(None)}, // #176 [ref=1x] - { 0 , 0 , 344, 2 , CONTROL(Return) , SINGLE_REG(None)}, // #177 [ref=1x] - { F(Vex) , 0 , 346, 2 , CONTROL(None) , SINGLE_REG(None)}, // #178 [ref=1x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL(None) , SINGLE_REG(WO) }, // #179 [ref=3x] - { F(Rep) , 0 , 151, 4 , CONTROL(None) , SINGLE_REG(None)}, // #180 [ref=1x] - { 0 , 0 , 459, 1 , CONTROL(None) , SINGLE_REG(None)}, // #181 [ref=30x] - { 0 , 0 , 188, 3 , CONTROL(None) , SINGLE_REG(None)}, // #182 [ref=2x] - { 0 , 0 , 460, 1 , CONTROL(None) , SINGLE_REG(None)}, // #183 [ref=3x] - { F(Rep) , 0 , 155, 4 , CONTROL(None) , SINGLE_REG(None)}, // #184 [ref=1x] - { F(Vex) , 0 , 461, 1 , CONTROL(None) , SINGLE_REG(None)}, // #185 [ref=5x] - { 0 , 0 , 66 , 7 , CONTROL(None) , SINGLE_REG(None)}, // #186 [ref=1x] - { F(Tsib)|F(Vex) , 0 , 462, 1 , CONTROL(None) , SINGLE_REG(None)}, // #187 [ref=2x] - { F(Vex) , 0 , 388, 1 , CONTROL(None) , SINGLE_REG(None)}, // #188 [ref=1x] - { F(Tsib)|F(Vex) , 0 , 463, 1 , CONTROL(None) , SINGLE_REG(None)}, // #189 [ref=1x] - { F(Vex) , 0 , 464, 1 , CONTROL(None) , SINGLE_REG(None)}, // #190 [ref=1x] - { 0 , 0 , 465, 1 , CONTROL(None) , SINGLE_REG(None)}, // #191 [ref=2x] - { 0 , 0 , 180, 1 , CONTROL(None) , SINGLE_REG(None)}, // #192 [ref=2x] - { 0 , 0 , 466, 1 , CONTROL(None) , SINGLE_REG(None)}, // #193 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(T4X) , 467, 1 , CONTROL(None) , SINGLE_REG(None)}, // #194 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(T4X) , 468, 1 , CONTROL(None) , SINGLE_REG(None)}, // #195 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64)|X(ER)|X(SAE) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #196 [ref=22x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32)|X(ER)|X(SAE) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #197 [ref=22x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(ER)|X(SAE) , 469, 1 , CONTROL(None) , SINGLE_REG(None)}, // #198 [ref=18x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(ER)|X(SAE) , 470, 1 , CONTROL(None) , SINGLE_REG(None)}, // #199 [ref=17x] - { F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL(None) , SINGLE_REG(None)}, // #200 [ref=15x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #201 [ref=5x] - { F(Vec)|F(Vex) , 0 , 79 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #202 [ref=17x] - { F(Vec)|F(Vex) , 0 , 215, 1 , CONTROL(None) , SINGLE_REG(None)}, // #203 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #204 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #205 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #206 [ref=10x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #207 [ref=12x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 191, 3 , CONTROL(None) , SINGLE_REG(RO) }, // #208 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(RO) }, // #209 [ref=6x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #210 [ref=19x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #211 [ref=12x] - { F(Vec)|F(Vex) , 0 , 194, 2 , CONTROL(None) , SINGLE_REG(None)}, // #212 [ref=6x] - { F(Vec)|F(Vex) , 0 , 348, 2 , CONTROL(None) , SINGLE_REG(None)}, // #213 [ref=3x] - { F(Vec)|F(Vex)|F(EvexTransformable) , 0 , 471, 1 , CONTROL(None) , SINGLE_REG(None)}, // #214 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 472, 1 , CONTROL(None) , SINGLE_REG(None)}, // #215 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 473, 1 , CONTROL(None) , SINGLE_REG(None)}, // #216 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 474, 1 , CONTROL(None) , SINGLE_REG(None)}, // #217 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 475, 1 , CONTROL(None) , SINGLE_REG(None)}, // #218 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 472, 1 , CONTROL(None) , SINGLE_REG(None)}, // #219 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 476, 1 , CONTROL(None) , SINGLE_REG(None)}, // #220 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K)|X(Z)|X(B64)|X(SAE) , 197, 3 , CONTROL(None) , SINGLE_REG(None)}, // #221 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K)|X(Z)|X(B32)|X(SAE) , 197, 3 , CONTROL(None) , SINGLE_REG(None)}, // #222 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K)|X(Z)|X(SAE) , 477, 1 , CONTROL(None) , SINGLE_REG(None)}, // #223 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K)|X(Z)|X(SAE) , 478, 1 , CONTROL(None) , SINGLE_REG(None)}, // #224 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(SAE) , 106, 1 , CONTROL(None) , SINGLE_REG(None)}, // #225 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(SAE) , 257, 1 , CONTROL(None) , SINGLE_REG(None)}, // #226 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 200, 3 , CONTROL(None) , SINGLE_REG(None)}, // #227 [ref=6x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #228 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32)|X(ER)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #229 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 350, 2 , CONTROL(None) , SINGLE_REG(None)}, // #230 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64)|X(ER)|X(SAE) , 350, 2 , CONTROL(None) , SINGLE_REG(None)}, // #231 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(ER)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #232 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(ER)|X(SAE) , 350, 2 , CONTROL(None) , SINGLE_REG(None)}, // #233 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(SAE) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #234 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32)|X(ER)|X(SAE) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #235 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(SAE) , 209, 3 , CONTROL(None) , SINGLE_REG(None)}, // #236 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(ER)|X(SAE) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #237 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(ER)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #238 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(ER)|X(SAE) , 399, 1 , CONTROL(None) , SINGLE_REG(None)}, // #239 [ref=1x] - { F(Vec)|F(Evex) , X(ER)|X(SAE) , 399, 1 , CONTROL(None) , SINGLE_REG(None)}, // #240 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(ER)|X(SAE) , 479, 1 , CONTROL(None) , SINGLE_REG(None)}, // #241 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(SAE) , 470, 1 , CONTROL(None) , SINGLE_REG(None)}, // #242 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(ER)|X(SAE) , 401, 1 , CONTROL(None) , SINGLE_REG(None)}, // #243 [ref=1x] - { F(Vec)|F(Evex) , X(ER)|X(SAE) , 401, 1 , CONTROL(None) , SINGLE_REG(None)}, // #244 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64)|X(SAE) , 350, 2 , CONTROL(None) , SINGLE_REG(None)}, // #245 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #246 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(SAE) , 350, 2 , CONTROL(None) , SINGLE_REG(None)}, // #247 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #248 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(SAE) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #249 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #250 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(SAE) , 399, 1 , CONTROL(None) , SINGLE_REG(None)}, // #251 [ref=1x] - { F(Vec)|F(Evex) , X(SAE) , 399, 1 , CONTROL(None) , SINGLE_REG(None)}, // #252 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(SAE) , 401, 1 , CONTROL(None) , SINGLE_REG(None)}, // #253 [ref=1x] - { F(Vec)|F(Evex) , X(SAE) , 401, 1 , CONTROL(None) , SINGLE_REG(None)}, // #254 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #255 [ref=1x] - { F(Vec)|F(Evex) , X(ER)|X(SAE) , 479, 1 , CONTROL(None) , SINGLE_REG(None)}, // #256 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #257 [ref=3x] - { F(Vec)|F(Vex) , 0 , 194, 1 , CONTROL(None) , SINGLE_REG(None)}, // #258 [ref=9x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(SAE)|X(B64) , 83 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #259 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(SAE)|X(B32) , 83 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #260 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #261 [ref=9x] - { F(Vec)|F(Vex)|F(EvexTransformable) , 0 , 210, 1 , CONTROL(None) , SINGLE_REG(None)}, // #262 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 480, 1 , CONTROL(None) , SINGLE_REG(None)}, // #263 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 211, 1 , CONTROL(None) , SINGLE_REG(None)}, // #264 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 405, 1 , CONTROL(None) , SINGLE_REG(None)}, // #265 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(SAE) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #266 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(SAE) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #267 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(SAE) , 481, 1 , CONTROL(None) , SINGLE_REG(None)}, // #268 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(SAE) , 482, 1 , CONTROL(None) , SINGLE_REG(None)}, // #269 [ref=4x] - { F(Vec)|F(Vex) , 0 , 159, 4 , CONTROL(None) , SINGLE_REG(None)}, // #270 [ref=13x] - { F(Vec)|F(Vex) , 0 , 352, 2 , CONTROL(None) , SINGLE_REG(None)}, // #271 [ref=4x] - { F(Vec)|F(Vex) , 0 , 354, 2 , CONTROL(None) , SINGLE_REG(None)}, // #272 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(B64) , 483, 1 , CONTROL(None) , SINGLE_REG(None)}, // #273 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(B32) , 483, 1 , CONTROL(None) , SINGLE_REG(None)}, // #274 [ref=1x] - { F(Vec)|F(Evex) , X(K) , 484, 1 , CONTROL(None) , SINGLE_REG(None)}, // #275 [ref=1x] - { F(Vec)|F(Evex) , X(K) , 485, 1 , CONTROL(None) , SINGLE_REG(None)}, // #276 [ref=1x] - { F(Vec)|F(Vex) , 0 , 206, 2 , CONTROL(None) , SINGLE_REG(None)}, // #277 [ref=7x] - { F(Vec)|F(Vex) , 0 , 106, 1 , CONTROL(None) , SINGLE_REG(None)}, // #278 [ref=1x] - { F(Vec)|F(Vex) , 0 , 257, 1 , CONTROL(None) , SINGLE_REG(None)}, // #279 [ref=1x] - { F(Vec)|F(Vsib)|F(Vex)|F(Evex)|F(EvexTwoOp) , X(K) , 163, 4 , CONTROL(None) , SINGLE_REG(None)}, // #280 [ref=2x] - { F(Vec)|F(Vsib)|F(Vex)|F(Evex)|F(EvexTwoOp) , X(K) , 113, 5 , CONTROL(None) , SINGLE_REG(None)}, // #281 [ref=2x] - { F(Vsib)|F(Evex) , X(K) , 486, 1 , CONTROL(None) , SINGLE_REG(None)}, // #282 [ref=4x] - { F(Vsib)|F(Evex) , X(K) , 487, 1 , CONTROL(None) , SINGLE_REG(None)}, // #283 [ref=4x] - { F(Vsib)|F(Evex) , X(K) , 488, 1 , CONTROL(None) , SINGLE_REG(None)}, // #284 [ref=8x] - { F(Vec)|F(Vsib)|F(Vex)|F(Evex)|F(EvexTwoOp) , X(K) , 118, 5 , CONTROL(None) , SINGLE_REG(None)}, // #285 [ref=2x] - { F(Vec)|F(Vsib)|F(Vex)|F(Evex)|F(EvexTwoOp) , X(K) , 212, 3 , CONTROL(None) , SINGLE_REG(None)}, // #286 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(SAE) , 469, 1 , CONTROL(None) , SINGLE_REG(None)}, // #287 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(SAE) , 470, 1 , CONTROL(None) , SINGLE_REG(None)}, // #288 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(SAE) , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #289 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(SAE) , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #290 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #291 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #292 [ref=22x] - { F(Vec)|F(Vex)|F(EvexTransformable) , 0 , 356, 1 , CONTROL(None) , SINGLE_REG(None)}, // #293 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 356, 2 , CONTROL(None) , SINGLE_REG(None)}, // #294 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 489, 1 , CONTROL(None) , SINGLE_REG(None)}, // #295 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 482, 1 , CONTROL(None) , SINGLE_REG(None)}, // #296 [ref=1x] - { F(Vec)|F(Vex) , 0 , 224, 2 , CONTROL(None) , SINGLE_REG(None)}, // #297 [ref=1x] - { F(Vex) , 0 , 424, 1 , CONTROL(None) , SINGLE_REG(None)}, // #298 [ref=2x] - { F(Vec)|F(Vex) , 0 , 430, 1 , CONTROL(None) , SINGLE_REG(None)}, // #299 [ref=1x] - { F(Vec)|F(Vex) , 0 , 167, 4 , CONTROL(None) , SINGLE_REG(None)}, // #300 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64)|X(SAE) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #301 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32)|X(SAE) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #302 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(SAE) , 469, 1 , CONTROL(None) , SINGLE_REG(None)}, // #303 [ref=2x] - { 0 , 0 , 358, 2 , CONTROL(None) , SINGLE_REG(None)}, // #304 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 79 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #305 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 360, 2 , CONTROL(None) , SINGLE_REG(None)}, // #306 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 218, 3 , CONTROL(None) , SINGLE_REG(None)}, // #307 [ref=1x] - { F(Vec)|F(Vex)|F(EvexTransformable) , 0 , 79 , 4 , CONTROL(None) , SINGLE_REG(None)}, // #308 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 79 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #309 [ref=6x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 232, 1 , CONTROL(None) , SINGLE_REG(None)}, // #310 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 362, 2 , CONTROL(None) , SINGLE_REG(None)}, // #311 [ref=4x] - { F(Vec)|F(Vex) , 0 , 490, 1 , CONTROL(None) , SINGLE_REG(None)}, // #312 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 221, 3 , CONTROL(None) , SINGLE_REG(None)}, // #313 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 224, 3 , CONTROL(None) , SINGLE_REG(None)}, // #314 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 227, 3 , CONTROL(None) , SINGLE_REG(None)}, // #315 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 230, 3 , CONTROL(None) , SINGLE_REG(None)}, // #316 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #317 [ref=5x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 233, 3 , CONTROL(None) , SINGLE_REG(None)}, // #318 [ref=1x] - { 0 , 0 , 364, 2 , CONTROL(None) , SINGLE_REG(None)}, // #319 [ref=1x] - { 0 , 0 , 366, 2 , CONTROL(None) , SINGLE_REG(None)}, // #320 [ref=1x] - { F(Vec)|F(Evex) , X(B32) , 236, 3 , CONTROL(None) , SINGLE_REG(None)}, // #321 [ref=1x] - { F(Vec)|F(Evex) , X(B64) , 236, 3 , CONTROL(None) , SINGLE_REG(None)}, // #322 [ref=1x] - { F(Vec)|F(Vex)|F(EvexTransformable) , 0 , 191, 2 , CONTROL(None) , SINGLE_REG(RO) }, // #323 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(RO) }, // #324 [ref=2x] - { F(Vec)|F(Vex)|F(EvexTransformable) , 0 , 191, 2 , CONTROL(None) , SINGLE_REG(WO) }, // #325 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #326 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 191, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #327 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 191, 3 , CONTROL(None) , SINGLE_REG(RO) }, // #328 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #329 [ref=13x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 491, 1 , CONTROL(None) , SINGLE_REG(None)}, // #330 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 492, 1 , CONTROL(None) , SINGLE_REG(None)}, // #331 [ref=1x] - { F(Vec)|F(Evex) , 0 , 493, 1 , CONTROL(None) , SINGLE_REG(None)}, // #332 [ref=6x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 239, 3 , CONTROL(None) , SINGLE_REG(None)}, // #333 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 494, 1 , CONTROL(None) , SINGLE_REG(None)}, // #334 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #335 [ref=1x] - { F(Vec)|F(Evex) , X(K) , 242, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #336 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(B32) , 242, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #337 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K) , 245, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #338 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K)|X(B32) , 245, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #339 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexKReg) , X(K)|X(B64) , 245, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #340 [ref=2x] - { F(Vec)|F(Vex) , 0 , 443, 1 , CONTROL(None) , SINGLE_REG(None)}, // #341 [ref=1x] - { F(Vec)|F(Vex) , 0 , 444, 1 , CONTROL(None) , SINGLE_REG(None)}, // #342 [ref=1x] - { F(Vec)|F(Vex) , 0 , 445, 1 , CONTROL(None) , SINGLE_REG(None)}, // #343 [ref=1x] - { F(Vec)|F(Vex) , 0 , 446, 1 , CONTROL(None) , SINGLE_REG(None)}, // #344 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(B64) , 242, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #345 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #346 [ref=6x] - { F(Vec)|F(Vex)|F(Evex)|F(PreferEvex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #347 [ref=4x] - { F(Vec)|F(Vex) , 0 , 195, 1 , CONTROL(None) , SINGLE_REG(None)}, // #348 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 192, 2 , CONTROL(None) , SINGLE_REG(None)}, // #349 [ref=2x] - { F(Vec)|F(Vex) , 0 , 171, 4 , CONTROL(None) , SINGLE_REG(None)}, // #350 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 85 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #351 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 175, 4 , CONTROL(None) , SINGLE_REG(None)}, // #352 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 447, 1 , CONTROL(None) , SINGLE_REG(None)}, // #353 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 448, 1 , CONTROL(None) , SINGLE_REG(None)}, // #354 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 495, 1 , CONTROL(None) , SINGLE_REG(None)}, // #355 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 496, 1 , CONTROL(None) , SINGLE_REG(None)}, // #356 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 497, 1 , CONTROL(None) , SINGLE_REG(None)}, // #357 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 498, 1 , CONTROL(None) , SINGLE_REG(None)}, // #358 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 499, 1 , CONTROL(None) , SINGLE_REG(None)}, // #359 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #360 [ref=4x] - { F(Vec)|F(Vex) , 0 , 348, 1 , CONTROL(None) , SINGLE_REG(None)}, // #361 [ref=12x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 191, 3 , CONTROL(None) , SINGLE_REG(RO) }, // #362 [ref=8x] - { F(Vec)|F(Evex) , 0 , 500, 1 , CONTROL(None) , SINGLE_REG(None)}, // #363 [ref=4x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 248, 3 , CONTROL(None) , SINGLE_REG(None)}, // #364 [ref=6x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 251, 3 , CONTROL(None) , SINGLE_REG(None)}, // #365 [ref=9x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 254, 3 , CONTROL(None) , SINGLE_REG(None)}, // #366 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 257, 3 , CONTROL(None) , SINGLE_REG(None)}, // #367 [ref=4x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 260, 3 , CONTROL(None) , SINGLE_REG(None)}, // #368 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 203, 3 , CONTROL(None) , SINGLE_REG(None)}, // #369 [ref=6x] - { F(Vec)|F(Vex) , 0 , 159, 2 , CONTROL(None) , SINGLE_REG(None)}, // #370 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #371 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #372 [ref=3x] - { F(Vec)|F(Vex) , 0 , 368, 2 , CONTROL(None) , SINGLE_REG(None)}, // #373 [ref=4x] - { F(Vec)|F(Vsib)|F(Evex) , X(K) , 263, 3 , CONTROL(None) , SINGLE_REG(None)}, // #374 [ref=2x] - { F(Vec)|F(Vsib)|F(Evex) , X(K) , 370, 2 , CONTROL(None) , SINGLE_REG(None)}, // #375 [ref=2x] - { F(Vec)|F(Vsib)|F(Evex) , X(K) , 372, 2 , CONTROL(None) , SINGLE_REG(None)}, // #376 [ref=2x] - { F(Vec)|F(Vsib)|F(Evex) , X(K) , 266, 3 , CONTROL(None) , SINGLE_REG(None)}, // #377 [ref=2x] - { F(Vec)|F(Vex) , 0 , 374, 2 , CONTROL(None) , SINGLE_REG(None)}, // #378 [ref=8x] - { F(Vec)|F(Evex) , X(K) , 269, 3 , CONTROL(None) , SINGLE_REG(None)}, // #379 [ref=5x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #380 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #381 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 91 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #382 [ref=3x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , 0 , 215, 3 , CONTROL(None) , SINGLE_REG(None)}, // #383 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 91 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #384 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 91 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #385 [ref=3x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 97 , 6 , CONTROL(None) , SINGLE_REG(None)}, // #386 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z) , 191, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #387 [ref=6x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 191, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #388 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 191, 3 , CONTROL(None) , SINGLE_REG(WO) }, // #389 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(B32) , 269, 3 , CONTROL(None) , SINGLE_REG(None)}, // #390 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(B64) , 269, 3 , CONTROL(None) , SINGLE_REG(None)}, // #391 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 469, 1 , CONTROL(None) , SINGLE_REG(None)}, // #392 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 470, 1 , CONTROL(None) , SINGLE_REG(None)}, // #393 [ref=2x] - { F(Vec)|F(Vex) , 0 , 470, 1 , CONTROL(None) , SINGLE_REG(None)}, // #394 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 481, 1 , CONTROL(None) , SINGLE_REG(None)}, // #395 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z) , 482, 1 , CONTROL(None) , SINGLE_REG(None)}, // #396 [ref=1x] - { F(Vec)|F(Vex) , 0 , 215, 2 , CONTROL(None) , SINGLE_REG(None)}, // #397 [ref=2x] - { F(Vec)|F(Vex) , 0 , 481, 1 , CONTROL(None) , SINGLE_REG(None)}, // #398 [ref=1x] - { F(Vec)|F(Vex) , 0 , 482, 1 , CONTROL(None) , SINGLE_REG(None)}, // #399 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64)|X(ER)|X(SAE) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #400 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32)|X(ER)|X(SAE) , 191, 3 , CONTROL(None) , SINGLE_REG(None)}, // #401 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(ER)|X(SAE) , 469, 1 , CONTROL(None) , SINGLE_REG(None)}, // #402 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(ER)|X(SAE) , 470, 1 , CONTROL(None) , SINGLE_REG(None)}, // #403 [ref=1x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B32) , 195, 2 , CONTROL(None) , SINGLE_REG(None)}, // #404 [ref=2x] - { F(Vec)|F(Evex) , X(K)|X(Z)|X(B64) , 195, 2 , CONTROL(None) , SINGLE_REG(None)}, // #405 [ref=2x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B32) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #406 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64) , 194, 3 , CONTROL(None) , SINGLE_REG(None)}, // #407 [ref=1x] - { F(Vec)|F(Vex)|F(Evex)|F(EvexCompat) , X(K)|X(Z)|X(B64)|X(ER)|X(SAE) , 206, 3 , CONTROL(None) , SINGLE_REG(None)}, // #408 [ref=1x] - { F(Vec)|F(Vex) , 0 , 108, 1 , CONTROL(None) , SINGLE_REG(None)}, // #409 [ref=2x] - { 0 , 0 , 23 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #410 [ref=2x] - { 0 , 0 , 61 , 1 , CONTROL(None) , SINGLE_REG(None)}, // #411 [ref=2x] - { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 58 , 4 , CONTROL(None) , SINGLE_REG(None)}, // #412 [ref=1x] - { 0 , 0 , 501, 1 , CONTROL(None) , SINGLE_REG(None)}, // #413 [ref=1x] - { F(Lock)|F(XAcquire) , 0 , 58 , 8 , CONTROL(None) , SINGLE_REG(RO) }, // #414 [ref=1x] - { 0 , 0 , 502, 1 , CONTROL(None) , SINGLE_REG(None)}, // #415 [ref=6x] - { 0 , 0 , 503, 1 , CONTROL(None) , SINGLE_REG(None)} // #416 [ref=6x] + { 0 , 0 , 0 , 0 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #0 [ref=1x] + { 0 , 0 , 383, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #1 [ref=4x] + { 0 , 0 , 384, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #2 [ref=2x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #3 [ref=2x] + { 0 , 0 , 180, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #4 [ref=2x] + { F(Vec) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #5 [ref=54x] + { F(Vec) , 0 , 106, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #6 [ref=19x] + { F(Vec) , 0 , 212, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #7 [ref=16x] + { F(Vec) , 0 , 221, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #8 [ref=20x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 28 , 11, CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #9 [ref=1x] + { F(Vex) , 0 , 275, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #10 [ref=3x] + { F(Vec) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #11 [ref=12x] + { 0 , 0 , 385, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #12 [ref=1x] + { F(Vex) , 0 , 277, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #13 [ref=5x] + { F(Vex) , 0 , 180, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #14 [ref=12x] + { F(Vec) , 0 , 386, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #15 [ref=4x] + { 0 , 0 , 279, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #16 [ref=3x] + { F(Mib) , 0 , 387, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #17 [ref=1x] + { 0 , 0 , 388, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #18 [ref=1x] + { 0 , 0 , 281, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #19 [ref=1x] + { F(Mib) , 0 , 389, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #20 [ref=1x] + { 0 , 0 , 283, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #21 [ref=1x] + { 0 , 0 , 179, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #22 [ref=35x] + { 0 , 0 , 390, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #23 [ref=3x] + { 0 , 0 , 123, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #24 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 123, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #25 [ref=3x] + { F(Rep)|F(RepIgnored) , 0 , 285, 2 , CONTROL_FLOW(Call), SAME_REG_HINT(None)}, // #26 [ref=1x] + { 0 , 0 , 391, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #27 [ref=1x] + { 0 , 0 , 392, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #28 [ref=2x] + { 0 , 0 , 364, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #29 [ref=1x] + { 0 , 0 , 108, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #30 [ref=83x] + { 0 , 0 , 393, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #31 [ref=11x] + { 0 , 0 , 394, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #32 [ref=6x] + { 0 , 0 , 395, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #33 [ref=13x] + { 0 , 0 , 396, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #34 [ref=1x] + { 0 , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #35 [ref=1x] + { F(Rep) , 0 , 127, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #36 [ref=1x] + { F(Vec) , 0 , 397, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #37 [ref=2x] + { F(Vec) , 0 , 398, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #38 [ref=3x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 131, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #39 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 399, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #40 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 400, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #41 [ref=1x] + { 0 , 0 , 401, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #42 [ref=1x] + { 0 , 0 , 402, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #43 [ref=1x] + { 0 , 0 , 287, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #44 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 403, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #45 [ref=2x] + { F(Mmx)|F(Vec) , 0 , 404, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #46 [ref=2x] + { F(Mmx)|F(Vec) , 0 , 405, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #47 [ref=2x] + { F(Vec) , 0 , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #48 [ref=2x] + { F(Vec) , 0 , 407, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #49 [ref=2x] + { F(Vec) , 0 , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #50 [ref=2x] + { 0 , 0 , 409, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #51 [ref=1x] + { 0 , 0 , 410, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #52 [ref=2x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 289, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #53 [ref=2x] + { 0 , 0 , 39 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #54 [ref=3x] + { F(Mmx) , 0 , 108, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #55 [ref=1x] + { 0 , 0 , 291, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #56 [ref=2x] + { 0 , 0 , 411, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #57 [ref=1x] + { F(Vec) , 0 , 412, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #58 [ref=2x] + { F(Vec) , 0 , 293, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #59 [ref=1x] + { F(FpuM32)|F(FpuM64) , 0 , 182, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #60 [ref=6x] + { 0 , 0 , 295, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #61 [ref=9x] + { F(FpuM80) , 0 , 413, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #62 [ref=2x] + { 0 , 0 , 296, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #63 [ref=13x] + { F(FpuM32)|F(FpuM64) , 0 , 297, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #64 [ref=2x] + { F(FpuM16)|F(FpuM32) , 0 , 414, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #65 [ref=9x] + { F(FpuM16)|F(FpuM32)|F(FpuM64) , 0 , 415, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #66 [ref=3x] + { F(FpuM32)|F(FpuM64)|F(FpuM80) , 0 , 416, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #67 [ref=2x] + { F(FpuM16) , 0 , 417, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #68 [ref=3x] + { 0 , 0 , 418, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #69 [ref=13x] + { F(FpuM16) , 0 , 419, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #70 [ref=2x] + { F(FpuM32)|F(FpuM64) , 0 , 298, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #71 [ref=1x] + { 0 , 0 , 420, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #72 [ref=2x] + { 0 , 0 , 421, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #73 [ref=1x] + { 0 , 0 , 39 , 10, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #74 [ref=1x] + { 0 , 0 , 422, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #75 [ref=1x] + { 0 , 0 , 423, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #76 [ref=2x] + { 0 , 0 , 348, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #77 [ref=3x] + { F(Rep) , 0 , 424, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #78 [ref=1x] + { F(Vec) , 0 , 299, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #79 [ref=1x] + { 0 , 0 , 425, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #80 [ref=2x] + { 0 , 0 , 426, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #81 [ref=8x] + { 0 , 0 , 301, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #82 [ref=3x] + { 0 , 0 , 303, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #83 [ref=1x] + { 0 , 0 , 108, 1 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #84 [ref=2x] + { 0 , 0 , 395, 1 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #85 [ref=1x] + { F(Rep)|F(RepIgnored) , 0 , 305, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #86 [ref=30x] + { F(Rep)|F(RepIgnored) , 0 , 307, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #87 [ref=1x] + { F(Rep)|F(RepIgnored) , 0 , 309, 2 , CONTROL_FLOW(Jump), SAME_REG_HINT(None)}, // #88 [ref=1x] + { F(Vex) , 0 , 427, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #89 [ref=19x] + { F(Vex) , 0 , 311, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #90 [ref=1x] + { F(Vex) , 0 , 313, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #91 [ref=1x] + { F(Vex) , 0 , 315, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #92 [ref=1x] + { F(Vex) , 0 , 317, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #93 [ref=1x] + { F(Vex) , 0 , 428, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #94 [ref=12x] + { F(Vex) , 0 , 429, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #95 [ref=8x] + { F(Vex) , 0 , 427, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #96 [ref=8x] + { 0 , 0 , 430, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #97 [ref=2x] + { 0 , 0 , 319, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #98 [ref=1x] + { 0 , 0 , 321, 2 , CONTROL_FLOW(Call), SAME_REG_HINT(None)}, // #99 [ref=1x] + { F(Vec) , 0 , 230, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #100 [ref=2x] + { 0 , 0 , 431, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #101 [ref=2x] + { 0 , 0 , 323, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #102 [ref=2x] + { F(Vex) , 0 , 432, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #103 [ref=2x] + { 0 , 0 , 433, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #104 [ref=1x] + { 0 , 0 , 185, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #105 [ref=3x] + { 0 , 0 , 321, 2 , CONTROL_FLOW(Jump), SAME_REG_HINT(None)}, // #106 [ref=1x] + { 0 , 0 , 434, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #107 [ref=5x] + { F(Vex) , 0 , 435, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #108 [ref=2x] + { F(Rep) , 0 , 135, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #109 [ref=1x] + { 0 , 0 , 307, 2 , CONTROL_FLOW(Branch), SAME_REG_HINT(None)}, // #110 [ref=3x] + { 0 , 0 , 325, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #111 [ref=1x] + { F(Vex) , 0 , 436, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #112 [ref=2x] + { F(Vec) , 0 , 437, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #113 [ref=1x] + { F(Mmx) , 0 , 438, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #114 [ref=1x] + { 0 , 0 , 439, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #115 [ref=2x] + { F(XRelease) , 0 , 0 , 16, CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #116 [ref=1x] + { 0 , 0 , 49 , 9 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #117 [ref=1x] + { F(Vec) , 0 , 79 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #118 [ref=6x] + { 0 , 0 , 73 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #119 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 327, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #120 [ref=1x] + { 0 , 0 , 440, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #121 [ref=1x] + { 0 , 0 , 77 , 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #122 [ref=2x] + { F(Mmx)|F(Vec) , 0 , 441, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #123 [ref=1x] + { F(Vec) , 0 , 294, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #124 [ref=2x] + { F(Vec) , 0 , 236, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #125 [ref=4x] + { F(Vec) , 0 , 442, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #126 [ref=2x] + { F(Vec) , 0 , 80 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #127 [ref=3x] + { F(Mmx) , 0 , 443, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #128 [ref=1x] + { F(Vec) , 0 , 107, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #129 [ref=1x] + { F(Vec) , 0 , 242, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #130 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 103, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #131 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 444, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #132 [ref=1x] + { F(Rep) , 0 , 139, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #133 [ref=1x] + { F(Vec) , 0 , 106, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #134 [ref=1x] + { F(Vec) , 0 , 329, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #135 [ref=1x] + { 0 , 0 , 331, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #136 [ref=2x] + { 0 , 0 , 333, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #137 [ref=1x] + { F(Vex) , 0 , 335, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #138 [ref=1x] + { 0 , 0 , 445, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #139 [ref=1x] + { 0 , 0 , 446, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #140 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 290, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #141 [ref=2x] + { 0 , 0 , 108, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #142 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #143 [ref=1x] + { 0 , 0 , 447, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #144 [ref=1x] + { F(Rep) , 0 , 448, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #145 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #146 [ref=37x] + { F(Mmx)|F(Vec) , 0 , 339, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #147 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #148 [ref=6x] + { F(Mmx)|F(Vec) , 0 , 337, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #149 [ref=16x] + { F(Mmx) , 0 , 337, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #150 [ref=26x] + { F(Vec) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #151 [ref=4x] + { F(Vec) , 0 , 449, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #152 [ref=1x] + { F(Vec) , 0 , 450, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #153 [ref=1x] + { F(Vec) , 0 , 451, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #154 [ref=1x] + { F(Vec) , 0 , 452, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #155 [ref=1x] + { F(Vec) , 0 , 453, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #156 [ref=1x] + { F(Vec) , 0 , 454, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #157 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 341, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #158 [ref=1x] + { F(Vec) , 0 , 455, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #159 [ref=1x] + { F(Vec) , 0 , 456, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #160 [ref=1x] + { F(Vec) , 0 , 457, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #161 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 458, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #162 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 459, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #163 [ref=1x] + { F(Vec) , 0 , 263, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #164 [ref=2x] + { 0 , 0 , 143, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #165 [ref=1x] + { F(Mmx) , 0 , 339, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #166 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 343, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #167 [ref=8x] + { F(Vec) , 0 , 460, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #168 [ref=2x] + { 0 , 0 , 461, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #169 [ref=1x] + { F(Mmx)|F(Vec) , 0 , 345, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #170 [ref=3x] + { 0 , 0 , 147, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #171 [ref=1x] + { 0 , 0 , 462, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #172 [ref=8x] + { 0 , 0 , 463, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #173 [ref=4x] + { 0 , 0 , 464, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #174 [ref=8x] + { 0 , 0 , 347, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #175 [ref=1x] + { F(Rep)|F(RepIgnored) , 0 , 349, 2 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #176 [ref=1x] + { 0 , 0 , 349, 2 , CONTROL_FLOW(Return), SAME_REG_HINT(None)}, // #177 [ref=1x] + { F(Vex) , 0 , 351, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #178 [ref=1x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 16 , 12, CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #179 [ref=3x] + { F(Rep) , 0 , 151, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #180 [ref=1x] + { 0 , 0 , 465, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #181 [ref=30x] + { 0 , 0 , 188, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #182 [ref=2x] + { 0 , 0 , 466, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #183 [ref=3x] + { F(Rep) , 0 , 155, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #184 [ref=1x] + { F(Vex) , 0 , 467, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #185 [ref=5x] + { 0 , 0 , 66 , 7 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #186 [ref=1x] + { F(Tsib)|F(Vex) , 0 , 468, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #187 [ref=2x] + { F(Vex) , 0 , 395, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #188 [ref=1x] + { F(Tsib)|F(Vex) , 0 , 469, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #189 [ref=1x] + { F(Vex) , 0 , 470, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #190 [ref=1x] + { 0 , 0 , 471, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #191 [ref=2x] + { 0 , 0 , 180, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #192 [ref=2x] + { 0 , 0 , 472, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #193 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(T4X)|X(Z) , 473, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #194 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(T4X)|X(Z) , 474, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #195 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #196 [ref=22x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #197 [ref=23x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #198 [ref=22x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #199 [ref=18x] + { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #200 [ref=18x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #201 [ref=17x] + { F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #202 [ref=15x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #203 [ref=5x] + { F(Vec)|F(Vex) , 0 , 79 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #204 [ref=17x] + { F(Vec)|F(Vex) , 0 , 221, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #205 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #206 [ref=4x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #207 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #208 [ref=10x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #209 [ref=12x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #210 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #211 [ref=6x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #212 [ref=19x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #213 [ref=12x] + { F(Vec)|F(Vex) , 0 , 194, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #214 [ref=6x] + { F(Vec)|F(Vex) , 0 , 353, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #215 [ref=3x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 478, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #216 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 479, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #217 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 480, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #218 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 481, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #219 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 482, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #220 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 479, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #221 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 483, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #222 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B64)|X(ImplicitZ)|X(K)|X(SAE), 197, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #223 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(ImplicitZ)|X(K)|X(SAE), 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #224 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B32)|X(ImplicitZ)|X(K)|X(SAE), 197, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #225 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(ImplicitZ)|X(K)|X(SAE) , 484, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #226 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K)|X(SAE) , 485, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #227 [ref=1x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(ImplicitZ)|X(K)|X(SAE) , 486, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #228 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 106, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #229 [ref=2x] + { F(Evex)|F(Vec) , X(SAE) , 263, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #230 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 212, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #231 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 203, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #232 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #233 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #234 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #235 [ref=3x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #236 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #237 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 487, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #238 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #239 [ref=4x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #240 [ref=3x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #241 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 212, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #242 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #243 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #244 [ref=3x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 212, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #245 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #246 [ref=5x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #247 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 215, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #248 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #249 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #250 [ref=2x] + { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #251 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #252 [ref=1x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #253 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #254 [ref=5x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 488, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #255 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 489, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #256 [ref=2x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 489, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #257 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #258 [ref=3x] + { F(Evex)|F(Vec) , X(ER)|X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #259 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(ER)|X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #260 [ref=1x] + { F(Evex)|F(Vec) , X(ER)|X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #261 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #262 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #263 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 355, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #264 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #265 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #266 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #267 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #268 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #269 [ref=1x] + { F(Evex)|F(Vec) , X(SAE) , 406, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #270 [ref=1x] + { F(Evex)|F(Vec) , X(SAE) , 488, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #271 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #272 [ref=1x] + { F(Evex)|F(Vec) , X(SAE) , 408, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #273 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #274 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #275 [ref=3x] + { F(Vec)|F(Vex) , 0 , 194, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #276 [ref=9x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 83 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #277 [ref=3x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 83 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #278 [ref=3x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #279 [ref=8x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 216, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #280 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 490, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #281 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 217, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #282 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 412, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #283 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #284 [ref=5x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #285 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #286 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #287 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #288 [ref=4x] + { F(Vec)|F(Vex) , 0 , 159, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #289 [ref=13x] + { F(Vec)|F(Vex) , 0 , 357, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #290 [ref=4x] + { F(Vec)|F(Vex) , 0 , 359, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #291 [ref=4x] + { F(Evex)|F(Vec) , X(B64)|X(ImplicitZ)|X(K) , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #292 [ref=1x] + { F(Evex)|F(Vec) , X(B16)|X(K) , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #293 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(ImplicitZ)|X(K) , 493, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #294 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 494, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #295 [ref=1x] + { F(Evex)|F(Vec) , X(K) , 495, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #296 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 496, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #297 [ref=1x] + { F(Vec)|F(Vex) , 0 , 209, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #298 [ref=7x] + { F(Vec)|F(Vex) , 0 , 106, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #299 [ref=1x] + { F(Vec)|F(Vex) , 0 , 212, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #300 [ref=1x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 163, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #301 [ref=2x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 113, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #302 [ref=2x] + { F(Evex)|F(Vsib) , X(K) , 497, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #303 [ref=4x] + { F(Evex)|F(Vsib) , X(K) , 498, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #304 [ref=4x] + { F(Evex)|F(Vsib) , X(K) , 499, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #305 [ref=8x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 118, 5 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #306 [ref=2x] + { F(Evex)|F(EvexTwoOp)|F(Vec)|F(Vex)|F(Vsib) , X(K) , 218, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #307 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #308 [ref=3x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #309 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(SAE)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #310 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #311 [ref=3x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(SAE)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #312 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(SAE)|X(Z) , 500, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #313 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #314 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #315 [ref=22x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 361, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #316 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 361, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #317 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 501, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #318 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #319 [ref=1x] + { F(Vec)|F(Vex) , 0 , 230, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #320 [ref=1x] + { F(Vex) , 0 , 431, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #321 [ref=2x] + { F(Vec)|F(Vex) , 0 , 437, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #322 [ref=1x] + { F(Vec)|F(Vex) , 0 , 167, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #323 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #324 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #325 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #326 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(SAE)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #327 [ref=2x] + { 0 , 0 , 363, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #328 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 79 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #329 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 365, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #330 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 224, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #331 [ref=1x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 79 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #332 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 79 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #333 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 238, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #334 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 367, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #335 [ref=4x] + { F(Vec)|F(Vex) , 0 , 502, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #336 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 227, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #337 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 230, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #338 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 233, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #339 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 236, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #340 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 239, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #341 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #342 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 242, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #343 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 369, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #344 [ref=1x] + { 0 , 0 , 371, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #345 [ref=1x] + { 0 , 0 , 373, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #346 [ref=1x] + { F(Evex)|F(Vec) , X(B32) , 245, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #347 [ref=1x] + { F(Evex)|F(Vec) , X(B64) , 245, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #348 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #349 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #350 [ref=5x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #351 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #352 [ref=2x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 191, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #353 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #354 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #355 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #356 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #357 [ref=13x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 503, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #358 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 504, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #359 [ref=1x] + { F(Evex)|F(Vec) , 0 , 505, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #360 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 248, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #361 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 506, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #362 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #363 [ref=1x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #364 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ImplicitZ)|X(K) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #365 [ref=2x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(ImplicitZ)|X(K) , 251, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #366 [ref=4x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B32)|X(ImplicitZ)|X(K) , 251, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #367 [ref=2x] + { F(Evex)|F(EvexKReg)|F(Vec)|F(Vex) , X(B64)|X(ImplicitZ)|X(K) , 251, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #368 [ref=2x] + { F(Vec)|F(Vex) , 0 , 449, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #369 [ref=1x] + { F(Vec)|F(Vex) , 0 , 450, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #370 [ref=1x] + { F(Vec)|F(Vex) , 0 , 451, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #371 [ref=1x] + { F(Vec)|F(Vex) , 0 , 452, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #372 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(ImplicitZ)|X(K) , 200, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #373 [ref=4x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #374 [ref=6x] + { F(Evex)|F(EvexCompat)|F(PreferEvex)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #375 [ref=4x] + { F(Vec)|F(Vex) , 0 , 195, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #376 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 192, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #377 [ref=2x] + { F(Vec)|F(Vex) , 0 , 171, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #378 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 85 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #379 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 85 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #380 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 175, 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #381 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 453, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #382 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 454, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #383 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 507, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #384 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 508, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #385 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 509, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #386 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 510, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #387 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 511, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #388 [ref=1x] + { F(Vec)|F(Vex) , 0 , 353, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #389 [ref=12x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #390 [ref=8x] + { F(Evex)|F(Vec) , 0 , 512, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #391 [ref=4x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 254, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #392 [ref=6x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 257, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #393 [ref=9x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 260, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #394 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 212, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #395 [ref=4x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 263, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #396 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 206, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #397 [ref=6x] + { F(Vec)|F(Vex) , 0 , 159, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #398 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #399 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #400 [ref=3x] + { F(Vec)|F(Vex) , 0 , 375, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #401 [ref=4x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 266, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #402 [ref=2x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 377, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #403 [ref=2x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 379, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #404 [ref=2x] + { F(Evex)|F(Vec)|F(Vsib) , X(K) , 269, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #405 [ref=2x] + { F(Vec)|F(Vex) , 0 , 381, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #406 [ref=8x] + { F(Evex)|F(Vec) , X(ImplicitZ)|X(K) , 272, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #407 [ref=5x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #408 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #409 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 91 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #410 [ref=3x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , 0 , 221, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #411 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 91 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #412 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 91 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #413 [ref=3x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 97 , 6 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #414 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #415 [ref=6x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #416 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(WO)}, // #417 [ref=2x] + { F(Evex)|F(Vec) , X(B32)|X(ImplicitZ)|X(K) , 272, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #418 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(ImplicitZ)|X(K) , 272, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #419 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 475, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #420 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #421 [ref=2x] + { F(Evex)|F(Vec) , X(B16)|X(K)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #422 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 476, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #423 [ref=2x] + { F(Vec)|F(Vex) , 0 , 477, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #424 [ref=2x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #425 [ref=1x] + { F(Evex)|F(Vec) , X(K)|X(Z) , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #426 [ref=1x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 221, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #427 [ref=2x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 491, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #428 [ref=1x] + { F(EvexTransformable)|F(Vec)|F(Vex) , 0 , 492, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #429 [ref=1x] + { F(Evex)|F(Vec) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 191, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #430 [ref=1x] + { F(Evex)|F(Vec) , X(B32)|X(K)|X(Z) , 195, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #431 [ref=2x] + { F(Evex)|F(Vec) , X(B64)|X(K)|X(Z) , 195, 2 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #432 [ref=2x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #433 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B32)|X(K)|X(Z) , 194, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #434 [ref=1x] + { F(Evex)|F(EvexCompat)|F(Vec)|F(Vex) , X(B64)|X(ER)|X(K)|X(SAE)|X(Z) , 209, 3 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #435 [ref=1x] + { F(Vec)|F(Vex) , 0 , 108, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #436 [ref=2x] + { 0 , 0 , 23 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #437 [ref=2x] + { 0 , 0 , 61 , 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #438 [ref=2x] + { F(Lock)|F(XAcquire)|F(XRelease) , 0 , 58 , 4 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #439 [ref=1x] + { 0 , 0 , 513, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #440 [ref=1x] + { F(Lock)|F(XAcquire) , 0 , 58 , 8 , CONTROL_FLOW(Regular), SAME_REG_HINT(RO)}, // #441 [ref=1x] + { 0 , 0 , 514, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)}, // #442 [ref=6x] + { 0 , 0 , 515, 1 , CONTROL_FLOW(Regular), SAME_REG_HINT(None)} // #443 [ref=6x] }; -#undef SINGLE_REG -#undef CONTROL +#undef SAME_REG_HINT +#undef CONTROL_FLOW #undef X #undef F // ---------------------------------------------------------------------------- // ${InstCommonTable:End} -// ============================================================================ -// [asmjit::x86::InstDB - CommonInfoTableB] -// ============================================================================ +// x86::InstDB - AdditionalInfoTable +// ================================= -// ${InstCommonInfoTableB:Begin} +// ${AdditionalInfoTable:Begin} // ------------------- Automatically generated, do not edit ------------------- -#define EXT(VAL) uint32_t(Features::k##VAL) -const InstDB::CommonInfoTableB InstDB::_commonInfoTableB[] = { +#define EXT(VAL) uint32_t(CpuFeatures::X86::k##VAL) +const InstDB::AdditionalInfo InstDB::_additionalInfoTable[] = { { { 0 }, 0, 0 }, // #0 [ref=149x] { { 0 }, 1, 0 }, // #1 [ref=32x] { { 0 }, 2, 0 }, // #2 [ref=2x] @@ -2617,57 +2734,59 @@ const InstDB::CommonInfoTableB InstDB::_commonInfoTableB[] = { { { EXT(WAITPKG) }, 0, 0 }, // #122 [ref=1x] { { EXT(AVX512_4FMAPS) }, 0, 0 }, // #123 [ref=4x] { { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #124 [ref=46x] - { { EXT(AVX), EXT(AVX512_F) }, 0, 0 }, // #125 [ref=32x] - { { EXT(AVX) }, 0, 0 }, // #126 [ref=37x] - { { EXT(AESNI), EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(VAES) }, 0, 0 }, // #127 [ref=4x] - { { EXT(AESNI), EXT(AVX) }, 0, 0 }, // #128 [ref=2x] - { { EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #129 [ref=112x] - { { EXT(AVX), EXT(AVX512_DQ), EXT(AVX512_VL) }, 0, 0 }, // #130 [ref=8x] - { { EXT(AVX512_DQ), EXT(AVX512_VL) }, 0, 0 }, // #131 [ref=30x] - { { EXT(AVX2) }, 0, 0 }, // #132 [ref=7x] - { { EXT(AVX), EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #133 [ref=39x] - { { EXT(AVX), EXT(AVX512_F) }, 1, 0 }, // #134 [ref=4x] - { { EXT(AVX512_BF16), EXT(AVX512_VL) }, 0, 0 }, // #135 [ref=3x] - { { EXT(AVX512_F), EXT(AVX512_VL), EXT(F16C) }, 0, 0 }, // #136 [ref=2x] - { { EXT(AVX512_BW), EXT(AVX512_VL) }, 0, 0 }, // #137 [ref=26x] - { { EXT(AVX512_ERI) }, 0, 0 }, // #138 [ref=10x] - { { EXT(AVX512_F), EXT(AVX512_VL), EXT(FMA) }, 0, 0 }, // #139 [ref=36x] - { { EXT(AVX512_F), EXT(FMA) }, 0, 0 }, // #140 [ref=24x] - { { EXT(FMA4) }, 0, 0 }, // #141 [ref=20x] - { { EXT(XOP) }, 0, 0 }, // #142 [ref=55x] - { { EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #143 [ref=19x] - { { EXT(AVX512_PFI) }, 0, 0 }, // #144 [ref=16x] - { { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(GFNI) }, 0, 0 }, // #145 [ref=3x] - { { EXT(AVX), EXT(AVX2) }, 0, 0 }, // #146 [ref=17x] - { { EXT(AVX512_VP2INTERSECT) }, 0, 0 }, // #147 [ref=2x] - { { EXT(AVX512_4VNNIW) }, 0, 0 }, // #148 [ref=2x] - { { EXT(AVX), EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) }, 0, 0 }, // #149 [ref=54x] - { { EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) }, 0, 0 }, // #150 [ref=2x] - { { EXT(AVX512_CDI), EXT(AVX512_VL) }, 0, 0 }, // #151 [ref=6x] - { { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(PCLMULQDQ), EXT(VPCLMULQDQ) }, 0, 0 }, // #152 [ref=1x] - { { EXT(AVX) }, 1, 0 }, // #153 [ref=7x] - { { EXT(AVX512_VBMI2), EXT(AVX512_VL) }, 0, 0 }, // #154 [ref=16x] - { { EXT(AVX512_VL), EXT(AVX512_VNNI), EXT(AVX_VNNI) }, 0, 0 }, // #155 [ref=4x] - { { EXT(AVX512_VBMI), EXT(AVX512_VL) }, 0, 0 }, // #156 [ref=4x] - { { EXT(AVX), EXT(AVX512_BW) }, 0, 0 }, // #157 [ref=4x] - { { EXT(AVX), EXT(AVX512_DQ) }, 0, 0 }, // #158 [ref=4x] - { { EXT(AVX512_IFMA), EXT(AVX512_VL) }, 0, 0 }, // #159 [ref=2x] - { { EXT(AVX512_BITALG), EXT(AVX512_VL) }, 0, 0 }, // #160 [ref=3x] - { { EXT(AVX512_VL), EXT(AVX512_VPOPCNTDQ) }, 0, 0 }, // #161 [ref=2x] - { { EXT(WBNOINVD) }, 0, 0 }, // #162 [ref=1x] - { { EXT(RTM) }, 0, 0 }, // #163 [ref=3x] - { { EXT(XSAVE) }, 0, 0 }, // #164 [ref=6x] - { { EXT(TSXLDTRK) }, 0, 0 }, // #165 [ref=2x] - { { EXT(XSAVES) }, 0, 0 }, // #166 [ref=4x] - { { EXT(XSAVEC) }, 0, 0 }, // #167 [ref=2x] - { { EXT(XSAVEOPT) }, 0, 0 }, // #168 [ref=2x] - { { EXT(TSX) }, 1, 0 } // #169 [ref=1x] + { { EXT(AVX512_FP16), EXT(AVX512_VL) }, 0, 0 }, // #125 [ref=63x] + { { EXT(AVX), EXT(AVX512_F) }, 0, 0 }, // #126 [ref=32x] + { { EXT(AVX512_FP16) }, 0, 0 }, // #127 [ref=43x] + { { EXT(AVX) }, 0, 0 }, // #128 [ref=37x] + { { EXT(AESNI), EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(VAES) }, 0, 0 }, // #129 [ref=4x] + { { EXT(AESNI), EXT(AVX) }, 0, 0 }, // #130 [ref=2x] + { { EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #131 [ref=112x] + { { EXT(AVX), EXT(AVX512_DQ), EXT(AVX512_VL) }, 0, 0 }, // #132 [ref=8x] + { { EXT(AVX512_DQ), EXT(AVX512_VL) }, 0, 0 }, // #133 [ref=30x] + { { EXT(AVX2) }, 0, 0 }, // #134 [ref=7x] + { { EXT(AVX), EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #135 [ref=39x] + { { EXT(AVX), EXT(AVX512_F) }, 1, 0 }, // #136 [ref=4x] + { { EXT(AVX512_BF16), EXT(AVX512_VL) }, 0, 0 }, // #137 [ref=3x] + { { EXT(AVX512_F), EXT(AVX512_VL), EXT(F16C) }, 0, 0 }, // #138 [ref=2x] + { { EXT(AVX512_BW), EXT(AVX512_VL) }, 0, 0 }, // #139 [ref=26x] + { { EXT(AVX512_ERI) }, 0, 0 }, // #140 [ref=10x] + { { EXT(AVX512_F), EXT(AVX512_VL), EXT(FMA) }, 0, 0 }, // #141 [ref=36x] + { { EXT(AVX512_F), EXT(FMA) }, 0, 0 }, // #142 [ref=24x] + { { EXT(FMA4) }, 0, 0 }, // #143 [ref=20x] + { { EXT(XOP) }, 0, 0 }, // #144 [ref=55x] + { { EXT(AVX2), EXT(AVX512_F), EXT(AVX512_VL) }, 0, 0 }, // #145 [ref=19x] + { { EXT(AVX512_PFI) }, 0, 0 }, // #146 [ref=16x] + { { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(GFNI) }, 0, 0 }, // #147 [ref=3x] + { { EXT(AVX), EXT(AVX2) }, 0, 0 }, // #148 [ref=17x] + { { EXT(AVX512_VP2INTERSECT) }, 0, 0 }, // #149 [ref=2x] + { { EXT(AVX512_4VNNIW) }, 0, 0 }, // #150 [ref=2x] + { { EXT(AVX), EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) }, 0, 0 }, // #151 [ref=54x] + { { EXT(AVX2), EXT(AVX512_BW), EXT(AVX512_VL) }, 0, 0 }, // #152 [ref=2x] + { { EXT(AVX512_CDI), EXT(AVX512_VL) }, 0, 0 }, // #153 [ref=6x] + { { EXT(AVX), EXT(AVX512_F), EXT(AVX512_VL), EXT(PCLMULQDQ), EXT(VPCLMULQDQ) }, 0, 0 }, // #154 [ref=1x] + { { EXT(AVX) }, 1, 0 }, // #155 [ref=7x] + { { EXT(AVX512_VBMI2), EXT(AVX512_VL) }, 0, 0 }, // #156 [ref=16x] + { { EXT(AVX512_VL), EXT(AVX512_VNNI), EXT(AVX_VNNI) }, 0, 0 }, // #157 [ref=4x] + { { EXT(AVX512_VBMI), EXT(AVX512_VL) }, 0, 0 }, // #158 [ref=4x] + { { EXT(AVX), EXT(AVX512_BW) }, 0, 0 }, // #159 [ref=4x] + { { EXT(AVX), EXT(AVX512_DQ) }, 0, 0 }, // #160 [ref=4x] + { { EXT(AVX512_IFMA), EXT(AVX512_VL) }, 0, 0 }, // #161 [ref=2x] + { { EXT(AVX512_BITALG), EXT(AVX512_VL) }, 0, 0 }, // #162 [ref=3x] + { { EXT(AVX512_VL), EXT(AVX512_VPOPCNTDQ) }, 0, 0 }, // #163 [ref=2x] + { { EXT(WBNOINVD) }, 0, 0 }, // #164 [ref=1x] + { { EXT(RTM) }, 0, 0 }, // #165 [ref=3x] + { { EXT(XSAVE) }, 0, 0 }, // #166 [ref=6x] + { { EXT(TSXLDTRK) }, 0, 0 }, // #167 [ref=2x] + { { EXT(XSAVES) }, 0, 0 }, // #168 [ref=4x] + { { EXT(XSAVEC) }, 0, 0 }, // #169 [ref=2x] + { { EXT(XSAVEOPT) }, 0, 0 }, // #170 [ref=2x] + { { EXT(TSX) }, 1, 0 } // #171 [ref=1x] }; #undef EXT -#define FLAG(VAL) uint32_t(Status::k##VAL) +#define FLAG(VAL) uint32_t(CpuRWFlags::kX86_##VAL) const InstDB::RWFlagsInfoTable InstDB::_rwFlagsInfoTable[] = { - { 0, 0 }, // #0 [ref=1323x] + { 0, 0 }, // #0 [ref=1429x] { 0, FLAG(AF) | FLAG(CF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #1 [ref=84x] { FLAG(CF), FLAG(AF) | FLAG(CF) | FLAG(OF) | FLAG(PF) | FLAG(SF) | FLAG(ZF) }, // #2 [ref=2x] { FLAG(CF), FLAG(CF) }, // #3 [ref=2x] @@ -2699,11 +2818,10 @@ const InstDB::RWFlagsInfoTable InstDB::_rwFlagsInfoTable[] = { }; #undef FLAG // ---------------------------------------------------------------------------- -// ${InstCommonInfoTableB:End} +// ${AdditionalInfoTable:End} -// ============================================================================ -// [asmjit::Inst - NameData] -// ============================================================================ +// Inst - NameData +// =============== #ifndef ASMJIT_NO_TEXT // ${NameData:Begin} @@ -2756,99 +2874,113 @@ const char InstDB::_nameData[] = "sysenter\0" "sysexit\0" "sysexitq\0" "sysret\0" "sysretq\0" "t1mskc\0" "tdpbf16ps\0" "tdpbssd\0" "tdpbsud\0" "tdpbusd\0" "tdpbuud\0" "testui\0" "tileloadd\0" "tileloaddt1\0" "tilerelease\0" "tilestored\0" "tilezero\0" "tpause\0" "tzcnt\0" "tzmsk\0" "ud0\0" "ud1\0" "ud2\0" "uiret\0" "umonitor\0" "umwait\0" "v4fmaddps\0" "v4fmaddss\0" - "v4fnmaddps\0" "v4fnmaddss\0" "vaddpd\0" "vaddps\0" "vaddsd\0" "vaddss\0" "vaddsubpd\0" "vaddsubps\0" "vaesdec\0" - "vaesdeclast\0" "vaesenc\0" "vaesenclast\0" "vaesimc\0" "vaeskeygenassist\0" "valignd\0" "valignq\0" "vandnpd\0" - "vandnps\0" "vandpd\0" "vandps\0" "vblendmpd\0" "vblendmps\0" "vblendpd\0" "vblendps\0" "vblendvpd\0" "vblendvps\0" - "vbroadcastf128\0" "vbroadcastf32x2\0" "vbroadcastf32x4\0" "vbroadcastf32x8\0" "vbroadcastf64x2\0" - "vbroadcastf64x4\0" "vbroadcasti128\0" "vbroadcasti32x2\0" "vbroadcasti32x4\0" "vbroadcasti32x8\0" - "vbroadcasti64x2\0" "vbroadcasti64x4\0" "vbroadcastsd\0" "vbroadcastss\0" "vcmppd\0" "vcmpps\0" "vcmpsd\0" "vcmpss\0" - "vcomisd\0" "vcomiss\0" "vcompresspd\0" "vcompressps\0" "vcvtdq2pd\0" "vcvtdq2ps\0" "vcvtne2ps2bf16\0" - "vcvtneps2bf16\0" "vcvtpd2dq\0" "vcvtpd2ps\0" "vcvtpd2qq\0" "vcvtpd2udq\0" "vcvtpd2uqq\0" "vcvtph2ps\0" "vcvtps2dq\0" - "vcvtps2pd\0" "vcvtps2ph\0" "vcvtps2qq\0" "vcvtps2udq\0" "vcvtps2uqq\0" "vcvtqq2pd\0" "vcvtqq2ps\0" "vcvtsd2si\0" - "vcvtsd2ss\0" "vcvtsd2usi\0" "vcvtsi2sd\0" "vcvtsi2ss\0" "vcvtss2sd\0" "vcvtss2si\0" "vcvtss2usi\0" "vcvttpd2dq\0" - "vcvttpd2qq\0" "vcvttpd2udq\0" "vcvttpd2uqq\0" "vcvttps2dq\0" "vcvttps2qq\0" "vcvttps2udq\0" "vcvttps2uqq\0" - "vcvttsd2si\0" "vcvttsd2usi\0" "vcvttss2si\0" "vcvttss2usi\0" "vcvtudq2pd\0" "vcvtudq2ps\0" "vcvtuqq2pd\0" - "vcvtuqq2ps\0" "vcvtusi2sd\0" "vcvtusi2ss\0" "vdbpsadbw\0" "vdivpd\0" "vdivps\0" "vdivsd\0" "vdivss\0" "vdpbf16ps\0" - "vdppd\0" "vdpps\0" "verr\0" "verw\0" "vexp2pd\0" "vexp2ps\0" "vexpandpd\0" "vexpandps\0" "vextractf128\0" - "vextractf32x4\0" "vextractf32x8\0" "vextractf64x2\0" "vextractf64x4\0" "vextracti128\0" "vextracti32x4\0" - "vextracti32x8\0" "vextracti64x2\0" "vextracti64x4\0" "vextractps\0" "vfixupimmpd\0" "vfixupimmps\0" "vfixupimmsd\0" - "vfixupimmss\0" "vfmadd132pd\0" "vfmadd132ps\0" "vfmadd132sd\0" "vfmadd132ss\0" "vfmadd213pd\0" "vfmadd213ps\0" - "vfmadd213sd\0" "vfmadd213ss\0" "vfmadd231pd\0" "vfmadd231ps\0" "vfmadd231sd\0" "vfmadd231ss\0" "vfmaddpd\0" - "vfmaddps\0" "vfmaddsd\0" "vfmaddss\0" "vfmaddsub132pd\0" "vfmaddsub132ps\0" "vfmaddsub213pd\0" "vfmaddsub213ps\0" - "vfmaddsub231pd\0" "vfmaddsub231ps\0" "vfmaddsubpd\0" "vfmaddsubps\0" "vfmsub132pd\0" "vfmsub132ps\0" "vfmsub132sd\0" - "vfmsub132ss\0" "vfmsub213pd\0" "vfmsub213ps\0" "vfmsub213sd\0" "vfmsub213ss\0" "vfmsub231pd\0" "vfmsub231ps\0" - "vfmsub231sd\0" "vfmsub231ss\0" "vfmsubadd132pd\0" "vfmsubadd132ps\0" "vfmsubadd213pd\0" "vfmsubadd213ps\0" - "vfmsubadd231pd\0" "vfmsubadd231ps\0" "vfmsubaddpd\0" "vfmsubaddps\0" "vfmsubpd\0" "vfmsubps\0" "vfmsubsd\0" - "vfmsubss\0" "vfnmadd132pd\0" "vfnmadd132ps\0" "vfnmadd132sd\0" "vfnmadd132ss\0" "vfnmadd213pd\0" "vfnmadd213ps\0" - "vfnmadd213sd\0" "vfnmadd213ss\0" "vfnmadd231pd\0" "vfnmadd231ps\0" "vfnmadd231sd\0" "vfnmadd231ss\0" "vfnmaddpd\0" - "vfnmaddps\0" "vfnmaddsd\0" "vfnmaddss\0" "vfnmsub132pd\0" "vfnmsub132ps\0" "vfnmsub132sd\0" "vfnmsub132ss\0" - "vfnmsub213pd\0" "vfnmsub213ps\0" "vfnmsub213sd\0" "vfnmsub213ss\0" "vfnmsub231pd\0" "vfnmsub231ps\0" - "vfnmsub231sd\0" "vfnmsub231ss\0" "vfnmsubpd\0" "vfnmsubps\0" "vfnmsubsd\0" "vfnmsubss\0" "vfpclasspd\0" - "vfpclassps\0" "vfpclasssd\0" "vfpclassss\0" "vfrczpd\0" "vfrczps\0" "vfrczsd\0" "vfrczss\0" "vgatherdpd\0" - "vgatherdps\0" "vgatherpf0dpd\0" "vgatherpf0dps\0" "vgatherpf0qpd\0" "vgatherpf0qps\0" "vgatherpf1dpd\0" - "vgatherpf1dps\0" "vgatherpf1qpd\0" "vgatherpf1qps\0" "vgatherqpd\0" "vgatherqps\0" "vgetexppd\0" "vgetexpps\0" - "vgetexpsd\0" "vgetexpss\0" "vgetmantpd\0" "vgetmantps\0" "vgetmantsd\0" "vgetmantss\0" "vgf2p8affineinvqb\0" - "vgf2p8affineqb\0" "vgf2p8mulb\0" "vhaddpd\0" "vhaddps\0" "vhsubpd\0" "vhsubps\0" "vinsertf128\0" "vinsertf32x4\0" - "vinsertf32x8\0" "vinsertf64x2\0" "vinsertf64x4\0" "vinserti128\0" "vinserti32x4\0" "vinserti32x8\0" "vinserti64x2\0" - "vinserti64x4\0" "vinsertps\0" "vlddqu\0" "vldmxcsr\0" "vmaskmovdqu\0" "vmaskmovpd\0" "vmaskmovps\0" "vmaxpd\0" - "vmaxps\0" "vmaxsd\0" "vmaxss\0" "vmcall\0" "vmclear\0" "vmfunc\0" "vminpd\0" "vminps\0" "vminsd\0" "vminss\0" - "vmlaunch\0" "vmload\0" "vmmcall\0" "vmovapd\0" "vmovaps\0" "vmovd\0" "vmovddup\0" "vmovdqa\0" "vmovdqa32\0" - "vmovdqa64\0" "vmovdqu\0" "vmovdqu16\0" "vmovdqu32\0" "vmovdqu64\0" "vmovdqu8\0" "vmovhlps\0" "vmovhpd\0" "vmovhps\0" - "vmovlhps\0" "vmovlpd\0" "vmovlps\0" "vmovmskpd\0" "vmovmskps\0" "vmovntdq\0" "vmovntdqa\0" "vmovntpd\0" "vmovntps\0" - "vmovq\0" "vmovsd\0" "vmovshdup\0" "vmovsldup\0" "vmovss\0" "vmovupd\0" "vmovups\0" "vmpsadbw\0" "vmptrld\0" - "vmptrst\0" "vmread\0" "vmresume\0" "vmrun\0" "vmsave\0" "vmulpd\0" "vmulps\0" "vmulsd\0" "vmulss\0" "vmwrite\0" - "vmxon\0" "vorpd\0" "vorps\0" "vp2intersectd\0" "vp2intersectq\0" "vp4dpwssd\0" "vp4dpwssds\0" "vpabsb\0" "vpabsd\0" - "vpabsq\0" "vpabsw\0" "vpackssdw\0" "vpacksswb\0" "vpackusdw\0" "vpackuswb\0" "vpaddb\0" "vpaddd\0" "vpaddq\0" - "vpaddsb\0" "vpaddsw\0" "vpaddusb\0" "vpaddusw\0" "vpaddw\0" "vpalignr\0" "vpand\0" "vpandd\0" "vpandn\0" "vpandnd\0" - "vpandnq\0" "vpandq\0" "vpavgb\0" "vpavgw\0" "vpblendd\0" "vpblendmb\0" "vpblendmd\0" "vpblendmq\0" "vpblendmw\0" - "vpblendvb\0" "vpblendw\0" "vpbroadcastb\0" "vpbroadcastd\0" "vpbroadcastmb2q\0" "vpbroadcastmw2d\0" "vpbroadcastq\0" - "vpbroadcastw\0" "vpclmulqdq\0" "vpcmov\0" "vpcmpb\0" "vpcmpd\0" "vpcmpeqb\0" "vpcmpeqd\0" "vpcmpeqq\0" "vpcmpeqw\0" - "vpcmpestri\0" "vpcmpestrm\0" "vpcmpgtb\0" "vpcmpgtd\0" "vpcmpgtq\0" "vpcmpgtw\0" "vpcmpistri\0" "vpcmpistrm\0" - "vpcmpq\0" "vpcmpub\0" "vpcmpud\0" "vpcmpuq\0" "vpcmpuw\0" "vpcmpw\0" "vpcomb\0" "vpcomd\0" "vpcompressb\0" - "vpcompressd\0" "vpcompressq\0" "vpcompressw\0" "vpcomq\0" "vpcomub\0" "vpcomud\0" "vpcomuq\0" "vpcomuw\0" "vpcomw\0" - "vpconflictd\0" "vpconflictq\0" "vpdpbusd\0" "vpdpbusds\0" "vpdpwssd\0" "vpdpwssds\0" "vperm2f128\0" "vperm2i128\0" - "vpermb\0" "vpermd\0" "vpermi2b\0" "vpermi2d\0" "vpermi2pd\0" "vpermi2ps\0" "vpermi2q\0" "vpermi2w\0" "vpermil2pd\0" - "vpermil2ps\0" "vpermilpd\0" "vpermilps\0" "vpermpd\0" "vpermps\0" "vpermq\0" "vpermt2b\0" "vpermt2d\0" "vpermt2pd\0" - "vpermt2ps\0" "vpermt2q\0" "vpermt2w\0" "vpermw\0" "vpexpandb\0" "vpexpandd\0" "vpexpandq\0" "vpexpandw\0" - "vpextrb\0" "vpextrd\0" "vpextrq\0" "vpextrw\0" "vpgatherdd\0" "vpgatherdq\0" "vpgatherqd\0" "vpgatherqq\0" - "vphaddbd\0" "vphaddbq\0" "vphaddbw\0" "vphaddd\0" "vphadddq\0" "vphaddsw\0" "vphaddubd\0" "vphaddubq\0" - "vphaddubw\0" "vphaddudq\0" "vphadduwd\0" "vphadduwq\0" "vphaddw\0" "vphaddwd\0" "vphaddwq\0" "vphminposuw\0" - "vphsubbw\0" "vphsubd\0" "vphsubdq\0" "vphsubsw\0" "vphsubw\0" "vphsubwd\0" "vpinsrb\0" "vpinsrd\0" "vpinsrq\0" - "vpinsrw\0" "vplzcntd\0" "vplzcntq\0" "vpmacsdd\0" "vpmacsdqh\0" "vpmacsdql\0" "vpmacssdd\0" "vpmacssdqh\0" - "vpmacssdql\0" "vpmacsswd\0" "vpmacssww\0" "vpmacswd\0" "vpmacsww\0" "vpmadcsswd\0" "vpmadcswd\0" "vpmadd52huq\0" - "vpmadd52luq\0" "vpmaddubsw\0" "vpmaddwd\0" "vpmaskmovd\0" "vpmaskmovq\0" "vpmaxsb\0" "vpmaxsd\0" "vpmaxsq\0" - "vpmaxsw\0" "vpmaxub\0" "vpmaxud\0" "vpmaxuq\0" "vpmaxuw\0" "vpminsb\0" "vpminsd\0" "vpminsq\0" "vpminsw\0" - "vpminub\0" "vpminud\0" "vpminuq\0" "vpminuw\0" "vpmovb2m\0" "vpmovd2m\0" "vpmovdb\0" "vpmovdw\0" "vpmovm2b\0" - "vpmovm2d\0" "vpmovm2q\0" "vpmovm2w\0" "vpmovmskb\0" "vpmovq2m\0" "vpmovqb\0" "vpmovqd\0" "vpmovqw\0" "vpmovsdb\0" - "vpmovsdw\0" "vpmovsqb\0" "vpmovsqd\0" "vpmovsqw\0" "vpmovswb\0" "vpmovsxbd\0" "vpmovsxbq\0" "vpmovsxbw\0" - "vpmovsxdq\0" "vpmovsxwd\0" "vpmovsxwq\0" "vpmovusdb\0" "vpmovusdw\0" "vpmovusqb\0" "vpmovusqd\0" "vpmovusqw\0" - "vpmovuswb\0" "vpmovw2m\0" "vpmovwb\0" "vpmovzxbd\0" "vpmovzxbq\0" "vpmovzxbw\0" "vpmovzxdq\0" "vpmovzxwd\0" - "vpmovzxwq\0" "vpmuldq\0" "vpmulhrsw\0" "vpmulhuw\0" "vpmulhw\0" "vpmulld\0" "vpmullq\0" "vpmullw\0" - "vpmultishiftqb\0" "vpmuludq\0" "vpopcntb\0" "vpopcntd\0" "vpopcntq\0" "vpopcntw\0" "vpor\0" "vpord\0" "vporq\0" - "vpperm\0" "vprold\0" "vprolq\0" "vprolvd\0" "vprolvq\0" "vprord\0" "vprorq\0" "vprorvd\0" "vprorvq\0" "vprotb\0" - "vprotd\0" "vprotq\0" "vprotw\0" "vpsadbw\0" "vpscatterdd\0" "vpscatterdq\0" "vpscatterqd\0" "vpscatterqq\0" - "vpshab\0" "vpshad\0" "vpshaq\0" "vpshaw\0" "vpshlb\0" "vpshld\0" "vpshldd\0" "vpshldq\0" "vpshldvd\0" "vpshldvq\0" - "vpshldvw\0" "vpshldw\0" "vpshlq\0" "vpshlw\0" "vpshrdd\0" "vpshrdq\0" "vpshrdvd\0" "vpshrdvq\0" "vpshrdvw\0" - "vpshrdw\0" "vpshufb\0" "vpshufbitqmb\0" "vpshufd\0" "vpshufhw\0" "vpshuflw\0" "vpsignb\0" "vpsignd\0" "vpsignw\0" - "vpslld\0" "vpslldq\0" "vpsllq\0" "vpsllvd\0" "vpsllvq\0" "vpsllvw\0" "vpsllw\0" "vpsrad\0" "vpsraq\0" "vpsravd\0" - "vpsravq\0" "vpsravw\0" "vpsraw\0" "vpsrld\0" "vpsrldq\0" "vpsrlq\0" "vpsrlvd\0" "vpsrlvq\0" "vpsrlvw\0" "vpsrlw\0" - "vpsubb\0" "vpsubd\0" "vpsubq\0" "vpsubsb\0" "vpsubsw\0" "vpsubusb\0" "vpsubusw\0" "vpsubw\0" "vpternlogd\0" - "vpternlogq\0" "vptest\0" "vptestmb\0" "vptestmd\0" "vptestmq\0" "vptestmw\0" "vptestnmb\0" "vptestnmd\0" - "vptestnmq\0" "vptestnmw\0" "vpunpckhbw\0" "vpunpckhdq\0" "vpunpckhqdq\0" "vpunpckhwd\0" "vpunpcklbw\0" - "vpunpckldq\0" "vpunpcklqdq\0" "vpunpcklwd\0" "vpxor\0" "vpxord\0" "vpxorq\0" "vrangepd\0" "vrangeps\0" "vrangesd\0" - "vrangess\0" "vrcp14pd\0" "vrcp14ps\0" "vrcp14sd\0" "vrcp14ss\0" "vrcp28pd\0" "vrcp28ps\0" "vrcp28sd\0" "vrcp28ss\0" - "vrcpps\0" "vrcpss\0" "vreducepd\0" "vreduceps\0" "vreducesd\0" "vreducess\0" "vrndscalepd\0" "vrndscaleps\0" - "vrndscalesd\0" "vrndscaless\0" "vroundpd\0" "vroundps\0" "vroundsd\0" "vroundss\0" "vrsqrt14pd\0" "vrsqrt14ps\0" - "vrsqrt14sd\0" "vrsqrt14ss\0" "vrsqrt28pd\0" "vrsqrt28ps\0" "vrsqrt28sd\0" "vrsqrt28ss\0" "vrsqrtps\0" "vrsqrtss\0" - "vscalefpd\0" "vscalefps\0" "vscalefsd\0" "vscalefss\0" "vscatterdpd\0" "vscatterdps\0" "vscatterpf0dpd\0" - "vscatterpf0dps\0" "vscatterpf0qpd\0" "vscatterpf0qps\0" "vscatterpf1dpd\0" "vscatterpf1dps\0" "vscatterpf1qpd\0" - "vscatterpf1qps\0" "vscatterqpd\0" "vscatterqps\0" "vshuff32x4\0" "vshuff64x2\0" "vshufi32x4\0" "vshufi64x2\0" - "vshufpd\0" "vshufps\0" "vsqrtpd\0" "vsqrtps\0" "vsqrtsd\0" "vsqrtss\0" "vstmxcsr\0" "vsubpd\0" "vsubps\0" "vsubsd\0" - "vsubss\0" "vtestpd\0" "vtestps\0" "vucomisd\0" "vucomiss\0" "vunpckhpd\0" "vunpckhps\0" "vunpcklpd\0" "vunpcklps\0" - "vxorpd\0" "vxorps\0" "vzeroall\0" "vzeroupper\0" "wbinvd\0" "wbnoinvd\0" "wrfsbase\0" "wrgsbase\0" "wrmsr\0" - "wrssd\0" "wrssq\0" "wrussd\0" "wrussq\0" "xabort\0" "xadd\0" "xbegin\0" "xend\0" "xgetbv\0" "xlatb\0" "xresldtrk\0" - "xrstors\0" "xrstors64\0" "xsavec\0" "xsavec64\0" "xsaveopt\0" "xsaveopt64\0" "xsaves\0" "xsaves64\0" "xsetbv\0" - "xsusldtrk\0" "xtest"; + "v4fnmaddps\0" "v4fnmaddss\0" "vaddpd\0" "vaddph\0" "vaddps\0" "vaddsd\0" "vaddsh\0" "vaddss\0" "vaddsubpd\0" + "vaddsubps\0" "vaesdec\0" "vaesdeclast\0" "vaesenc\0" "vaesenclast\0" "vaesimc\0" "vaeskeygenassist\0" "valignd\0" + "valignq\0" "vandnpd\0" "vandnps\0" "vandpd\0" "vandps\0" "vblendmpd\0" "vblendmps\0" "vblendpd\0" "vblendps\0" + "vblendvpd\0" "vblendvps\0" "vbroadcastf128\0" "vbroadcastf32x2\0" "vbroadcastf32x4\0" "vbroadcastf32x8\0" + "vbroadcastf64x2\0" "vbroadcastf64x4\0" "vbroadcasti128\0" "vbroadcasti32x2\0" "vbroadcasti32x4\0" + "vbroadcasti32x8\0" "vbroadcasti64x2\0" "vbroadcasti64x4\0" "vbroadcastsd\0" "vbroadcastss\0" "vcmppd\0" "vcmpph\0" + "vcmpps\0" "vcmpsd\0" "vcmpsh\0" "vcmpss\0" "vcomisd\0" "vcomish\0" "vcomiss\0" "vcompresspd\0" "vcompressps\0" + "vcvtdq2pd\0" "vcvtdq2ph\0" "vcvtdq2ps\0" "vcvtne2ps2bf16\0" "vcvtneps2bf16\0" "vcvtpd2dq\0" "vcvtpd2ph\0" + "vcvtpd2ps\0" "vcvtpd2qq\0" "vcvtpd2udq\0" "vcvtpd2uqq\0" "vcvtph2dq\0" "vcvtph2pd\0" "vcvtph2ps\0" "vcvtph2psx\0" + "vcvtph2qq\0" "vcvtph2udq\0" "vcvtph2uqq\0" "vcvtph2uw\0" "vcvtph2w\0" "vcvtps2dq\0" "vcvtps2pd\0" "vcvtps2ph\0" + "vcvtps2phx\0" "vcvtps2qq\0" "vcvtps2udq\0" "vcvtps2uqq\0" "vcvtqq2pd\0" "vcvtqq2ph\0" "vcvtqq2ps\0" "vcvtsd2sh\0" + "vcvtsd2si\0" "vcvtsd2ss\0" "vcvtsd2usi\0" "vcvtsh2sd\0" "vcvtsh2si\0" "vcvtsh2ss\0" "vcvtsh2usi\0" "vcvtsi2sd\0" + "vcvtsi2sh\0" "vcvtsi2ss\0" "vcvtss2sd\0" "vcvtss2sh\0" "vcvtss2si\0" "vcvtss2usi\0" "vcvttpd2dq\0" "vcvttpd2qq\0" + "vcvttpd2udq\0" "vcvttpd2uqq\0" "vcvttph2dq\0" "vcvttph2qq\0" "vcvttph2udq\0" "vcvttph2uqq\0" "vcvttph2uw\0" + "vcvttph2w\0" "vcvttps2dq\0" "vcvttps2qq\0" "vcvttps2udq\0" "vcvttps2uqq\0" "vcvttsd2si\0" "vcvttsd2usi\0" + "vcvttsh2si\0" "vcvttsh2usi\0" "vcvttss2si\0" "vcvttss2usi\0" "vcvtudq2pd\0" "vcvtudq2ph\0" "vcvtudq2ps\0" + "vcvtuqq2pd\0" "vcvtuqq2ph\0" "vcvtuqq2ps\0" "vcvtusi2sd\0" "vcvtusi2sh\0" "vcvtusi2ss\0" "vcvtuw2ph\0" "vcvtw2ph\0" + "vdbpsadbw\0" "vdivpd\0" "vdivph\0" "vdivps\0" "vdivsd\0" "vdivsh\0" "vdivss\0" "vdpbf16ps\0" "vdppd\0" "vdpps\0" + "verr\0" "verw\0" "vexp2pd\0" "vexp2ps\0" "vexpandpd\0" "vexpandps\0" "vextractf128\0" "vextractf32x4\0" + "vextractf32x8\0" "vextractf64x2\0" "vextractf64x4\0" "vextracti128\0" "vextracti32x4\0" "vextracti32x8\0" + "vextracti64x2\0" "vextracti64x4\0" "vextractps\0" "vfcmaddcph\0" "vfcmaddcsh\0" "vfcmulcph\0" "vfcmulcsh\0" + "vfixupimmpd\0" "vfixupimmps\0" "vfixupimmsd\0" "vfixupimmss\0" "vfmadd132pd\0" "vfmadd132ph\0" "vfmadd132ps\0" + "vfmadd132sd\0" "vfmadd132sh\0" "vfmadd132ss\0" "vfmadd213pd\0" "vfmadd213ph\0" "vfmadd213ps\0" "vfmadd213sd\0" + "vfmadd213sh\0" "vfmadd213ss\0" "vfmadd231pd\0" "vfmadd231ph\0" "vfmadd231ps\0" "vfmadd231sd\0" "vfmadd231sh\0" + "vfmadd231ss\0" "vfmaddcph\0" "vfmaddcsh\0" "vfmaddpd\0" "vfmaddps\0" "vfmaddsd\0" "vfmaddss\0" "vfmaddsub132pd\0" + "vfmaddsub132ph\0" "vfmaddsub132ps\0" "vfmaddsub213pd\0" "vfmaddsub213ph\0" "vfmaddsub213ps\0" "vfmaddsub231pd\0" + "vfmaddsub231ph\0" "vfmaddsub231ps\0" "vfmaddsubpd\0" "vfmaddsubps\0" "vfmsub132pd\0" "vfmsub132ph\0" "vfmsub132ps\0" + "vfmsub132sd\0" "vfmsub132sh\0" "vfmsub132ss\0" "vfmsub213pd\0" "vfmsub213ph\0" "vfmsub213ps\0" "vfmsub213sd\0" + "vfmsub213sh\0" "vfmsub213ss\0" "vfmsub231pd\0" "vfmsub231ph\0" "vfmsub231ps\0" "vfmsub231sd\0" "vfmsub231sh\0" + "vfmsub231ss\0" "vfmsubadd132pd\0" "vfmsubadd132ph\0" "vfmsubadd132ps\0" "vfmsubadd213pd\0" "vfmsubadd213ph\0" + "vfmsubadd213ps\0" "vfmsubadd231pd\0" "vfmsubadd231ph\0" "vfmsubadd231ps\0" "vfmsubaddpd\0" "vfmsubaddps\0" + "vfmsubpd\0" "vfmsubps\0" "vfmsubsd\0" "vfmsubss\0" "vfmulcph\0" "vfmulcsh\0" "vfnmadd132pd\0" "vfnmadd132ph\0" + "vfnmadd132ps\0" "vfnmadd132sd\0" "vfnmadd132sh\0" "vfnmadd132ss\0" "vfnmadd213pd\0" "vfnmadd213ph\0" + "vfnmadd213ps\0" "vfnmadd213sd\0" "vfnmadd213sh\0" "vfnmadd213ss\0" "vfnmadd231pd\0" "vfnmadd231ph\0" + "vfnmadd231ps\0" "vfnmadd231sd\0" "vfnmadd231sh\0" "vfnmadd231ss\0" "vfnmaddpd\0" "vfnmaddps\0" "vfnmaddsd\0" + "vfnmaddss\0" "vfnmsub132pd\0" "vfnmsub132ph\0" "vfnmsub132ps\0" "vfnmsub132sd\0" "vfnmsub132sh\0" "vfnmsub132ss\0" + "vfnmsub213pd\0" "vfnmsub213ph\0" "vfnmsub213ps\0" "vfnmsub213sd\0" "vfnmsub213sh\0" "vfnmsub213ss\0" + "vfnmsub231pd\0" "vfnmsub231ph\0" "vfnmsub231ps\0" "vfnmsub231sd\0" "vfnmsub231sh\0" "vfnmsub231ss\0" "vfnmsubpd\0" + "vfnmsubps\0" "vfnmsubsd\0" "vfnmsubss\0" "vfpclasspd\0" "vfpclassph\0" "vfpclassps\0" "vfpclasssd\0" "vfpclasssh\0" + "vfpclassss\0" "vfrczpd\0" "vfrczps\0" "vfrczsd\0" "vfrczss\0" "vgatherdpd\0" "vgatherdps\0" "vgatherpf0dpd\0" + "vgatherpf0dps\0" "vgatherpf0qpd\0" "vgatherpf0qps\0" "vgatherpf1dpd\0" "vgatherpf1dps\0" "vgatherpf1qpd\0" + "vgatherpf1qps\0" "vgatherqpd\0" "vgatherqps\0" "vgetexppd\0" "vgetexpph\0" "vgetexpps\0" "vgetexpsd\0" "vgetexpsh\0" + "vgetexpss\0" "vgetmantpd\0" "vgetmantph\0" "vgetmantps\0" "vgetmantsd\0" "vgetmantsh\0" "vgetmantss\0" + "vgf2p8affineinvqb\0" "vgf2p8affineqb\0" "vgf2p8mulb\0" "vhaddpd\0" "vhaddps\0" "vhsubpd\0" "vhsubps\0" + "vinsertf128\0" "vinsertf32x4\0" "vinsertf32x8\0" "vinsertf64x2\0" "vinsertf64x4\0" "vinserti128\0" "vinserti32x4\0" + "vinserti32x8\0" "vinserti64x2\0" "vinserti64x4\0" "vinsertps\0" "vlddqu\0" "vldmxcsr\0" "vmaskmovdqu\0" + "vmaskmovpd\0" "vmaskmovps\0" "vmaxpd\0" "vmaxph\0" "vmaxps\0" "vmaxsd\0" "vmaxsh\0" "vmaxss\0" "vmcall\0" + "vmclear\0" "vmfunc\0" "vminpd\0" "vminph\0" "vminps\0" "vminsd\0" "vminsh\0" "vminss\0" "vmlaunch\0" "vmload\0" + "vmmcall\0" "vmovapd\0" "vmovaps\0" "vmovd\0" "vmovddup\0" "vmovdqa\0" "vmovdqa32\0" "vmovdqa64\0" "vmovdqu\0" + "vmovdqu16\0" "vmovdqu32\0" "vmovdqu64\0" "vmovdqu8\0" "vmovhlps\0" "vmovhpd\0" "vmovhps\0" "vmovlhps\0" "vmovlpd\0" + "vmovlps\0" "vmovmskpd\0" "vmovmskps\0" "vmovntdq\0" "vmovntdqa\0" "vmovntpd\0" "vmovntps\0" "vmovq\0" "vmovsd\0" + "vmovsh\0" "vmovshdup\0" "vmovsldup\0" "vmovss\0" "vmovupd\0" "vmovups\0" "vmovw\0" "vmpsadbw\0" "vmptrld\0" + "vmptrst\0" "vmread\0" "vmresume\0" "vmrun\0" "vmsave\0" "vmulpd\0" "vmulph\0" "vmulps\0" "vmulsd\0" "vmulsh\0" + "vmulss\0" "vmwrite\0" "vmxon\0" "vorpd\0" "vorps\0" "vp2intersectd\0" "vp2intersectq\0" "vp4dpwssd\0" "vp4dpwssds\0" + "vpabsb\0" "vpabsd\0" "vpabsq\0" "vpabsw\0" "vpackssdw\0" "vpacksswb\0" "vpackusdw\0" "vpackuswb\0" "vpaddb\0" + "vpaddd\0" "vpaddq\0" "vpaddsb\0" "vpaddsw\0" "vpaddusb\0" "vpaddusw\0" "vpaddw\0" "vpalignr\0" "vpand\0" "vpandd\0" + "vpandn\0" "vpandnd\0" "vpandnq\0" "vpandq\0" "vpavgb\0" "vpavgw\0" "vpblendd\0" "vpblendmb\0" "vpblendmd\0" + "vpblendmq\0" "vpblendmw\0" "vpblendvb\0" "vpblendw\0" "vpbroadcastb\0" "vpbroadcastd\0" "vpbroadcastmb2q\0" + "vpbroadcastmw2d\0" "vpbroadcastq\0" "vpbroadcastw\0" "vpclmulqdq\0" "vpcmov\0" "vpcmpb\0" "vpcmpd\0" "vpcmpeqb\0" + "vpcmpeqd\0" "vpcmpeqq\0" "vpcmpeqw\0" "vpcmpestri\0" "vpcmpestrm\0" "vpcmpgtb\0" "vpcmpgtd\0" "vpcmpgtq\0" + "vpcmpgtw\0" "vpcmpistri\0" "vpcmpistrm\0" "vpcmpq\0" "vpcmpub\0" "vpcmpud\0" "vpcmpuq\0" "vpcmpuw\0" "vpcmpw\0" + "vpcomb\0" "vpcomd\0" "vpcompressb\0" "vpcompressd\0" "vpcompressq\0" "vpcompressw\0" "vpcomq\0" "vpcomub\0" + "vpcomud\0" "vpcomuq\0" "vpcomuw\0" "vpcomw\0" "vpconflictd\0" "vpconflictq\0" "vpdpbusd\0" "vpdpbusds\0" + "vpdpwssd\0" "vpdpwssds\0" "vperm2f128\0" "vperm2i128\0" "vpermb\0" "vpermd\0" "vpermi2b\0" "vpermi2d\0" + "vpermi2pd\0" "vpermi2ps\0" "vpermi2q\0" "vpermi2w\0" "vpermil2pd\0" "vpermil2ps\0" "vpermilpd\0" "vpermilps\0" + "vpermpd\0" "vpermps\0" "vpermq\0" "vpermt2b\0" "vpermt2d\0" "vpermt2pd\0" "vpermt2ps\0" "vpermt2q\0" "vpermt2w\0" + "vpermw\0" "vpexpandb\0" "vpexpandd\0" "vpexpandq\0" "vpexpandw\0" "vpextrb\0" "vpextrd\0" "vpextrq\0" "vpextrw\0" + "vpgatherdd\0" "vpgatherdq\0" "vpgatherqd\0" "vpgatherqq\0" "vphaddbd\0" "vphaddbq\0" "vphaddbw\0" "vphaddd\0" + "vphadddq\0" "vphaddsw\0" "vphaddubd\0" "vphaddubq\0" "vphaddubw\0" "vphaddudq\0" "vphadduwd\0" "vphadduwq\0" + "vphaddw\0" "vphaddwd\0" "vphaddwq\0" "vphminposuw\0" "vphsubbw\0" "vphsubd\0" "vphsubdq\0" "vphsubsw\0" "vphsubw\0" + "vphsubwd\0" "vpinsrb\0" "vpinsrd\0" "vpinsrq\0" "vpinsrw\0" "vplzcntd\0" "vplzcntq\0" "vpmacsdd\0" "vpmacsdqh\0" + "vpmacsdql\0" "vpmacssdd\0" "vpmacssdqh\0" "vpmacssdql\0" "vpmacsswd\0" "vpmacssww\0" "vpmacswd\0" "vpmacsww\0" + "vpmadcsswd\0" "vpmadcswd\0" "vpmadd52huq\0" "vpmadd52luq\0" "vpmaddubsw\0" "vpmaddwd\0" "vpmaskmovd\0" + "vpmaskmovq\0" "vpmaxsb\0" "vpmaxsd\0" "vpmaxsq\0" "vpmaxsw\0" "vpmaxub\0" "vpmaxud\0" "vpmaxuq\0" "vpmaxuw\0" + "vpminsb\0" "vpminsd\0" "vpminsq\0" "vpminsw\0" "vpminub\0" "vpminud\0" "vpminuq\0" "vpminuw\0" "vpmovb2m\0" + "vpmovd2m\0" "vpmovdb\0" "vpmovdw\0" "vpmovm2b\0" "vpmovm2d\0" "vpmovm2q\0" "vpmovm2w\0" "vpmovmskb\0" "vpmovq2m\0" + "vpmovqb\0" "vpmovqd\0" "vpmovqw\0" "vpmovsdb\0" "vpmovsdw\0" "vpmovsqb\0" "vpmovsqd\0" "vpmovsqw\0" "vpmovswb\0" + "vpmovsxbd\0" "vpmovsxbq\0" "vpmovsxbw\0" "vpmovsxdq\0" "vpmovsxwd\0" "vpmovsxwq\0" "vpmovusdb\0" "vpmovusdw\0" + "vpmovusqb\0" "vpmovusqd\0" "vpmovusqw\0" "vpmovuswb\0" "vpmovw2m\0" "vpmovwb\0" "vpmovzxbd\0" "vpmovzxbq\0" + "vpmovzxbw\0" "vpmovzxdq\0" "vpmovzxwd\0" "vpmovzxwq\0" "vpmuldq\0" "vpmulhrsw\0" "vpmulhuw\0" "vpmulhw\0" + "vpmulld\0" "vpmullq\0" "vpmullw\0" "vpmultishiftqb\0" "vpmuludq\0" "vpopcntb\0" "vpopcntd\0" "vpopcntq\0" + "vpopcntw\0" "vpor\0" "vpord\0" "vporq\0" "vpperm\0" "vprold\0" "vprolq\0" "vprolvd\0" "vprolvq\0" "vprord\0" + "vprorq\0" "vprorvd\0" "vprorvq\0" "vprotb\0" "vprotd\0" "vprotq\0" "vprotw\0" "vpsadbw\0" "vpscatterdd\0" + "vpscatterdq\0" "vpscatterqd\0" "vpscatterqq\0" "vpshab\0" "vpshad\0" "vpshaq\0" "vpshaw\0" "vpshlb\0" "vpshld\0" + "vpshldd\0" "vpshldq\0" "vpshldvd\0" "vpshldvq\0" "vpshldvw\0" "vpshldw\0" "vpshlq\0" "vpshlw\0" "vpshrdd\0" + "vpshrdq\0" "vpshrdvd\0" "vpshrdvq\0" "vpshrdvw\0" "vpshrdw\0" "vpshufb\0" "vpshufbitqmb\0" "vpshufd\0" "vpshufhw\0" + "vpshuflw\0" "vpsignb\0" "vpsignd\0" "vpsignw\0" "vpslld\0" "vpslldq\0" "vpsllq\0" "vpsllvd\0" "vpsllvq\0" + "vpsllvw\0" "vpsllw\0" "vpsrad\0" "vpsraq\0" "vpsravd\0" "vpsravq\0" "vpsravw\0" "vpsraw\0" "vpsrld\0" "vpsrldq\0" + "vpsrlq\0" "vpsrlvd\0" "vpsrlvq\0" "vpsrlvw\0" "vpsrlw\0" "vpsubb\0" "vpsubd\0" "vpsubq\0" "vpsubsb\0" "vpsubsw\0" + "vpsubusb\0" "vpsubusw\0" "vpsubw\0" "vpternlogd\0" "vpternlogq\0" "vptest\0" "vptestmb\0" "vptestmd\0" "vptestmq\0" + "vptestmw\0" "vptestnmb\0" "vptestnmd\0" "vptestnmq\0" "vptestnmw\0" "vpunpckhbw\0" "vpunpckhdq\0" "vpunpckhqdq\0" + "vpunpckhwd\0" "vpunpcklbw\0" "vpunpckldq\0" "vpunpcklqdq\0" "vpunpcklwd\0" "vpxor\0" "vpxord\0" "vpxorq\0" + "vrangepd\0" "vrangeps\0" "vrangesd\0" "vrangess\0" "vrcp14pd\0" "vrcp14ps\0" "vrcp14sd\0" "vrcp14ss\0" "vrcp28pd\0" + "vrcp28ps\0" "vrcp28sd\0" "vrcp28ss\0" "vrcpph\0" "vrcpps\0" "vrcpsh\0" "vrcpss\0" "vreducepd\0" "vreduceph\0" + "vreduceps\0" "vreducesd\0" "vreducesh\0" "vreducess\0" "vrndscalepd\0" "vrndscaleph\0" "vrndscaleps\0" + "vrndscalesd\0" "vrndscalesh\0" "vrndscaless\0" "vroundpd\0" "vroundps\0" "vroundsd\0" "vroundss\0" "vrsqrt14pd\0" + "vrsqrt14ps\0" "vrsqrt14sd\0" "vrsqrt14ss\0" "vrsqrt28pd\0" "vrsqrt28ps\0" "vrsqrt28sd\0" "vrsqrt28ss\0" "vrsqrtph\0" + "vrsqrtps\0" "vrsqrtsh\0" "vrsqrtss\0" "vscalefpd\0" "vscalefph\0" "vscalefps\0" "vscalefsd\0" "vscalefsh\0" + "vscalefss\0" "vscatterdpd\0" "vscatterdps\0" "vscatterpf0dpd\0" "vscatterpf0dps\0" "vscatterpf0qpd\0" + "vscatterpf0qps\0" "vscatterpf1dpd\0" "vscatterpf1dps\0" "vscatterpf1qpd\0" "vscatterpf1qps\0" "vscatterqpd\0" + "vscatterqps\0" "vshuff32x4\0" "vshuff64x2\0" "vshufi32x4\0" "vshufi64x2\0" "vshufpd\0" "vshufps\0" "vsqrtpd\0" + "vsqrtph\0" "vsqrtps\0" "vsqrtsd\0" "vsqrtsh\0" "vsqrtss\0" "vstmxcsr\0" "vsubpd\0" "vsubph\0" "vsubps\0" "vsubsd\0" + "vsubsh\0" "vsubss\0" "vtestpd\0" "vtestps\0" "vucomisd\0" "vucomish\0" "vucomiss\0" "vunpckhpd\0" "vunpckhps\0" + "vunpcklpd\0" "vunpcklps\0" "vxorpd\0" "vxorps\0" "vzeroall\0" "vzeroupper\0" "wbinvd\0" "wbnoinvd\0" "wrfsbase\0" + "wrgsbase\0" "wrmsr\0" "wrssd\0" "wrssq\0" "wrussd\0" "wrussq\0" "xabort\0" "xadd\0" "xbegin\0" "xend\0" "xgetbv\0" + "xlatb\0" "xresldtrk\0" "xrstors\0" "xrstors64\0" "xsavec\0" "xsavec64\0" "xsaveopt\0" "xsaveopt64\0" "xsaves\0" + "xsaves64\0" "xsetbv\0" "xsusldtrk\0" "xtest"; const InstDB::InstNameIndex InstDB::instNameIndex[26] = { { Inst::kIdAaa , Inst::kIdArpl + 1 }, @@ -2882,19 +3014,18 @@ const InstDB::InstNameIndex InstDB::instNameIndex[26] = { // ${NameData:End} #endif // !ASMJIT_NO_TEXT -// ============================================================================ -// [asmjit::x86::InstDB - InstSignature / OpSignature] -// ============================================================================ +// x86::InstDB - InstSignature & OpSignature +// ========================================= #ifndef ASMJIT_NO_VALIDATION // ${InstSignatureTable:Begin} // ------------------- Automatically generated, do not edit ------------------- -#define ROW(count, x86, x64, implicit, o0, o1, o2, o3, o4, o5) \ - { count, (x86 ? uint8_t(InstDB::kModeX86) : uint8_t(0)) | \ - (x64 ? uint8_t(InstDB::kModeX64) : uint8_t(0)) , \ - implicit, \ - 0, \ - { o0, o1, o2, o3, o4, o5 } \ +#define ROW(count, x86, x64, implicit, o0, o1, o2, o3, o4, o5) \ + { count, uint8_t(x86 ? uint8_t(InstDB::Mode::kX86) : uint8_t(0)) | \ + (x64 ? uint8_t(InstDB::Mode::kX64) : uint8_t(0)) , \ + implicit, \ + 0, \ + { o0, o1, o2, o3, o4, o5 } \ } const InstDB::InstSignature InstDB::_instSignatureTable[] = { ROW(2, 1, 1, 0, 1 , 2 , 0 , 0 , 0 , 0 ), // #0 {r8lo|r8hi|m8|mem, r8lo|r8hi} @@ -3097,507 +3228,517 @@ const InstDB::InstSignature InstDB::_instSignatureTable[] = { ROW(4, 1, 1, 0, 104, 50 , 51 , 10 , 0 , 0 ), // #197 {xmm|k, xmm, xmm|m128|mem, i8|u8} ROW(4, 1, 1, 0, 105, 53 , 54 , 10 , 0 , 0 ), // {ymm|k, ymm, ymm|m256|mem, i8|u8} ROW(4, 1, 1, 0, 106, 56 , 57 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} - ROW(2, 1, 1, 0, 51 , 50 , 0 , 0 , 0 , 0 ), // #200 {xmm|m128|mem, xmm} + ROW(4, 1, 1, 0, 106, 50 , 51 , 10 , 0 , 0 ), // #200 {k, xmm, xmm|m128|mem, i8|u8} + ROW(4, 1, 1, 0, 106, 53 , 54 , 10 , 0 , 0 ), // {k, ymm, ymm|m256|mem, i8|u8} + ROW(4, 1, 1, 0, 106, 56 , 57 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} + ROW(2, 1, 1, 0, 51 , 50 , 0 , 0 , 0 , 0 ), // #203 {xmm|m128|mem, xmm} ROW(2, 1, 1, 0, 54 , 53 , 0 , 0 , 0 , 0 ), // {ymm|m256|mem, ymm} ROW(2, 1, 1, 0, 57 , 56 , 0 , 0 , 0 , 0 ), // {zmm|m512|mem, zmm} - ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #203 {xmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #206 {xmm, xmm|m64|mem} ROW(2, 1, 1, 0, 53 , 51 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m128|mem} ROW(2, 1, 1, 0, 56 , 54 , 0 , 0 , 0 , 0 ), // {zmm, ymm|m256|mem} - ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // #206 {xmm, xmm|m128|mem} + ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // #209 {xmm, xmm|m128|mem} ROW(2, 1, 1, 0, 53 , 54 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} ROW(2, 1, 1, 0, 56 , 57 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} - ROW(3, 1, 1, 0, 65 , 50 , 10 , 0 , 0 , 0 ), // #209 {xmm|m64|mem, xmm, i8|u8} - ROW(3, 1, 1, 0, 51 , 53 , 10 , 0 , 0 , 0 ), // #210 {xmm|m128|mem, ymm, i8|u8} - ROW(3, 1, 1, 0, 54 , 56 , 10 , 0 , 0 , 0 ), // #211 {ymm|m256|mem, zmm, i8|u8} - ROW(3, 1, 1, 0, 50 , 107, 50 , 0 , 0 , 0 ), // #212 {xmm, vm64x|vm64y, xmm} - ROW(2, 1, 1, 0, 50 , 107, 0 , 0 , 0 , 0 ), // {xmm, vm64x|vm64y} + ROW(2, 1, 1, 0, 50 , 107, 0 , 0 , 0 , 0 ), // #212 {xmm, xmm|m32|mem} + ROW(2, 1, 1, 0, 53 , 65 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m64|mem} + ROW(2, 1, 1, 0, 56 , 51 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 65 , 50 , 10 , 0 , 0 , 0 ), // #215 {xmm|m64|mem, xmm, i8|u8} + ROW(3, 1, 1, 0, 51 , 53 , 10 , 0 , 0 , 0 ), // #216 {xmm|m128|mem, ymm, i8|u8} + ROW(3, 1, 1, 0, 54 , 56 , 10 , 0 , 0 , 0 ), // #217 {ymm|m256|mem, zmm, i8|u8} + ROW(3, 1, 1, 0, 50 , 108, 50 , 0 , 0 , 0 ), // #218 {xmm, vm64x|vm64y, xmm} + ROW(2, 1, 1, 0, 50 , 108, 0 , 0 , 0 , 0 ), // {xmm, vm64x|vm64y} ROW(2, 1, 1, 0, 53 , 72 , 0 , 0 , 0 , 0 ), // {ymm, vm64z} - ROW(3, 1, 1, 0, 50 , 51 , 10 , 0 , 0 , 0 ), // #215 {xmm, xmm|m128|mem, i8|u8} + ROW(3, 1, 1, 0, 50 , 51 , 10 , 0 , 0 , 0 ), // #221 {xmm, xmm|m128|mem, i8|u8} ROW(3, 1, 1, 0, 53 , 54 , 10 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem, i8|u8} ROW(3, 1, 1, 0, 56 , 57 , 10 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem, i8|u8} - ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #218 {xmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 50 , 65 , 0 , 0 , 0 , 0 ), // #224 {xmm, xmm|m64|mem} ROW(2, 1, 1, 0, 53 , 54 , 0 , 0 , 0 , 0 ), // {ymm, ymm|m256|mem} ROW(2, 1, 1, 0, 56 , 57 , 0 , 0 , 0 , 0 ), // {zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 52 , 50 , 0 , 0 , 0 , 0 ), // #221 {m128|mem, xmm} + ROW(2, 1, 1, 0, 52 , 50 , 0 , 0 , 0 , 0 ), // #227 {m128|mem, xmm} ROW(2, 1, 1, 0, 55 , 53 , 0 , 0 , 0 , 0 ), // {m256|mem, ymm} ROW(2, 1, 1, 0, 58 , 56 , 0 , 0 , 0 , 0 ), // {m512|mem, zmm} - ROW(2, 1, 1, 0, 50 , 52 , 0 , 0 , 0 , 0 ), // #224 {xmm, m128|mem} + ROW(2, 1, 1, 0, 50 , 52 , 0 , 0 , 0 , 0 ), // #230 {xmm, m128|mem} ROW(2, 1, 1, 0, 53 , 55 , 0 , 0 , 0 , 0 ), // {ymm, m256|mem} ROW(2, 1, 1, 0, 56 , 58 , 0 , 0 , 0 , 0 ), // {zmm, m512|mem} - ROW(2, 0, 1, 0, 15 , 50 , 0 , 0 , 0 , 0 ), // #227 {r64|m64|mem, xmm} - ROW(2, 1, 1, 0, 50 , 108, 0 , 0 , 0 , 0 ), // {xmm, xmm|m64|mem|r64} + ROW(2, 0, 1, 0, 15 , 50 , 0 , 0 , 0 , 0 ), // #233 {r64|m64|mem, xmm} + ROW(2, 1, 1, 0, 50 , 109, 0 , 0 , 0 , 0 ), // {xmm, xmm|m64|mem|r64} ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // {m64|mem, xmm} - ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #230 {m64|mem, xmm} + ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #236 {m64|mem, xmm} ROW(2, 1, 1, 0, 50 , 30 , 0 , 0 , 0 , 0 ), // {xmm, m64|mem} - ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // #232 {xmm, xmm, xmm} - ROW(2, 1, 1, 0, 29 , 50 , 0 , 0 , 0 , 0 ), // #233 {m32|mem, xmm} + ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // #238 {xmm, xmm, xmm} + ROW(2, 1, 1, 0, 21 , 50 , 0 , 0 , 0 , 0 ), // #239 {m16|mem, xmm} + ROW(2, 1, 1, 0, 50 , 21 , 0 , 0 , 0 , 0 ), // {xmm, m16|mem} + ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // {xmm, xmm, xmm} + ROW(2, 1, 1, 0, 29 , 50 , 0 , 0 , 0 , 0 ), // #242 {m32|mem, xmm} ROW(2, 1, 1, 0, 50 , 29 , 0 , 0 , 0 , 0 ), // {xmm, m32|mem} ROW(3, 1, 1, 0, 50 , 50 , 50 , 0 , 0 , 0 ), // {xmm, xmm, xmm} - ROW(4, 1, 1, 0, 106, 106, 50 , 51 , 0 , 0 ), // #236 {k, k, xmm, xmm|m128|mem} + ROW(4, 1, 1, 0, 106, 106, 50 , 51 , 0 , 0 ), // #245 {k, k, xmm, xmm|m128|mem} ROW(4, 1, 1, 0, 106, 106, 53 , 54 , 0 , 0 ), // {k, k, ymm, ymm|m256|mem} ROW(4, 1, 1, 0, 106, 106, 56 , 57 , 0 , 0 ), // {k, k, zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 96 , 108, 0 , 0 , 0 , 0 ), // #239 {xmm|ymm, xmm|m64|mem|r64} + ROW(2, 1, 1, 0, 96 , 109, 0 , 0 , 0 , 0 ), // #248 {xmm|ymm, xmm|m64|mem|r64} ROW(2, 0, 1, 0, 56 , 8 , 0 , 0 , 0 , 0 ), // {zmm, r64} ROW(2, 1, 1, 0, 56 , 65 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m64|mem} - ROW(4, 1, 1, 0, 106, 50 , 51 , 10 , 0 , 0 ), // #242 {k, xmm, xmm|m128|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 53 , 54 , 10 , 0 , 0 ), // {k, ymm, ymm|m256|mem, i8|u8} - ROW(4, 1, 1, 0, 106, 56 , 57 , 10 , 0 , 0 ), // {k, zmm, zmm|m512|mem, i8|u8} - ROW(3, 1, 1, 0, 104, 50 , 51 , 0 , 0 , 0 ), // #245 {xmm|k, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 104, 50 , 51 , 0 , 0 , 0 ), // #251 {xmm|k, xmm, xmm|m128|mem} ROW(3, 1, 1, 0, 105, 53 , 54 , 0 , 0 , 0 ), // {ymm|k, ymm, ymm|m256|mem} ROW(3, 1, 1, 0, 106, 56 , 57 , 0 , 0 , 0 ), // {k, zmm, zmm|m512|mem} - ROW(2, 1, 1, 0, 109, 50 , 0 , 0 , 0 , 0 ), // #248 {xmm|m32|mem, xmm} + ROW(2, 1, 1, 0, 107, 50 , 0 , 0 , 0 , 0 ), // #254 {xmm|m32|mem, xmm} ROW(2, 1, 1, 0, 65 , 53 , 0 , 0 , 0 , 0 ), // {xmm|m64|mem, ymm} ROW(2, 1, 1, 0, 51 , 56 , 0 , 0 , 0 , 0 ), // {xmm|m128|mem, zmm} - ROW(2, 1, 1, 0, 65 , 50 , 0 , 0 , 0 , 0 ), // #251 {xmm|m64|mem, xmm} + ROW(2, 1, 1, 0, 65 , 50 , 0 , 0 , 0 , 0 ), // #257 {xmm|m64|mem, xmm} ROW(2, 1, 1, 0, 51 , 53 , 0 , 0 , 0 , 0 ), // {xmm|m128|mem, ymm} ROW(2, 1, 1, 0, 54 , 56 , 0 , 0 , 0 , 0 ), // {ymm|m256|mem, zmm} - ROW(2, 1, 1, 0, 110, 50 , 0 , 0 , 0 , 0 ), // #254 {xmm|m16|mem, xmm} - ROW(2, 1, 1, 0, 109, 53 , 0 , 0 , 0 , 0 ), // {xmm|m32|mem, ymm} + ROW(2, 1, 1, 0, 110, 50 , 0 , 0 , 0 , 0 ), // #260 {xmm|m16|mem, xmm} + ROW(2, 1, 1, 0, 107, 53 , 0 , 0 , 0 , 0 ), // {xmm|m32|mem, ymm} ROW(2, 1, 1, 0, 65 , 56 , 0 , 0 , 0 , 0 ), // {xmm|m64|mem, zmm} - ROW(2, 1, 1, 0, 50 , 109, 0 , 0 , 0 , 0 ), // #257 {xmm, xmm|m32|mem} - ROW(2, 1, 1, 0, 53 , 65 , 0 , 0 , 0 , 0 ), // {ymm, xmm|m64|mem} - ROW(2, 1, 1, 0, 56 , 51 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m128|mem} - ROW(2, 1, 1, 0, 50 , 110, 0 , 0 , 0 , 0 ), // #260 {xmm, xmm|m16|mem} - ROW(2, 1, 1, 0, 53 , 109, 0 , 0 , 0 , 0 ), // {ymm, xmm|m32|mem} + ROW(2, 1, 1, 0, 50 , 110, 0 , 0 , 0 , 0 ), // #263 {xmm, xmm|m16|mem} + ROW(2, 1, 1, 0, 53 , 107, 0 , 0 , 0 , 0 ), // {ymm, xmm|m32|mem} ROW(2, 1, 1, 0, 56 , 65 , 0 , 0 , 0 , 0 ), // {zmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 67 , 50 , 0 , 0 , 0 , 0 ), // #263 {vm32x, xmm} + ROW(2, 1, 1, 0, 67 , 50 , 0 , 0 , 0 , 0 ), // #266 {vm32x, xmm} ROW(2, 1, 1, 0, 68 , 53 , 0 , 0 , 0 , 0 ), // {vm32y, ymm} ROW(2, 1, 1, 0, 69 , 56 , 0 , 0 , 0 , 0 ), // {vm32z, zmm} - ROW(2, 1, 1, 0, 70 , 50 , 0 , 0 , 0 , 0 ), // #266 {vm64x, xmm} + ROW(2, 1, 1, 0, 70 , 50 , 0 , 0 , 0 , 0 ), // #269 {vm64x, xmm} ROW(2, 1, 1, 0, 71 , 53 , 0 , 0 , 0 , 0 ), // {vm64y, ymm} ROW(2, 1, 1, 0, 72 , 56 , 0 , 0 , 0 , 0 ), // {vm64z, zmm} - ROW(3, 1, 1, 0, 106, 50 , 51 , 0 , 0 , 0 ), // #269 {k, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 106, 50 , 51 , 0 , 0 , 0 ), // #272 {k, xmm, xmm|m128|mem} ROW(3, 1, 1, 0, 106, 53 , 54 , 0 , 0 , 0 ), // {k, ymm, ymm|m256|mem} ROW(3, 1, 1, 0, 106, 56 , 57 , 0 , 0 , 0 ), // {k, zmm, zmm|m512|mem} - ROW(3, 1, 1, 0, 6 , 6 , 28 , 0 , 0 , 0 ), // #272 {r32, r32, r32|m32|mem} + ROW(3, 1, 1, 0, 6 , 6 , 28 , 0 , 0 , 0 ), // #275 {r32, r32, r32|m32|mem} ROW(3, 0, 1, 0, 8 , 8 , 15 , 0 , 0 , 0 ), // {r64, r64, r64|m64|mem} - ROW(3, 1, 1, 0, 6 , 28 , 6 , 0 , 0 , 0 ), // #274 {r32, r32|m32|mem, r32} + ROW(3, 1, 1, 0, 6 , 28 , 6 , 0 , 0 , 0 ), // #277 {r32, r32|m32|mem, r32} ROW(3, 0, 1, 0, 8 , 15 , 8 , 0 , 0 , 0 ), // {r64, r64|m64|mem, r64} - ROW(2, 1, 0, 0, 111, 28 , 0 , 0 , 0 , 0 ), // #276 {bnd, r32|m32|mem} + ROW(2, 1, 0, 0, 111, 28 , 0 , 0 , 0 , 0 ), // #279 {bnd, r32|m32|mem} ROW(2, 0, 1, 0, 111, 15 , 0 , 0 , 0 , 0 ), // {bnd, r64|m64|mem} - ROW(2, 1, 1, 0, 111, 112, 0 , 0 , 0 , 0 ), // #278 {bnd, bnd|mem} + ROW(2, 1, 1, 0, 111, 112, 0 , 0 , 0 , 0 ), // #281 {bnd, bnd|mem} ROW(2, 1, 1, 0, 113, 111, 0 , 0 , 0 , 0 ), // {mem, bnd} - ROW(2, 1, 0, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #280 {r16, m32|mem} + ROW(2, 1, 0, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #283 {r16, m32|mem} ROW(2, 1, 0, 0, 6 , 30 , 0 , 0 , 0 , 0 ), // {r32, m64|mem} - ROW(1, 1, 0, 0, 114, 0 , 0 , 0 , 0 , 0 ), // #282 {rel16|r16|m16|r32|m32} + ROW(1, 1, 0, 0, 114, 0 , 0 , 0 , 0 , 0 ), // #285 {rel16|r16|m16|r32|m32} ROW(1, 1, 1, 0, 115, 0 , 0 , 0 , 0 , 0 ), // {rel32|r64|m64|mem} - ROW(2, 1, 1, 0, 6 , 116, 0 , 0 , 0 , 0 ), // #284 {r32, r8lo|r8hi|m8|r16|m16|r32|m32} + ROW(2, 1, 1, 0, 6 , 116, 0 , 0 , 0 , 0 ), // #287 {r32, r8lo|r8hi|m8|r16|m16|r32|m32} ROW(2, 0, 1, 0, 8 , 117, 0 , 0 , 0 , 0 ), // {r64, r8lo|r8hi|m8|r64|m64} - ROW(1, 1, 0, 0, 118, 0 , 0 , 0 , 0 , 0 ), // #286 {r16|r32} - ROW(1, 1, 1, 0, 31 , 0 , 0 , 0 , 0 , 0 ), // #287 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem} - ROW(2, 1, 0, 0, 119, 58 , 0 , 0 , 0 , 0 ), // #288 {es:[mem|m512|memBase], m512|mem} + ROW(1, 1, 0, 0, 118, 0 , 0 , 0 , 0 , 0 ), // #289 {r16|r32} + ROW(1, 1, 1, 0, 31 , 0 , 0 , 0 , 0 , 0 ), // #290 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem} + ROW(2, 1, 0, 0, 119, 58 , 0 , 0 , 0 , 0 ), // #291 {es:[mem|m512|memBase], m512|mem} ROW(2, 0, 1, 0, 119, 58 , 0 , 0 , 0 , 0 ), // {es:[mem|m512|memBase], m512|mem} - ROW(3, 1, 1, 0, 50 , 10 , 10 , 0 , 0 , 0 ), // #290 {xmm, i8|u8, i8|u8} - ROW(2, 1, 1, 0, 50 , 50 , 0 , 0 , 0 , 0 ), // #291 {xmm, xmm} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #292 {} - ROW(1, 1, 1, 0, 100, 0 , 0 , 0 , 0 , 0 ), // #293 {st} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #294 {} - ROW(1, 1, 1, 0, 120, 0 , 0 , 0 , 0 , 0 ), // #295 {m32|m64|st} - ROW(2, 1, 1, 0, 50 , 50 , 0 , 0 , 0 , 0 ), // #296 {xmm, xmm} + ROW(3, 1, 1, 0, 50 , 10 , 10 , 0 , 0 , 0 ), // #293 {xmm, i8|u8, i8|u8} + ROW(2, 1, 1, 0, 50 , 50 , 0 , 0 , 0 , 0 ), // #294 {xmm, xmm} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #295 {} + ROW(1, 1, 1, 0, 100, 0 , 0 , 0 , 0 , 0 ), // #296 {st} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #297 {} + ROW(1, 1, 1, 0, 120, 0 , 0 , 0 , 0 , 0 ), // #298 {m32|m64|st} + ROW(2, 1, 1, 0, 50 , 50 , 0 , 0 , 0 , 0 ), // #299 {xmm, xmm} ROW(4, 1, 1, 0, 50 , 50 , 10 , 10 , 0 , 0 ), // {xmm, xmm, i8|u8, i8|u8} - ROW(2, 1, 0, 0, 6 , 52 , 0 , 0 , 0 , 0 ), // #298 {r32, m128|mem} + ROW(2, 1, 0, 0, 6 , 52 , 0 , 0 , 0 , 0 ), // #301 {r32, m128|mem} ROW(2, 0, 1, 0, 8 , 52 , 0 , 0 , 0 , 0 ), // {r64, m128|mem} - ROW(2, 1, 0, 2, 36 , 121, 0 , 0 , 0 , 0 ), // #300 {<eax>, <ecx>} + ROW(2, 1, 0, 2, 36 , 121, 0 , 0 , 0 , 0 ), // #303 {<eax>, <ecx>} ROW(2, 0, 1, 2, 122, 121, 0 , 0 , 0 , 0 ), // {<eax|rax>, <ecx>} - ROW(1, 1, 1, 0, 123, 0 , 0 , 0 , 0 , 0 ), // #302 {rel8|rel32} + ROW(1, 1, 1, 0, 123, 0 , 0 , 0 , 0 , 0 ), // #305 {rel8|rel32} ROW(1, 1, 0, 0, 124, 0 , 0 , 0 , 0 , 0 ), // {rel16} - ROW(2, 1, 0, 1, 125, 126, 0 , 0 , 0 , 0 ), // #304 {<cx|ecx>, rel8} + ROW(2, 1, 0, 1, 125, 126, 0 , 0 , 0 , 0 ), // #307 {<cx|ecx>, rel8} ROW(2, 0, 1, 1, 127, 126, 0 , 0 , 0 , 0 ), // {<ecx|rcx>, rel8} - ROW(1, 1, 1, 0, 128, 0 , 0 , 0 , 0 , 0 ), // #306 {rel8|rel32|r64|m64|mem} + ROW(1, 1, 1, 0, 128, 0 , 0 , 0 , 0 , 0 ), // #309 {rel8|rel32|r64|m64|mem} ROW(1, 1, 0, 0, 129, 0 , 0 , 0 , 0 , 0 ), // {rel16|r32|m32|mem} - ROW(2, 1, 1, 0, 106, 130, 0 , 0 , 0 , 0 ), // #308 {k, k|m8|mem|r32} + ROW(2, 1, 1, 0, 106, 130, 0 , 0 , 0 , 0 ), // #311 {k, k|m8|mem|r32} ROW(2, 1, 1, 0, 131, 106, 0 , 0 , 0 , 0 ), // {m8|mem|r32, k} - ROW(2, 1, 1, 0, 106, 132, 0 , 0 , 0 , 0 ), // #310 {k, k|m32|mem|r32} + ROW(2, 1, 1, 0, 106, 132, 0 , 0 , 0 , 0 ), // #313 {k, k|m32|mem|r32} ROW(2, 1, 1, 0, 28 , 106, 0 , 0 , 0 , 0 ), // {m32|mem|r32, k} - ROW(2, 1, 1, 0, 106, 133, 0 , 0 , 0 , 0 ), // #312 {k, k|m64|mem|r64} + ROW(2, 1, 1, 0, 106, 133, 0 , 0 , 0 , 0 ), // #315 {k, k|m64|mem|r64} ROW(2, 1, 1, 0, 15 , 106, 0 , 0 , 0 , 0 ), // {m64|mem|r64, k} - ROW(2, 1, 1, 0, 106, 134, 0 , 0 , 0 , 0 ), // #314 {k, k|m16|mem|r32} + ROW(2, 1, 1, 0, 106, 134, 0 , 0 , 0 , 0 ), // #317 {k, k|m16|mem|r32} ROW(2, 1, 1, 0, 135, 106, 0 , 0 , 0 , 0 ), // {m16|mem|r32, k} - ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #316 {r16, r16|m16|mem} + ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #319 {r16, r16|m16|mem} ROW(2, 1, 1, 0, 6 , 135, 0 , 0 , 0 , 0 ), // {r32, r32|m16|mem} - ROW(2, 1, 0, 0, 136, 137, 0 , 0 , 0 , 0 ), // #318 {i16, i16|i32} + ROW(2, 1, 0, 0, 136, 137, 0 , 0 , 0 , 0 ), // #321 {i16, i16|i32} ROW(1, 1, 1, 0, 138, 0 , 0 , 0 , 0 , 0 ), // {m32|m48|m80|mem} - ROW(2, 1, 0, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #320 {r16, m32|mem} + ROW(2, 1, 0, 0, 4 , 29 , 0 , 0 , 0 , 0 ), // #323 {r16, m32|mem} ROW(2, 1, 0, 0, 6 , 101, 0 , 0 , 0 , 0 ), // {r32, m48|mem} - ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #322 {r16, r16|m16|mem} + ROW(2, 1, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #325 {r16, r16|m16|mem} ROW(2, 1, 1, 0, 139, 135, 0 , 0 , 0 , 0 ), // {r32|r64, r32|m16|mem} - ROW(2, 1, 1, 0, 64 , 28 , 0 , 0 , 0 , 0 ), // #324 {mm|xmm, r32|m32|mem} + ROW(2, 1, 1, 0, 64 , 28 , 0 , 0 , 0 , 0 ), // #327 {mm|xmm, r32|m32|mem} ROW(2, 1, 1, 0, 28 , 64 , 0 , 0 , 0 , 0 ), // {r32|m32|mem, mm|xmm} - ROW(2, 1, 1, 0, 50 , 109, 0 , 0 , 0 , 0 ), // #326 {xmm, xmm|m32|mem} + ROW(2, 1, 1, 0, 50 , 107, 0 , 0 , 0 , 0 ), // #329 {xmm, xmm|m32|mem} ROW(2, 1, 1, 0, 29 , 50 , 0 , 0 , 0 , 0 ), // {m32|mem, xmm} - ROW(2, 1, 1, 0, 4 , 9 , 0 , 0 , 0 , 0 ), // #328 {r16, r8lo|r8hi|m8} + ROW(2, 1, 1, 0, 4 , 9 , 0 , 0 , 0 , 0 ), // #331 {r16, r8lo|r8hi|m8} ROW(2, 1, 1, 0, 139, 140, 0 , 0 , 0 , 0 ), // {r32|r64, r8lo|r8hi|m8|r16|m16} - ROW(4, 1, 1, 1, 6 , 6 , 28 , 35 , 0 , 0 ), // #330 {r32, r32, r32|m32|mem, <edx>} + ROW(2, 0, 1, 0, 4 , 27 , 0 , 0 , 0 , 0 ), // #333 {r16, r16|m16|mem} + ROW(2, 0, 1, 0, 139, 28 , 0 , 0 , 0 , 0 ), // {r32|r64, r32|m32|mem} + ROW(4, 1, 1, 1, 6 , 6 , 28 , 35 , 0 , 0 ), // #335 {r32, r32, r32|m32|mem, <edx>} ROW(4, 0, 1, 1, 8 , 8 , 15 , 37 , 0 , 0 ), // {r64, r64, r64|m64|mem, <rdx>} - ROW(2, 1, 1, 0, 62 , 141, 0 , 0 , 0 , 0 ), // #332 {mm, mm|m64|mem} + ROW(2, 1, 1, 0, 62 , 141, 0 , 0 , 0 , 0 ), // #337 {mm, mm|m64|mem} ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem} - ROW(3, 1, 1, 0, 62 , 141, 10 , 0 , 0 , 0 ), // #334 {mm, mm|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 62 , 141, 10 , 0 , 0 , 0 ), // #339 {mm, mm|m64|mem, i8|u8} ROW(3, 1, 1, 0, 50 , 51 , 10 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem, i8|u8} - ROW(3, 1, 1, 0, 6 , 64 , 10 , 0 , 0 , 0 ), // #336 {r32, mm|xmm, i8|u8} + ROW(3, 1, 1, 0, 6 , 64 , 10 , 0 , 0 , 0 ), // #341 {r32, mm|xmm, i8|u8} ROW(3, 1, 1, 0, 21 , 50 , 10 , 0 , 0 , 0 ), // {m16|mem, xmm, i8|u8} - ROW(2, 1, 1, 0, 62 , 142, 0 , 0 , 0 , 0 ), // #338 {mm, i8|u8|mm|m64|mem} + ROW(2, 1, 1, 0, 62 , 142, 0 , 0 , 0 , 0 ), // #343 {mm, i8|u8|mm|m64|mem} ROW(2, 1, 1, 0, 50 , 59 , 0 , 0 , 0 , 0 ), // {xmm, i8|u8|xmm|m128|mem} - ROW(2, 1, 1, 0, 62 , 143, 0 , 0 , 0 , 0 ), // #340 {mm, mm|m32|mem} + ROW(2, 1, 1, 0, 62 , 143, 0 , 0 , 0 , 0 ), // #345 {mm, mm|m32|mem} ROW(2, 1, 1, 0, 50 , 51 , 0 , 0 , 0 , 0 ), // {xmm, xmm|m128|mem} - ROW(1, 1, 0, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #342 {r32} - ROW(1, 0, 1, 0, 8 , 0 , 0 , 0 , 0 , 0 ), // #343 {r64} - ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #344 {} + ROW(1, 1, 0, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #347 {r32} + ROW(1, 0, 1, 0, 8 , 0 , 0 , 0 , 0 , 0 ), // #348 {r64} + ROW(0, 1, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #349 {} ROW(1, 1, 1, 0, 144, 0 , 0 , 0 , 0 , 0 ), // {u16} - ROW(3, 1, 1, 0, 6 , 28 , 10 , 0 , 0 , 0 ), // #346 {r32, r32|m32|mem, i8|u8} + ROW(3, 1, 1, 0, 6 , 28 , 10 , 0 , 0 , 0 ), // #351 {r32, r32|m32|mem, i8|u8} ROW(3, 0, 1, 0, 8 , 15 , 10 , 0 , 0 , 0 ), // {r64, r64|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 51 , 50 , 0 , 0 ), // #348 {xmm, xmm, xmm|m128|mem, xmm} + ROW(4, 1, 1, 0, 50 , 50 , 51 , 50 , 0 , 0 ), // #353 {xmm, xmm, xmm|m128|mem, xmm} ROW(4, 1, 1, 0, 53 , 53 , 54 , 53 , 0 , 0 ), // {ymm, ymm, ymm|m256|mem, ymm} - ROW(2, 1, 1, 0, 50 , 145, 0 , 0 , 0 , 0 ), // #350 {xmm, xmm|m128|ymm|m256} + ROW(2, 1, 1, 0, 50 , 145, 0 , 0 , 0 , 0 ), // #355 {xmm, xmm|m128|ymm|m256} ROW(2, 1, 1, 0, 53 , 57 , 0 , 0 , 0 , 0 ), // {ymm, zmm|m512|mem} - ROW(4, 1, 1, 0, 50 , 50 , 50 , 65 , 0 , 0 ), // #352 {xmm, xmm, xmm, xmm|m64|mem} + ROW(4, 1, 1, 0, 50 , 50 , 50 , 65 , 0 , 0 ), // #357 {xmm, xmm, xmm, xmm|m64|mem} ROW(4, 1, 1, 0, 50 , 50 , 30 , 50 , 0 , 0 ), // {xmm, xmm, m64|mem, xmm} - ROW(4, 1, 1, 0, 50 , 50 , 50 , 109, 0 , 0 ), // #354 {xmm, xmm, xmm, xmm|m32|mem} + ROW(4, 1, 1, 0, 50 , 50 , 50 , 107, 0 , 0 ), // #359 {xmm, xmm, xmm, xmm|m32|mem} ROW(4, 1, 1, 0, 50 , 50 , 29 , 50 , 0 , 0 ), // {xmm, xmm, m32|mem, xmm} - ROW(4, 1, 1, 0, 53 , 53 , 51 , 10 , 0 , 0 ), // #356 {ymm, ymm, xmm|m128|mem, i8|u8} + ROW(4, 1, 1, 0, 53 , 53 , 51 , 10 , 0 , 0 ), // #361 {ymm, ymm, xmm|m128|mem, i8|u8} ROW(4, 1, 1, 0, 56 , 56 , 51 , 10 , 0 , 0 ), // {zmm, zmm, xmm|m128|mem, i8|u8} - ROW(1, 1, 0, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #358 {<eax>} - ROW(1, 0, 1, 1, 38 , 0 , 0 , 0 , 0 , 0 ), // #359 {<rax>} - ROW(2, 1, 1, 0, 28 , 50 , 0 , 0 , 0 , 0 ), // #360 {r32|m32|mem, xmm} + ROW(1, 1, 0, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #363 {<eax>} + ROW(1, 0, 1, 1, 38 , 0 , 0 , 0 , 0 , 0 ), // #364 {<rax>} + ROW(2, 1, 1, 0, 28 , 50 , 0 , 0 , 0 , 0 ), // #365 {r32|m32|mem, xmm} ROW(2, 1, 1, 0, 50 , 28 , 0 , 0 , 0 , 0 ), // {xmm, r32|m32|mem} - ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #362 {m64|mem, xmm} + ROW(2, 1, 1, 0, 30 , 50 , 0 , 0 , 0 , 0 ), // #367 {m64|mem, xmm} ROW(3, 1, 1, 0, 50 , 50 , 30 , 0 , 0 , 0 ), // {xmm, xmm, m64|mem} - ROW(2, 1, 0, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // #364 {r32|m32|mem, r32} + ROW(2, 1, 1, 0, 135, 50 , 0 , 0 , 0 , 0 ), // #369 {r32|m16|mem, xmm} + ROW(2, 1, 1, 0, 50 , 135, 0 , 0 , 0 , 0 ), // {xmm, r32|m16|mem} + ROW(2, 1, 0, 0, 28 , 6 , 0 , 0 , 0 , 0 ), // #371 {r32|m32|mem, r32} ROW(2, 0, 1, 0, 15 , 8 , 0 , 0 , 0 , 0 ), // {r64|m64|mem, r64} - ROW(2, 1, 0, 0, 6 , 28 , 0 , 0 , 0 , 0 ), // #366 {r32, r32|m32|mem} + ROW(2, 1, 0, 0, 6 , 28 , 0 , 0 , 0 , 0 ), // #373 {r32, r32|m32|mem} ROW(2, 0, 1, 0, 8 , 15 , 0 , 0 , 0 , 0 ), // {r64, r64|m64|mem} - ROW(3, 1, 1, 0, 50 , 50 , 59 , 0 , 0 , 0 ), // #368 {xmm, xmm, xmm|m128|mem|i8|u8} + ROW(3, 1, 1, 0, 50 , 50 , 59 , 0 , 0 , 0 ), // #375 {xmm, xmm, xmm|m128|mem|i8|u8} ROW(3, 1, 1, 0, 50 , 52 , 146, 0 , 0 , 0 ), // {xmm, m128|mem, i8|u8|xmm} - ROW(2, 1, 1, 0, 67 , 96 , 0 , 0 , 0 , 0 ), // #370 {vm32x, xmm|ymm} + ROW(2, 1, 1, 0, 67 , 96 , 0 , 0 , 0 , 0 ), // #377 {vm32x, xmm|ymm} ROW(2, 1, 1, 0, 68 , 56 , 0 , 0 , 0 , 0 ), // {vm32y, zmm} - ROW(2, 1, 1, 0, 107, 50 , 0 , 0 , 0 , 0 ), // #372 {vm64x|vm64y, xmm} + ROW(2, 1, 1, 0, 108, 50 , 0 , 0 , 0 , 0 ), // #379 {vm64x|vm64y, xmm} ROW(2, 1, 1, 0, 72 , 53 , 0 , 0 , 0 , 0 ), // {vm64z, ymm} - ROW(3, 1, 1, 0, 50 , 50 , 51 , 0 , 0 , 0 ), // #374 {xmm, xmm, xmm|m128|mem} + ROW(3, 1, 1, 0, 50 , 50 , 51 , 0 , 0 , 0 ), // #381 {xmm, xmm, xmm|m128|mem} ROW(3, 1, 1, 0, 50 , 52 , 50 , 0 , 0 , 0 ), // {xmm, m128|mem, xmm} - ROW(1, 1, 0, 1, 33 , 0 , 0 , 0 , 0 , 0 ), // #376 {<ax>} - ROW(2, 1, 0, 1, 33 , 10 , 0 , 0 , 0 , 0 ), // #377 {<ax>, i8|u8} - ROW(2, 1, 0, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // #378 {r16|m16|mem, r16} - ROW(3, 1, 1, 1, 50 , 51 , 147, 0 , 0 , 0 ), // #379 {xmm, xmm|m128|mem, <xmm0>} - ROW(2, 1, 1, 0, 111, 148, 0 , 0 , 0 , 0 ), // #380 {bnd, mib} - ROW(2, 1, 1, 0, 111, 113, 0 , 0 , 0 , 0 ), // #381 {bnd, mem} - ROW(2, 1, 1, 0, 148, 111, 0 , 0 , 0 , 0 ), // #382 {mib, bnd} - ROW(1, 1, 1, 0, 149, 0 , 0 , 0 , 0 , 0 ), // #383 {r16|r32|r64} - ROW(1, 1, 1, 1, 33 , 0 , 0 , 0 , 0 , 0 ), // #384 {<ax>} - ROW(2, 1, 1, 2, 35 , 36 , 0 , 0 , 0 , 0 ), // #385 {<edx>, <eax>} - ROW(1, 1, 1, 0, 150, 0 , 0 , 0 , 0 , 0 ), // #386 {mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} - ROW(1, 1, 1, 0, 30 , 0 , 0 , 0 , 0 , 0 ), // #387 {m64|mem} - ROW(0, 0, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #388 {} - ROW(1, 1, 1, 1, 151, 0 , 0 , 0 , 0 , 0 ), // #389 {<ds:[mem|m512|memBase|zax]>} - ROW(3, 1, 1, 0, 50 , 65 , 10 , 0 , 0 , 0 ), // #390 {xmm, xmm|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 109, 10 , 0 , 0 , 0 ), // #391 {xmm, xmm|m32|mem, i8|u8} - ROW(5, 0, 1, 4, 52 , 37 , 38 , 152, 153, 0 ), // #392 {m128|mem, <rdx>, <rax>, <rcx>, <rbx>} - ROW(5, 1, 1, 4, 30 , 35 , 36 , 121, 154, 0 ), // #393 {m64|mem, <edx>, <eax>, <ecx>, <ebx>} - ROW(4, 1, 1, 4, 36 , 154, 121, 35 , 0 , 0 ), // #394 {<eax>, <ebx>, <ecx>, <edx>} - ROW(2, 0, 1, 2, 37 , 38 , 0 , 0 , 0 , 0 ), // #395 {<rdx>, <rax>} - ROW(2, 1, 1, 0, 62 , 51 , 0 , 0 , 0 , 0 ), // #396 {mm, xmm|m128|mem} - ROW(2, 1, 1, 0, 50 , 141, 0 , 0 , 0 , 0 ), // #397 {xmm, mm|m64|mem} - ROW(2, 1, 1, 0, 62 , 65 , 0 , 0 , 0 , 0 ), // #398 {mm, xmm|m64|mem} - ROW(2, 1, 1, 0, 139, 65 , 0 , 0 , 0 , 0 ), // #399 {r32|r64, xmm|m64|mem} - ROW(2, 1, 1, 0, 50 , 155, 0 , 0 , 0 , 0 ), // #400 {xmm, r32|m32|mem|r64|m64} - ROW(2, 1, 1, 0, 139, 109, 0 , 0 , 0 , 0 ), // #401 {r32|r64, xmm|m32|mem} - ROW(2, 1, 1, 2, 34 , 33 , 0 , 0 , 0 , 0 ), // #402 {<dx>, <ax>} - ROW(1, 1, 1, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #403 {<eax>} - ROW(2, 1, 1, 0, 12 , 10 , 0 , 0 , 0 , 0 ), // #404 {i16|u16, i8|u8} - ROW(3, 1, 1, 0, 28 , 50 , 10 , 0 , 0 , 0 ), // #405 {r32|m32|mem, xmm, i8|u8} - ROW(1, 1, 1, 0, 102, 0 , 0 , 0 , 0 , 0 ), // #406 {m80|mem} - ROW(1, 1, 1, 0, 156, 0 , 0 , 0 , 0 , 0 ), // #407 {m16|m32} - ROW(1, 1, 1, 0, 157, 0 , 0 , 0 , 0 , 0 ), // #408 {m16|m32|m64} - ROW(1, 1, 1, 0, 158, 0 , 0 , 0 , 0 , 0 ), // #409 {m32|m64|m80|st} - ROW(1, 1, 1, 0, 21 , 0 , 0 , 0 , 0 , 0 ), // #410 {m16|mem} - ROW(1, 1, 1, 0, 113, 0 , 0 , 0 , 0 , 0 ), // #411 {mem} - ROW(1, 1, 1, 0, 159, 0 , 0 , 0 , 0 , 0 ), // #412 {ax|m16|mem} - ROW(1, 0, 1, 0, 113, 0 , 0 , 0 , 0 , 0 ), // #413 {mem} - ROW(2, 1, 1, 1, 10 , 36 , 0 , 0 , 0 , 0 ), // #414 {i8|u8, <eax>} - ROW(2, 1, 1, 0, 160, 161, 0 , 0 , 0 , 0 ), // #415 {al|ax|eax, i8|u8|dx} - ROW(1, 1, 1, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #416 {r32} - ROW(2, 1, 1, 0, 162, 163, 0 , 0 , 0 , 0 ), // #417 {es:[m8|memBase|zdi|m16|m32], dx} - ROW(1, 1, 1, 0, 10 , 0 , 0 , 0 , 0 , 0 ), // #418 {i8|u8} - ROW(0, 1, 0, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #419 {} - ROW(3, 1, 1, 0, 106, 106, 106, 0 , 0 , 0 ), // #420 {k, k, k} - ROW(2, 1, 1, 0, 106, 106, 0 , 0 , 0 , 0 ), // #421 {k, k} - ROW(3, 1, 1, 0, 106, 106, 10 , 0 , 0 , 0 ), // #422 {k, k, i8|u8} - ROW(1, 1, 1, 1, 164, 0 , 0 , 0 , 0 , 0 ), // #423 {<ah>} - ROW(1, 1, 1, 0, 29 , 0 , 0 , 0 , 0 , 0 ), // #424 {m32|mem} - ROW(1, 0, 1, 0, 58 , 0 , 0 , 0 , 0 , 0 ), // #425 {m512|mem} - ROW(2, 1, 1, 0, 149, 150, 0 , 0 , 0 , 0 ), // #426 {r16|r32|r64, mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} - ROW(1, 1, 1, 0, 27 , 0 , 0 , 0 , 0 , 0 ), // #427 {r16|m16|mem} - ROW(1, 1, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // #428 {r32|r64} - ROW(3, 1, 1, 0, 139, 28 , 14 , 0 , 0 , 0 ), // #429 {r32|r64, r32|m32|mem, i32|u32} - ROW(3, 1, 1, 1, 50 , 50 , 165, 0 , 0 , 0 ), // #430 {xmm, xmm, <ds:[mem|m128|memBase|zdi]>} - ROW(3, 1, 1, 1, 62 , 62 , 166, 0 , 0 , 0 ), // #431 {mm, mm, <ds:[mem|m64|memBase|zdi]>} - ROW(3, 1, 1, 3, 167, 121, 35 , 0 , 0 , 0 ), // #432 {<ds:[mem|memBase|zax]>, <ecx>, <edx>} - ROW(2, 1, 1, 0, 119, 58 , 0 , 0 , 0 , 0 ), // #433 {es:[mem|m512|memBase], m512|mem} - ROW(2, 1, 1, 0, 62 , 50 , 0 , 0 , 0 , 0 ), // #434 {mm, xmm} - ROW(2, 1, 1, 0, 6 , 50 , 0 , 0 , 0 , 0 ), // #435 {r32, xmm} - ROW(2, 1, 1, 0, 30 , 62 , 0 , 0 , 0 , 0 ), // #436 {m64|mem, mm} - ROW(2, 1, 1, 0, 50 , 62 , 0 , 0 , 0 , 0 ), // #437 {xmm, mm} - ROW(2, 0, 1, 0, 149, 28 , 0 , 0 , 0 , 0 ), // #438 {r16|r32|r64, r32|m32|mem} - ROW(2, 1, 1, 2, 36 , 121, 0 , 0 , 0 , 0 ), // #439 {<eax>, <ecx>} - ROW(3, 1, 1, 3, 36 , 121, 154, 0 , 0 , 0 ), // #440 {<eax>, <ecx>, <ebx>} - ROW(2, 1, 1, 0, 168, 160, 0 , 0 , 0 , 0 ), // #441 {u8|dx, al|ax|eax} - ROW(2, 1, 1, 0, 163, 169, 0 , 0 , 0 , 0 ), // #442 {dx, ds:[m8|memBase|zsi|m16|m32]} - ROW(6, 1, 1, 3, 50 , 51 , 10 , 121, 36 , 35 ), // #443 {xmm, xmm|m128|mem, i8|u8, <ecx>, <eax>, <edx>} - ROW(6, 1, 1, 3, 50 , 51 , 10 , 147, 36 , 35 ), // #444 {xmm, xmm|m128|mem, i8|u8, <xmm0>, <eax>, <edx>} - ROW(4, 1, 1, 1, 50 , 51 , 10 , 121, 0 , 0 ), // #445 {xmm, xmm|m128|mem, i8|u8, <ecx>} - ROW(4, 1, 1, 1, 50 , 51 , 10 , 147, 0 , 0 ), // #446 {xmm, xmm|m128|mem, i8|u8, <xmm0>} - ROW(3, 1, 1, 0, 131, 50 , 10 , 0 , 0 , 0 ), // #447 {r32|m8|mem, xmm, i8|u8} - ROW(3, 0, 1, 0, 15 , 50 , 10 , 0 , 0 , 0 ), // #448 {r64|m64|mem, xmm, i8|u8} - ROW(3, 1, 1, 0, 50 , 131, 10 , 0 , 0 , 0 ), // #449 {xmm, r32|m8|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 28 , 10 , 0 , 0 , 0 ), // #450 {xmm, r32|m32|mem, i8|u8} - ROW(3, 0, 1, 0, 50 , 15 , 10 , 0 , 0 , 0 ), // #451 {xmm, r64|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 64 , 135, 10 , 0 , 0 , 0 ), // #452 {mm|xmm, r32|m16|mem, i8|u8} - ROW(2, 1, 1, 0, 6 , 64 , 0 , 0 , 0 , 0 ), // #453 {r32, mm|xmm} - ROW(2, 1, 1, 0, 50 , 10 , 0 , 0 , 0 , 0 ), // #454 {xmm, i8|u8} - ROW(1, 1, 1, 0, 155, 0 , 0 , 0 , 0 , 0 ), // #455 {r32|m32|mem|r64|m64} - ROW(2, 1, 1, 0, 31 , 103, 0 , 0 , 0 , 0 ), // #456 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem, cl|i8|u8} - ROW(1, 0, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // #457 {r32|r64} - ROW(3, 1, 1, 3, 35 , 36 , 121, 0 , 0 , 0 ), // #458 {<edx>, <eax>, <ecx>} - ROW(1, 1, 1, 0, 1 , 0 , 0 , 0 , 0 , 0 ), // #459 {r8lo|r8hi|m8|mem} - ROW(1, 1, 1, 0, 170, 0 , 0 , 0 , 0 , 0 ), // #460 {r16|m16|mem|r32|r64} - ROW(3, 0, 1, 0, 171, 171, 171, 0 , 0 , 0 ), // #461 {tmm, tmm, tmm} - ROW(2, 0, 1, 0, 171, 113, 0 , 0 , 0 , 0 ), // #462 {tmm, tmem} - ROW(2, 0, 1, 0, 113, 171, 0 , 0 , 0 , 0 ), // #463 {tmem, tmm} - ROW(1, 0, 1, 0, 171, 0 , 0 , 0 , 0 , 0 ), // #464 {tmm} - ROW(3, 1, 1, 2, 6 , 35 , 36 , 0 , 0 , 0 ), // #465 {r32, <edx>, <eax>} - ROW(1, 1, 1, 0, 172, 0 , 0 , 0 , 0 , 0 ), // #466 {ds:[mem|memBase]} - ROW(6, 1, 1, 0, 56 , 56 , 56 , 56 , 56 , 52 ), // #467 {zmm, zmm, zmm, zmm, zmm, m128|mem} - ROW(6, 1, 1, 0, 50 , 50 , 50 , 50 , 50 , 52 ), // #468 {xmm, xmm, xmm, xmm, xmm, m128|mem} - ROW(3, 1, 1, 0, 50 , 50 , 65 , 0 , 0 , 0 ), // #469 {xmm, xmm, xmm|m64|mem} - ROW(3, 1, 1, 0, 50 , 50 , 109, 0 , 0 , 0 ), // #470 {xmm, xmm, xmm|m32|mem} - ROW(2, 1, 1, 0, 53 , 52 , 0 , 0 , 0 , 0 ), // #471 {ymm, m128|mem} - ROW(2, 1, 1, 0, 173, 65 , 0 , 0 , 0 , 0 ), // #472 {ymm|zmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 173, 52 , 0 , 0 , 0 , 0 ), // #473 {ymm|zmm, m128|mem} - ROW(2, 1, 1, 0, 56 , 55 , 0 , 0 , 0 , 0 ), // #474 {zmm, m256|mem} - ROW(2, 1, 1, 0, 174, 65 , 0 , 0 , 0 , 0 ), // #475 {xmm|ymm|zmm, xmm|m64|mem} - ROW(2, 1, 1, 0, 174, 109, 0 , 0 , 0 , 0 ), // #476 {xmm|ymm|zmm, m32|mem|xmm} - ROW(4, 1, 1, 0, 104, 50 , 65 , 10 , 0 , 0 ), // #477 {xmm|k, xmm, xmm|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 104, 50 , 109, 10 , 0 , 0 ), // #478 {xmm|k, xmm, xmm|m32|mem, i8|u8} - ROW(3, 1, 1, 0, 50 , 50 , 155, 0 , 0 , 0 ), // #479 {xmm, xmm, r32|m32|mem|r64|m64} - ROW(3, 1, 1, 0, 51 , 173, 10 , 0 , 0 , 0 ), // #480 {xmm|m128|mem, ymm|zmm, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 65 , 10 , 0 , 0 ), // #481 {xmm, xmm, xmm|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 109, 10 , 0 , 0 ), // #482 {xmm, xmm, xmm|m32|mem, i8|u8} - ROW(3, 1, 1, 0, 106, 175, 10 , 0 , 0 , 0 ), // #483 {k, xmm|m128|ymm|m256|zmm|m512, i8|u8} - ROW(3, 1, 1, 0, 106, 65 , 10 , 0 , 0 , 0 ), // #484 {k, xmm|m64|mem, i8|u8} - ROW(3, 1, 1, 0, 106, 109, 10 , 0 , 0 , 0 ), // #485 {k, xmm|m32|mem, i8|u8} - ROW(1, 1, 1, 0, 68 , 0 , 0 , 0 , 0 , 0 ), // #486 {vm32y} - ROW(1, 1, 1, 0, 69 , 0 , 0 , 0 , 0 , 0 ), // #487 {vm32z} - ROW(1, 1, 1, 0, 72 , 0 , 0 , 0 , 0 , 0 ), // #488 {vm64z} - ROW(4, 1, 1, 0, 56 , 56 , 54 , 10 , 0 , 0 ), // #489 {zmm, zmm, ymm|m256|mem, i8|u8} - ROW(2, 1, 1, 0, 6 , 96 , 0 , 0 , 0 , 0 ), // #490 {r32, xmm|ymm} - ROW(2, 1, 1, 0, 174, 176, 0 , 0 , 0 , 0 ), // #491 {xmm|ymm|zmm, xmm|m8|mem|r32} - ROW(2, 1, 1, 0, 174, 177, 0 , 0 , 0 , 0 ), // #492 {xmm|ymm|zmm, xmm|m32|mem|r32} - ROW(2, 1, 1, 0, 174, 106, 0 , 0 , 0 , 0 ), // #493 {xmm|ymm|zmm, k} - ROW(2, 1, 1, 0, 174, 178, 0 , 0 , 0 , 0 ), // #494 {xmm|ymm|zmm, xmm|m16|mem|r32} - ROW(3, 1, 1, 0, 135, 50 , 10 , 0 , 0 , 0 ), // #495 {r32|m16|mem, xmm, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 131, 10 , 0 , 0 ), // #496 {xmm, xmm, r32|m8|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 28 , 10 , 0 , 0 ), // #497 {xmm, xmm, r32|m32|mem, i8|u8} - ROW(4, 0, 1, 0, 50 , 50 , 15 , 10 , 0 , 0 ), // #498 {xmm, xmm, r64|m64|mem, i8|u8} - ROW(4, 1, 1, 0, 50 , 50 , 135, 10 , 0 , 0 ), // #499 {xmm, xmm, r32|m16|mem, i8|u8} - ROW(2, 1, 1, 0, 106, 174, 0 , 0 , 0 , 0 ), // #500 {k, xmm|ymm|zmm} - ROW(1, 1, 1, 0, 124, 0 , 0 , 0 , 0 , 0 ), // #501 {rel16|rel32} - ROW(3, 1, 1, 2, 113, 35 , 36 , 0 , 0 , 0 ), // #502 {mem, <edx>, <eax>} - ROW(3, 0, 1, 2, 113, 35 , 36 , 0 , 0 , 0 ) // #503 {mem, <edx>, <eax>} + ROW(1, 1, 0, 1, 33 , 0 , 0 , 0 , 0 , 0 ), // #383 {<ax>} + ROW(2, 1, 0, 1, 33 , 10 , 0 , 0 , 0 , 0 ), // #384 {<ax>, i8|u8} + ROW(2, 1, 0, 0, 27 , 4 , 0 , 0 , 0 , 0 ), // #385 {r16|m16|mem, r16} + ROW(3, 1, 1, 1, 50 , 51 , 147, 0 , 0 , 0 ), // #386 {xmm, xmm|m128|mem, <xmm0>} + ROW(2, 1, 1, 0, 111, 148, 0 , 0 , 0 , 0 ), // #387 {bnd, mib} + ROW(2, 1, 1, 0, 111, 113, 0 , 0 , 0 , 0 ), // #388 {bnd, mem} + ROW(2, 1, 1, 0, 148, 111, 0 , 0 , 0 , 0 ), // #389 {mib, bnd} + ROW(1, 1, 1, 0, 149, 0 , 0 , 0 , 0 , 0 ), // #390 {r16|r32|r64} + ROW(1, 1, 1, 1, 33 , 0 , 0 , 0 , 0 , 0 ), // #391 {<ax>} + ROW(2, 1, 1, 2, 35 , 36 , 0 , 0 , 0 , 0 ), // #392 {<edx>, <eax>} + ROW(1, 1, 1, 0, 150, 0 , 0 , 0 , 0 , 0 ), // #393 {mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} + ROW(1, 1, 1, 0, 30 , 0 , 0 , 0 , 0 , 0 ), // #394 {m64|mem} + ROW(0, 0, 1, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #395 {} + ROW(1, 1, 1, 1, 151, 0 , 0 , 0 , 0 , 0 ), // #396 {<ds:[mem|m512|memBase|zax]>} + ROW(3, 1, 1, 0, 50 , 65 , 10 , 0 , 0 , 0 ), // #397 {xmm, xmm|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 50 , 107, 10 , 0 , 0 , 0 ), // #398 {xmm, xmm|m32|mem, i8|u8} + ROW(5, 0, 1, 4, 52 , 37 , 38 , 152, 153, 0 ), // #399 {m128|mem, <rdx>, <rax>, <rcx>, <rbx>} + ROW(5, 1, 1, 4, 30 , 35 , 36 , 121, 154, 0 ), // #400 {m64|mem, <edx>, <eax>, <ecx>, <ebx>} + ROW(4, 1, 1, 4, 36 , 154, 121, 35 , 0 , 0 ), // #401 {<eax>, <ebx>, <ecx>, <edx>} + ROW(2, 0, 1, 2, 37 , 38 , 0 , 0 , 0 , 0 ), // #402 {<rdx>, <rax>} + ROW(2, 1, 1, 0, 62 , 51 , 0 , 0 , 0 , 0 ), // #403 {mm, xmm|m128|mem} + ROW(2, 1, 1, 0, 50 , 141, 0 , 0 , 0 , 0 ), // #404 {xmm, mm|m64|mem} + ROW(2, 1, 1, 0, 62 , 65 , 0 , 0 , 0 , 0 ), // #405 {mm, xmm|m64|mem} + ROW(2, 1, 1, 0, 139, 65 , 0 , 0 , 0 , 0 ), // #406 {r32|r64, xmm|m64|mem} + ROW(2, 1, 1, 0, 50 , 155, 0 , 0 , 0 , 0 ), // #407 {xmm, r32|m32|mem|r64|m64} + ROW(2, 1, 1, 0, 139, 107, 0 , 0 , 0 , 0 ), // #408 {r32|r64, xmm|m32|mem} + ROW(2, 1, 1, 2, 34 , 33 , 0 , 0 , 0 , 0 ), // #409 {<dx>, <ax>} + ROW(1, 1, 1, 1, 36 , 0 , 0 , 0 , 0 , 0 ), // #410 {<eax>} + ROW(2, 1, 1, 0, 12 , 10 , 0 , 0 , 0 , 0 ), // #411 {i16|u16, i8|u8} + ROW(3, 1, 1, 0, 28 , 50 , 10 , 0 , 0 , 0 ), // #412 {r32|m32|mem, xmm, i8|u8} + ROW(1, 1, 1, 0, 102, 0 , 0 , 0 , 0 , 0 ), // #413 {m80|mem} + ROW(1, 1, 1, 0, 156, 0 , 0 , 0 , 0 , 0 ), // #414 {m16|m32} + ROW(1, 1, 1, 0, 157, 0 , 0 , 0 , 0 , 0 ), // #415 {m16|m32|m64} + ROW(1, 1, 1, 0, 158, 0 , 0 , 0 , 0 , 0 ), // #416 {m32|m64|m80|st} + ROW(1, 1, 1, 0, 21 , 0 , 0 , 0 , 0 , 0 ), // #417 {m16|mem} + ROW(1, 1, 1, 0, 113, 0 , 0 , 0 , 0 , 0 ), // #418 {mem} + ROW(1, 1, 1, 0, 159, 0 , 0 , 0 , 0 , 0 ), // #419 {ax|m16|mem} + ROW(1, 0, 1, 0, 113, 0 , 0 , 0 , 0 , 0 ), // #420 {mem} + ROW(2, 1, 1, 1, 10 , 36 , 0 , 0 , 0 , 0 ), // #421 {i8|u8, <eax>} + ROW(2, 1, 1, 0, 160, 161, 0 , 0 , 0 , 0 ), // #422 {al|ax|eax, i8|u8|dx} + ROW(1, 1, 1, 0, 6 , 0 , 0 , 0 , 0 , 0 ), // #423 {r32} + ROW(2, 1, 1, 0, 162, 163, 0 , 0 , 0 , 0 ), // #424 {es:[m8|memBase|zdi|m16|m32], dx} + ROW(1, 1, 1, 0, 10 , 0 , 0 , 0 , 0 , 0 ), // #425 {i8|u8} + ROW(0, 1, 0, 0, 0 , 0 , 0 , 0 , 0 , 0 ), // #426 {} + ROW(3, 1, 1, 0, 106, 106, 106, 0 , 0 , 0 ), // #427 {k, k, k} + ROW(2, 1, 1, 0, 106, 106, 0 , 0 , 0 , 0 ), // #428 {k, k} + ROW(3, 1, 1, 0, 106, 106, 10 , 0 , 0 , 0 ), // #429 {k, k, i8|u8} + ROW(1, 1, 1, 1, 164, 0 , 0 , 0 , 0 , 0 ), // #430 {<ah>} + ROW(1, 1, 1, 0, 29 , 0 , 0 , 0 , 0 , 0 ), // #431 {m32|mem} + ROW(1, 0, 1, 0, 58 , 0 , 0 , 0 , 0 , 0 ), // #432 {m512|mem} + ROW(2, 1, 1, 0, 149, 150, 0 , 0 , 0 , 0 ), // #433 {r16|r32|r64, mem|m8|m16|m32|m48|m64|m80|m128|m256|m512|m1024} + ROW(1, 1, 1, 0, 27 , 0 , 0 , 0 , 0 , 0 ), // #434 {r16|m16|mem} + ROW(1, 1, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // #435 {r32|r64} + ROW(3, 1, 1, 0, 139, 28 , 14 , 0 , 0 , 0 ), // #436 {r32|r64, r32|m32|mem, i32|u32} + ROW(3, 1, 1, 1, 50 , 50 , 165, 0 , 0 , 0 ), // #437 {xmm, xmm, <ds:[mem|m128|memBase|zdi]>} + ROW(3, 1, 1, 1, 62 , 62 , 166, 0 , 0 , 0 ), // #438 {mm, mm, <ds:[mem|m64|memBase|zdi]>} + ROW(3, 1, 1, 3, 167, 121, 35 , 0 , 0 , 0 ), // #439 {<ds:[mem|memBase|zax]>, <ecx>, <edx>} + ROW(2, 1, 1, 0, 119, 58 , 0 , 0 , 0 , 0 ), // #440 {es:[mem|m512|memBase], m512|mem} + ROW(2, 1, 1, 0, 62 , 50 , 0 , 0 , 0 , 0 ), // #441 {mm, xmm} + ROW(2, 1, 1, 0, 6 , 50 , 0 , 0 , 0 , 0 ), // #442 {r32, xmm} + ROW(2, 1, 1, 0, 30 , 62 , 0 , 0 , 0 , 0 ), // #443 {m64|mem, mm} + ROW(2, 1, 1, 0, 50 , 62 , 0 , 0 , 0 , 0 ), // #444 {xmm, mm} + ROW(2, 1, 1, 2, 36 , 121, 0 , 0 , 0 , 0 ), // #445 {<eax>, <ecx>} + ROW(3, 1, 1, 3, 36 , 121, 154, 0 , 0 , 0 ), // #446 {<eax>, <ecx>, <ebx>} + ROW(2, 1, 1, 0, 168, 160, 0 , 0 , 0 , 0 ), // #447 {u8|dx, al|ax|eax} + ROW(2, 1, 1, 0, 163, 169, 0 , 0 , 0 , 0 ), // #448 {dx, ds:[m8|memBase|zsi|m16|m32]} + ROW(6, 1, 1, 3, 50 , 51 , 10 , 121, 36 , 35 ), // #449 {xmm, xmm|m128|mem, i8|u8, <ecx>, <eax>, <edx>} + ROW(6, 1, 1, 3, 50 , 51 , 10 , 147, 36 , 35 ), // #450 {xmm, xmm|m128|mem, i8|u8, <xmm0>, <eax>, <edx>} + ROW(4, 1, 1, 1, 50 , 51 , 10 , 121, 0 , 0 ), // #451 {xmm, xmm|m128|mem, i8|u8, <ecx>} + ROW(4, 1, 1, 1, 50 , 51 , 10 , 147, 0 , 0 ), // #452 {xmm, xmm|m128|mem, i8|u8, <xmm0>} + ROW(3, 1, 1, 0, 131, 50 , 10 , 0 , 0 , 0 ), // #453 {r32|m8|mem, xmm, i8|u8} + ROW(3, 0, 1, 0, 15 , 50 , 10 , 0 , 0 , 0 ), // #454 {r64|m64|mem, xmm, i8|u8} + ROW(3, 1, 1, 0, 50 , 131, 10 , 0 , 0 , 0 ), // #455 {xmm, r32|m8|mem, i8|u8} + ROW(3, 1, 1, 0, 50 , 28 , 10 , 0 , 0 , 0 ), // #456 {xmm, r32|m32|mem, i8|u8} + ROW(3, 0, 1, 0, 50 , 15 , 10 , 0 , 0 , 0 ), // #457 {xmm, r64|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 64 , 135, 10 , 0 , 0 , 0 ), // #458 {mm|xmm, r32|m16|mem, i8|u8} + ROW(2, 1, 1, 0, 6 , 64 , 0 , 0 , 0 , 0 ), // #459 {r32, mm|xmm} + ROW(2, 1, 1, 0, 50 , 10 , 0 , 0 , 0 , 0 ), // #460 {xmm, i8|u8} + ROW(1, 1, 1, 0, 155, 0 , 0 , 0 , 0 , 0 ), // #461 {r32|m32|mem|r64|m64} + ROW(2, 1, 1, 0, 31 , 103, 0 , 0 , 0 , 0 ), // #462 {r8lo|r8hi|m8|r16|m16|r32|m32|r64|m64|mem, cl|i8|u8} + ROW(1, 0, 1, 0, 139, 0 , 0 , 0 , 0 , 0 ), // #463 {r32|r64} + ROW(3, 1, 1, 3, 35 , 36 , 121, 0 , 0 , 0 ), // #464 {<edx>, <eax>, <ecx>} + ROW(1, 1, 1, 0, 1 , 0 , 0 , 0 , 0 , 0 ), // #465 {r8lo|r8hi|m8|mem} + ROW(1, 1, 1, 0, 170, 0 , 0 , 0 , 0 , 0 ), // #466 {r16|m16|mem|r32|r64} + ROW(3, 0, 1, 0, 171, 171, 171, 0 , 0 , 0 ), // #467 {tmm, tmm, tmm} + ROW(2, 0, 1, 0, 171, 172, 0 , 0 , 0 , 0 ), // #468 {tmm, tmem} + ROW(2, 0, 1, 0, 172, 171, 0 , 0 , 0 , 0 ), // #469 {tmem, tmm} + ROW(1, 0, 1, 0, 171, 0 , 0 , 0 , 0 , 0 ), // #470 {tmm} + ROW(3, 1, 1, 2, 6 , 35 , 36 , 0 , 0 , 0 ), // #471 {r32, <edx>, <eax>} + ROW(1, 1, 1, 0, 173, 0 , 0 , 0 , 0 , 0 ), // #472 {ds:[mem|memBase]} + ROW(6, 1, 1, 0, 56 , 56 , 56 , 56 , 56 , 52 ), // #473 {zmm, zmm, zmm, zmm, zmm, m128|mem} + ROW(6, 1, 1, 0, 50 , 50 , 50 , 50 , 50 , 52 ), // #474 {xmm, xmm, xmm, xmm, xmm, m128|mem} + ROW(3, 1, 1, 0, 50 , 50 , 65 , 0 , 0 , 0 ), // #475 {xmm, xmm, xmm|m64|mem} + ROW(3, 1, 1, 0, 50 , 50 , 110, 0 , 0 , 0 ), // #476 {xmm, xmm, xmm|m16|mem} + ROW(3, 1, 1, 0, 50 , 50 , 107, 0 , 0 , 0 ), // #477 {xmm, xmm, xmm|m32|mem} + ROW(2, 1, 1, 0, 53 , 52 , 0 , 0 , 0 , 0 ), // #478 {ymm, m128|mem} + ROW(2, 1, 1, 0, 174, 65 , 0 , 0 , 0 , 0 ), // #479 {ymm|zmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 174, 52 , 0 , 0 , 0 , 0 ), // #480 {ymm|zmm, m128|mem} + ROW(2, 1, 1, 0, 56 , 55 , 0 , 0 , 0 , 0 ), // #481 {zmm, m256|mem} + ROW(2, 1, 1, 0, 175, 65 , 0 , 0 , 0 , 0 ), // #482 {xmm|ymm|zmm, xmm|m64|mem} + ROW(2, 1, 1, 0, 175, 107, 0 , 0 , 0 , 0 ), // #483 {xmm|ymm|zmm, m32|mem|xmm} + ROW(4, 1, 1, 0, 104, 50 , 65 , 10 , 0 , 0 ), // #484 {xmm|k, xmm, xmm|m64|mem, i8|u8} + ROW(4, 1, 1, 0, 106, 50 , 110, 10 , 0 , 0 ), // #485 {k, xmm, xmm|m16|mem, i8|u8} + ROW(4, 1, 1, 0, 104, 50 , 107, 10 , 0 , 0 ), // #486 {xmm|k, xmm, xmm|m32|mem, i8|u8} + ROW(2, 1, 1, 0, 50 , 176, 0 , 0 , 0 , 0 ), // #487 {xmm, xmm|m128|ymm|m256|zmm|m512} + ROW(2, 1, 1, 0, 139, 110, 0 , 0 , 0 , 0 ), // #488 {r32|r64, xmm|m16|mem} + ROW(3, 1, 1, 0, 50 , 50 , 155, 0 , 0 , 0 ), // #489 {xmm, xmm, r32|m32|mem|r64|m64} + ROW(3, 1, 1, 0, 51 , 174, 10 , 0 , 0 , 0 ), // #490 {xmm|m128|mem, ymm|zmm, i8|u8} + ROW(4, 1, 1, 0, 50 , 50 , 65 , 10 , 0 , 0 ), // #491 {xmm, xmm, xmm|m64|mem, i8|u8} + ROW(4, 1, 1, 0, 50 , 50 , 107, 10 , 0 , 0 ), // #492 {xmm, xmm, xmm|m32|mem, i8|u8} + ROW(3, 1, 1, 0, 106, 176, 10 , 0 , 0 , 0 ), // #493 {k, xmm|m128|ymm|m256|zmm|m512, i8|u8} + ROW(3, 1, 1, 0, 106, 65 , 10 , 0 , 0 , 0 ), // #494 {k, xmm|m64|mem, i8|u8} + ROW(3, 1, 1, 0, 106, 110, 10 , 0 , 0 , 0 ), // #495 {k, xmm|m16|mem, i8|u8} + ROW(3, 1, 1, 0, 106, 107, 10 , 0 , 0 , 0 ), // #496 {k, xmm|m32|mem, i8|u8} + ROW(1, 1, 1, 0, 68 , 0 , 0 , 0 , 0 , 0 ), // #497 {vm32y} + ROW(1, 1, 1, 0, 69 , 0 , 0 , 0 , 0 , 0 ), // #498 {vm32z} + ROW(1, 1, 1, 0, 72 , 0 , 0 , 0 , 0 , 0 ), // #499 {vm64z} + ROW(4, 1, 1, 0, 50 , 50 , 110, 10 , 0 , 0 ), // #500 {xmm, xmm, xmm|m16|mem, i8|u8} + ROW(4, 1, 1, 0, 56 , 56 , 54 , 10 , 0 , 0 ), // #501 {zmm, zmm, ymm|m256|mem, i8|u8} + ROW(2, 1, 1, 0, 6 , 96 , 0 , 0 , 0 , 0 ), // #502 {r32, xmm|ymm} + ROW(2, 1, 1, 0, 175, 177, 0 , 0 , 0 , 0 ), // #503 {xmm|ymm|zmm, xmm|m8|mem|r32} + ROW(2, 1, 1, 0, 175, 178, 0 , 0 , 0 , 0 ), // #504 {xmm|ymm|zmm, xmm|m32|mem|r32} + ROW(2, 1, 1, 0, 175, 106, 0 , 0 , 0 , 0 ), // #505 {xmm|ymm|zmm, k} + ROW(2, 1, 1, 0, 175, 179, 0 , 0 , 0 , 0 ), // #506 {xmm|ymm|zmm, xmm|m16|mem|r32} + ROW(3, 1, 1, 0, 135, 50 , 10 , 0 , 0 , 0 ), // #507 {r32|m16|mem, xmm, i8|u8} + ROW(4, 1, 1, 0, 50 , 50 , 131, 10 , 0 , 0 ), // #508 {xmm, xmm, r32|m8|mem, i8|u8} + ROW(4, 1, 1, 0, 50 , 50 , 28 , 10 , 0 , 0 ), // #509 {xmm, xmm, r32|m32|mem, i8|u8} + ROW(4, 0, 1, 0, 50 , 50 , 15 , 10 , 0 , 0 ), // #510 {xmm, xmm, r64|m64|mem, i8|u8} + ROW(4, 1, 1, 0, 50 , 50 , 135, 10 , 0 , 0 ), // #511 {xmm, xmm, r32|m16|mem, i8|u8} + ROW(2, 1, 1, 0, 106, 175, 0 , 0 , 0 , 0 ), // #512 {k, xmm|ymm|zmm} + ROW(1, 1, 1, 0, 124, 0 , 0 , 0 , 0 , 0 ), // #513 {rel16|rel32} + ROW(3, 1, 1, 2, 113, 35 , 36 , 0 , 0 , 0 ), // #514 {mem, <edx>, <eax>} + ROW(3, 0, 1, 2, 113, 35 , 36 , 0 , 0 , 0 ) // #515 {mem, <edx>, <eax>} }; #undef ROW -#define ROW(flags, mFlags, extFlags, regId) { uint32_t(flags), uint16_t(mFlags), uint8_t(extFlags), uint8_t(regId) } -#define F(VAL) InstDB::kOp##VAL -#define M(VAL) InstDB::kMemOp##VAL +#define ROW(opFlags, regId) { opFlags, uint8_t(regId) } +#define F(VAL) uint64_t(InstDB::OpFlags::k##VAL) const InstDB::OpSignature InstDB::_opSignatureTable[] = { - ROW(0, 0, 0, 0xFF), - ROW(F(GpbLo) | F(GpbHi) | F(Mem), M(M8) | M(Any), 0, 0x00), - ROW(F(GpbLo) | F(GpbHi), 0, 0, 0x00), - ROW(F(Gpw) | F(SReg) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(Gpw), 0, 0, 0x00), - ROW(F(Gpd) | F(SReg) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Gpd), 0, 0, 0x00), - ROW(F(Gpq) | F(SReg) | F(CReg) | F(DReg) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(Gpq), 0, 0, 0x00), - ROW(F(GpbLo) | F(GpbHi) | F(Mem), M(M8), 0, 0x00), - ROW(F(I8) | F(U8), 0, 0, 0x00), - ROW(F(Gpw) | F(Mem), M(M16), 0, 0x00), - ROW(F(I16) | F(U16), 0, 0, 0x00), - ROW(F(Gpd) | F(Mem), M(M32), 0, 0x00), - ROW(F(I32) | F(U32), 0, 0, 0x00), - ROW(F(Gpq) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(I32), 0, 0, 0x00), - ROW(F(SReg) | F(CReg) | F(DReg) | F(Mem) | F(I64) | F(U64), M(M64) | M(Any), 0, 0x00), - ROW(F(Mem), M(M8) | M(Any), 0, 0x00), - ROW(F(SReg) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(SReg) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(SReg), 0, 0, 0x00), - ROW(F(CReg) | F(DReg), 0, 0, 0x00), - ROW(F(Gpq) | F(I32), 0, 0, 0x00), - ROW(F(Gpw) | F(Gpd) | F(Gpq) | F(Mem), M(M16) | M(M32) | M(M64) | M(Any), 0, 0x00), - ROW(F(I8), 0, 0, 0x00), - ROW(F(Gpw) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(GpbLo) | F(GpbHi) | F(Gpw) | F(Gpd) | F(Gpq) | F(Mem), M(M8) | M(M16) | M(M32) | M(M64) | M(Any), 0, 0x00), - ROW(F(Gpq) | F(Mem) | F(I32) | F(U32), M(M64) | M(Any), 0, 0x00), - ROW(F(Gpw) | F(Implicit), 0, 0, 0x01), - ROW(F(Gpw) | F(Implicit), 0, 0, 0x04), - ROW(F(Gpd) | F(Implicit), 0, 0, 0x04), - ROW(F(Gpd) | F(Implicit), 0, 0, 0x01), - ROW(F(Gpq) | F(Implicit), 0, 0, 0x04), - ROW(F(Gpq) | F(Implicit), 0, 0, 0x01), - ROW(F(Gpw) | F(Mem) | F(I8) | F(I16), M(M16) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Mem) | F(I8) | F(I32), M(M32) | M(Any), 0, 0x00), - ROW(F(Gpq) | F(Mem) | F(I8) | F(I32), M(M64) | M(Any), 0, 0x00), - ROW(F(I8) | F(I16) | F(U16), 0, 0, 0x00), - ROW(F(I8) | F(I32) | F(U32), 0, 0, 0x00), - ROW(F(I8) | F(I32), 0, 0, 0x00), - ROW(F(I64) | F(U64), 0, 0, 0x00), - ROW(F(GpbLo), 0, 0, 0x01), - ROW(F(Gpw), 0, 0, 0x01), - ROW(F(Gpd), 0, 0, 0x01), - ROW(F(Gpq), 0, 0, 0x01), - ROW(F(Xmm), 0, 0, 0x00), - ROW(F(Xmm) | F(Mem), M(M128) | M(Any), 0, 0x00), - ROW(F(Mem), M(M128) | M(Any), 0, 0x00), - ROW(F(Ymm), 0, 0, 0x00), - ROW(F(Ymm) | F(Mem), M(M256) | M(Any), 0, 0x00), - ROW(F(Mem), M(M256) | M(Any), 0, 0x00), - ROW(F(Zmm), 0, 0, 0x00), - ROW(F(Zmm) | F(Mem), M(M512) | M(Any), 0, 0x00), - ROW(F(Mem), M(M512) | M(Any), 0, 0x00), - ROW(F(Xmm) | F(Mem) | F(I8) | F(U8), M(M128) | M(Any), 0, 0x00), - ROW(F(Ymm) | F(Mem) | F(I8) | F(U8), M(M256) | M(Any), 0, 0x00), - ROW(F(Zmm) | F(Mem) | F(I8) | F(U8), M(M512) | M(Any), 0, 0x00), - ROW(F(Mm), 0, 0, 0x00), - ROW(F(Gpq) | F(Mm) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(Xmm) | F(Mm), 0, 0, 0x00), - ROW(F(Xmm) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(Gpw) | F(Gpd) | F(Gpq) | F(Mem), M(M16) | M(M32) | M(M64), 0, 0x00), - ROW(F(Vm), M(Vm32x), 0, 0x00), - ROW(F(Vm), M(Vm32y), 0, 0x00), - ROW(F(Vm), M(Vm32z), 0, 0x00), - ROW(F(Vm), M(Vm64x), 0, 0x00), - ROW(F(Vm), M(Vm64y), 0, 0x00), - ROW(F(Vm), M(Vm64z), 0, 0x00), - ROW(F(Mem) | F(Implicit), M(M8) | M(BaseOnly) | M(Ds), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M8) | M(BaseOnly) | M(Es), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M16) | M(BaseOnly) | M(Ds), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M16) | M(BaseOnly) | M(Es), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M32) | M(BaseOnly) | M(Ds), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M32) | M(BaseOnly) | M(Es), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M64) | M(BaseOnly) | M(Ds), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M64) | M(BaseOnly) | M(Es), 0, 0x80), - ROW(F(GpbLo) | F(Implicit), 0, 0, 0x01), - ROW(F(Mem) | F(Implicit), M(M8) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M16) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M32) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x40), - ROW(F(Mem) | F(Implicit), M(M64) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x40), - ROW(F(Gpw) | F(Gpq) | F(Mem), M(M16) | M(M64), 0, 0x00), - ROW(F(SReg), 0, 0, 0x1A), - ROW(F(SReg), 0, 0, 0x60), - ROW(F(Gpw) | F(Gpq) | F(Mem) | F(I8) | F(I16) | F(I32), M(M16) | M(M64), 0, 0x00), - ROW(F(Gpd) | F(Mem) | F(I32) | F(U32), M(M32), 0, 0x00), - ROW(F(SReg), 0, 0, 0x1E), - ROW(F(Mem) | F(Implicit), M(M8) | M(BaseOnly) | M(Es) | M(Any), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M16) | M(BaseOnly) | M(Es) | M(Any), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M32) | M(BaseOnly) | M(Es) | M(Any), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M64) | M(BaseOnly) | M(Es) | M(Any), 0, 0x80), - ROW(F(Xmm) | F(Ymm), 0, 0, 0x00), - ROW(F(I4) | F(U4), 0, 0, 0x00), - ROW(F(Mem), M(M32) | M(M64), 0, 0x00), - ROW(F(St), 0, 0, 0x01), - ROW(F(St), 0, 0, 0x00), - ROW(F(Mem), M(M48) | M(Any), 0, 0x00), - ROW(F(Mem), M(M80) | M(Any), 0, 0x00), - ROW(F(GpbLo) | F(I8) | F(U8), 0, 0, 0x02), - ROW(F(Xmm) | F(KReg), 0, 0, 0x00), - ROW(F(Ymm) | F(KReg), 0, 0, 0x00), - ROW(F(KReg), 0, 0, 0x00), - ROW(F(Vm), M(Vm64x) | M(Vm64y), 0, 0x00), - ROW(F(Gpq) | F(Xmm) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(Xmm) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Xmm) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(Bnd), 0, 0, 0x00), - ROW(F(Bnd) | F(Mem), M(Any), 0, 0x00), - ROW(F(Mem), M(Any), 0, 0x00), - ROW(F(Gpw) | F(Gpd) | F(Mem) | F(I32) | F(I64) | F(Rel32), M(M16) | M(M32), 0, 0x00), - ROW(F(Gpq) | F(Mem) | F(I32) | F(I64) | F(Rel32), M(M64) | M(Any), 0, 0x00), - ROW(F(GpbLo) | F(GpbHi) | F(Gpw) | F(Gpd) | F(Mem), M(M8) | M(M16) | M(M32), 0, 0x00), - ROW(F(GpbLo) | F(GpbHi) | F(Gpq) | F(Mem), M(M8) | M(M64), 0, 0x00), - ROW(F(Gpw) | F(Gpd), 0, 0, 0x00), - ROW(F(Mem), M(M512) | M(BaseOnly) | M(Es) | M(Any), 0, 0x00), - ROW(F(St) | F(Mem), M(M32) | M(M64), 0, 0x00), - ROW(F(Gpd) | F(Implicit), 0, 0, 0x02), - ROW(F(Gpd) | F(Gpq) | F(Implicit), 0, 0, 0x01), - ROW(F(I32) | F(I64) | F(Rel8) | F(Rel32), 0, 0, 0x00), - ROW(F(I32) | F(I64) | F(Rel32), 0, 0, 0x00), - ROW(F(Gpw) | F(Gpd) | F(Implicit), 0, 0, 0x02), - ROW(F(I32) | F(I64) | F(Rel8), 0, 0, 0x00), - ROW(F(Gpd) | F(Gpq) | F(Implicit), 0, 0, 0x02), - ROW(F(Gpq) | F(Mem) | F(I32) | F(I64) | F(Rel8) | F(Rel32), M(M64) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Mem) | F(I32) | F(I64) | F(Rel32), M(M32) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(KReg) | F(Mem), M(M8) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Mem), M(M8) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(KReg) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Gpq) | F(KReg) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(KReg) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(I16), 0, 0, 0x00), - ROW(F(I16) | F(I32), 0, 0, 0x00), - ROW(F(Mem), M(M32) | M(M48) | M(M80) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Gpq), 0, 0, 0x00), - ROW(F(GpbLo) | F(GpbHi) | F(Gpw) | F(Mem), M(M8) | M(M16), 0, 0x00), - ROW(F(Mm) | F(Mem), M(M64) | M(Any), 0, 0x00), - ROW(F(Mm) | F(Mem) | F(I8) | F(U8), M(M64) | M(Any), 0, 0x00), - ROW(F(Mm) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(U16), 0, 0, 0x00), - ROW(F(Xmm) | F(Ymm) | F(Mem), M(M128) | M(M256), 0, 0x00), - ROW(F(Xmm) | F(I8) | F(U8), 0, 0, 0x00), - ROW(F(Xmm) | F(Implicit), 0, 0, 0x01), - ROW(F(Mem), M(Mib), 0, 0x00), - ROW(F(Gpw) | F(Gpd) | F(Gpq), 0, 0, 0x00), - ROW(F(Mem), M(M8) | M(M16) | M(M32) | M(M48) | M(M64) | M(M80) | M(M128) | M(M256) | M(M512) | M(M1024) | M(Any), 0, 0x00), - ROW(F(Mem) | F(Implicit), M(M512) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x01), - ROW(F(Gpq) | F(Implicit), 0, 0, 0x02), - ROW(F(Gpq) | F(Implicit), 0, 0, 0x08), - ROW(F(Gpd) | F(Implicit), 0, 0, 0x08), - ROW(F(Gpd) | F(Gpq) | F(Mem), M(M32) | M(M64) | M(Any), 0, 0x00), - ROW(F(Mem), M(M16) | M(M32), 0, 0x00), - ROW(F(Mem), M(M16) | M(M32) | M(M64), 0, 0x00), - ROW(F(St) | F(Mem), M(M32) | M(M64) | M(M80), 0, 0x00), - ROW(F(Gpw) | F(Mem), M(M16) | M(Any), 0, 0x01), - ROW(F(GpbLo) | F(Gpw) | F(Gpd), 0, 0, 0x01), - ROW(F(Gpw) | F(I8) | F(U8), 0, 0, 0x04), - ROW(F(Mem), M(M8) | M(M16) | M(M32) | M(BaseOnly) | M(Es), 0, 0x80), - ROW(F(Gpw), 0, 0, 0x04), - ROW(F(GpbHi) | F(Implicit), 0, 0, 0x01), - ROW(F(Mem) | F(Implicit), M(M128) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(M64) | M(BaseOnly) | M(Ds) | M(Any), 0, 0x80), - ROW(F(Mem) | F(Implicit), M(BaseOnly) | M(Ds) | M(Any), 0, 0x01), - ROW(F(Gpw) | F(U8), 0, 0, 0x04), - ROW(F(Mem), M(M8) | M(M16) | M(M32) | M(BaseOnly) | M(Ds), 0, 0x40), - ROW(F(Gpw) | F(Gpd) | F(Gpq) | F(Mem), M(M16) | M(Any), 0, 0x00), - ROW(F(Tmm), 0, 0, 0x00), - ROW(F(Mem), M(BaseOnly) | M(Ds) | M(Any), 0, 0x00), - ROW(F(Ymm) | F(Zmm), 0, 0, 0x00), - ROW(F(Xmm) | F(Ymm) | F(Zmm), 0, 0, 0x00), - ROW(F(Xmm) | F(Ymm) | F(Zmm) | F(Mem), M(M128) | M(M256) | M(M512), 0, 0x00), - ROW(F(Gpd) | F(Xmm) | F(Mem), M(M8) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Xmm) | F(Mem), M(M32) | M(Any), 0, 0x00), - ROW(F(Gpd) | F(Xmm) | F(Mem), M(M16) | M(Any), 0, 0x00) + ROW(0, 0xFF), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(MemUnspecified) | F(Mem8), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi), 0x00), + ROW(F(RegGpw) | F(RegSReg) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegGpw), 0x00), + ROW(F(RegGpd) | F(RegSReg) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(RegGpd), 0x00), + ROW(F(RegGpq) | F(RegSReg) | F(RegCReg) | F(RegDReg) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegGpq), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(Mem8), 0x00), + ROW(F(ImmI8) | F(ImmU8), 0x00), + ROW(F(RegGpw) | F(Mem16), 0x00), + ROW(F(ImmI16) | F(ImmU16), 0x00), + ROW(F(RegGpd) | F(Mem32), 0x00), + ROW(F(ImmI32) | F(ImmU32), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(ImmI32), 0x00), + ROW(F(RegSReg) | F(RegCReg) | F(RegDReg) | F(MemUnspecified) | F(Mem64) | F(ImmI64) | F(ImmU64), 0x00), + ROW(F(MemUnspecified) | F(Mem8), 0x00), + ROW(F(RegSReg) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegSReg) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegSReg), 0x00), + ROW(F(RegCReg) | F(RegDReg), 0x00), + ROW(F(RegGpq) | F(ImmI32), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem16) | F(Mem32) | F(Mem64), 0x00), + ROW(F(ImmI8), 0x00), + ROW(F(RegGpw) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegGpd) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem8) | F(Mem16) | F(Mem32) | F(Mem64), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI32) | F(ImmU32), 0x00), + ROW(F(RegGpw) | F(FlagImplicit), 0x01), + ROW(F(RegGpw) | F(FlagImplicit), 0x04), + ROW(F(RegGpd) | F(FlagImplicit), 0x04), + ROW(F(RegGpd) | F(FlagImplicit), 0x01), + ROW(F(RegGpq) | F(FlagImplicit), 0x04), + ROW(F(RegGpq) | F(FlagImplicit), 0x01), + ROW(F(RegGpw) | F(MemUnspecified) | F(Mem16) | F(ImmI8) | F(ImmI16), 0x00), + ROW(F(RegGpd) | F(MemUnspecified) | F(Mem32) | F(ImmI8) | F(ImmI32), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI8) | F(ImmI32), 0x00), + ROW(F(ImmI8) | F(ImmI16) | F(ImmU16), 0x00), + ROW(F(ImmI8) | F(ImmI32) | F(ImmU32), 0x00), + ROW(F(ImmI8) | F(ImmI32), 0x00), + ROW(F(ImmI64) | F(ImmU64), 0x00), + ROW(F(RegGpbLo), 0x01), + ROW(F(RegGpw), 0x01), + ROW(F(RegGpd), 0x01), + ROW(F(RegGpq), 0x01), + ROW(F(RegXmm), 0x00), + ROW(F(RegXmm) | F(MemUnspecified) | F(Mem128), 0x00), + ROW(F(MemUnspecified) | F(Mem128), 0x00), + ROW(F(RegYmm), 0x00), + ROW(F(RegYmm) | F(MemUnspecified) | F(Mem256), 0x00), + ROW(F(MemUnspecified) | F(Mem256), 0x00), + ROW(F(RegZmm), 0x00), + ROW(F(RegZmm) | F(MemUnspecified) | F(Mem512), 0x00), + ROW(F(MemUnspecified) | F(Mem512), 0x00), + ROW(F(RegXmm) | F(MemUnspecified) | F(Mem128) | F(ImmI8) | F(ImmU8), 0x00), + ROW(F(RegYmm) | F(MemUnspecified) | F(Mem256) | F(ImmI8) | F(ImmU8), 0x00), + ROW(F(RegZmm) | F(MemUnspecified) | F(Mem512) | F(ImmI8) | F(ImmU8), 0x00), + ROW(F(RegMm), 0x00), + ROW(F(RegGpq) | F(RegMm) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegXmm) | F(RegMm), 0x00), + ROW(F(RegXmm) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(RegGpq) | F(Mem16) | F(Mem32) | F(Mem64), 0x00), + ROW(F(Vm32x), 0x00), + ROW(F(Vm32y), 0x00), + ROW(F(Vm32z), 0x00), + ROW(F(Vm64x), 0x00), + ROW(F(Vm64y), 0x00), + ROW(F(Vm64z), 0x00), + ROW(F(Mem8) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(Mem8) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(Mem16) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(Mem16) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(Mem32) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(Mem32) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(Mem64) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(Mem64) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(RegGpbLo) | F(FlagImplicit), 0x01), + ROW(F(MemUnspecified) | F(Mem8) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(MemUnspecified) | F(Mem16) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(MemUnspecified) | F(Mem32) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x40), + ROW(F(RegGpw) | F(RegGpq) | F(Mem16) | F(Mem64), 0x00), + ROW(F(RegSReg), 0x1A), + ROW(F(RegSReg), 0x60), + ROW(F(RegGpw) | F(RegGpq) | F(Mem16) | F(Mem64) | F(ImmI8) | F(ImmI16) | F(ImmI32), 0x00), + ROW(F(RegGpd) | F(Mem32) | F(ImmI32) | F(ImmU32), 0x00), + ROW(F(RegSReg), 0x1E), + ROW(F(MemUnspecified) | F(Mem8) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(MemUnspecified) | F(Mem16) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(MemUnspecified) | F(Mem32) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemEs) | F(FlagImplicit), 0x80), + ROW(F(RegXmm) | F(RegYmm), 0x00), + ROW(F(ImmI4) | F(ImmU4), 0x00), + ROW(F(Mem32) | F(Mem64), 0x00), + ROW(F(RegSt), 0x01), + ROW(F(RegSt), 0x00), + ROW(F(MemUnspecified) | F(Mem48), 0x00), + ROW(F(MemUnspecified) | F(Mem80), 0x00), + ROW(F(RegGpbLo) | F(ImmI8) | F(ImmU8), 0x02), + ROW(F(RegXmm) | F(RegKReg), 0x00), + ROW(F(RegYmm) | F(RegKReg), 0x00), + ROW(F(RegKReg), 0x00), + ROW(F(RegXmm) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(Vm64x) | F(Vm64y), 0x00), + ROW(F(RegGpq) | F(RegXmm) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegXmm) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegBnd), 0x00), + ROW(F(RegBnd) | F(MemUnspecified), 0x00), + ROW(F(MemUnspecified), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(Mem16) | F(Mem32) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(RegGpd) | F(Mem8) | F(Mem16) | F(Mem32), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpq) | F(Mem8) | F(Mem64), 0x00), + ROW(F(RegGpw) | F(RegGpd), 0x00), + ROW(F(MemUnspecified) | F(Mem512) | F(FlagMemBase) | F(FlagMemEs), 0x00), + ROW(F(RegSt) | F(Mem32) | F(Mem64), 0x00), + ROW(F(RegGpd) | F(FlagImplicit), 0x02), + ROW(F(RegGpd) | F(RegGpq) | F(FlagImplicit), 0x01), + ROW(F(ImmI32) | F(ImmI64) | F(Rel8) | F(Rel32), 0x00), + ROW(F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(FlagImplicit), 0x02), + ROW(F(ImmI32) | F(ImmI64) | F(Rel8), 0x00), + ROW(F(RegGpd) | F(RegGpq) | F(FlagImplicit), 0x02), + ROW(F(RegGpq) | F(MemUnspecified) | F(Mem64) | F(ImmI32) | F(ImmI64) | F(Rel8) | F(Rel32), 0x00), + ROW(F(RegGpd) | F(MemUnspecified) | F(Mem32) | F(ImmI32) | F(ImmI64) | F(Rel32), 0x00), + ROW(F(RegGpd) | F(RegKReg) | F(MemUnspecified) | F(Mem8), 0x00), + ROW(F(RegGpd) | F(MemUnspecified) | F(Mem8), 0x00), + ROW(F(RegGpd) | F(RegKReg) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(RegGpq) | F(RegKReg) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegGpd) | F(RegKReg) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegGpd) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(ImmI16), 0x00), + ROW(F(ImmI16) | F(ImmI32), 0x00), + ROW(F(MemUnspecified) | F(Mem32) | F(Mem48) | F(Mem80), 0x00), + ROW(F(RegGpd) | F(RegGpq), 0x00), + ROW(F(RegGpbLo) | F(RegGpbHi) | F(RegGpw) | F(Mem8) | F(Mem16), 0x00), + ROW(F(RegMm) | F(MemUnspecified) | F(Mem64), 0x00), + ROW(F(RegMm) | F(MemUnspecified) | F(Mem64) | F(ImmI8) | F(ImmU8), 0x00), + ROW(F(RegMm) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(ImmU16), 0x00), + ROW(F(RegXmm) | F(RegYmm) | F(Mem128) | F(Mem256), 0x00), + ROW(F(RegXmm) | F(ImmI8) | F(ImmU8), 0x00), + ROW(F(RegXmm) | F(FlagImplicit), 0x01), + ROW(F(MemUnspecified) | F(FlagMib), 0x00), + ROW(F(RegGpw) | F(RegGpd) | F(RegGpq), 0x00), + ROW(F(MemUnspecified) | F(Mem8) | F(Mem16) | F(Mem32) | F(Mem48) | F(Mem64) | F(Mem80) | F(Mem128) | F(Mem256) | F(Mem512) | F(Mem1024), 0x00), + ROW(F(MemUnspecified) | F(Mem512) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x01), + ROW(F(RegGpq) | F(FlagImplicit), 0x02), + ROW(F(RegGpq) | F(FlagImplicit), 0x08), + ROW(F(RegGpd) | F(FlagImplicit), 0x08), + ROW(F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem32) | F(Mem64), 0x00), + ROW(F(Mem16) | F(Mem32), 0x00), + ROW(F(Mem16) | F(Mem32) | F(Mem64), 0x00), + ROW(F(RegSt) | F(Mem32) | F(Mem64) | F(Mem80), 0x00), + ROW(F(RegGpw) | F(MemUnspecified) | F(Mem16), 0x01), + ROW(F(RegGpbLo) | F(RegGpw) | F(RegGpd), 0x01), + ROW(F(RegGpw) | F(ImmI8) | F(ImmU8), 0x04), + ROW(F(Mem8) | F(Mem16) | F(Mem32) | F(FlagMemBase) | F(FlagMemEs), 0x80), + ROW(F(RegGpw), 0x04), + ROW(F(RegGpbHi) | F(FlagImplicit), 0x01), + ROW(F(MemUnspecified) | F(Mem128) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x80), + ROW(F(MemUnspecified) | F(Mem64) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x80), + ROW(F(MemUnspecified) | F(FlagMemBase) | F(FlagMemDs) | F(FlagImplicit), 0x01), + ROW(F(RegGpw) | F(ImmU8), 0x04), + ROW(F(Mem8) | F(Mem16) | F(Mem32) | F(FlagMemBase) | F(FlagMemDs), 0x40), + ROW(F(RegGpw) | F(RegGpd) | F(RegGpq) | F(MemUnspecified) | F(Mem16), 0x00), + ROW(F(RegTmm), 0x00), + ROW(F(MemUnspecified) | F(FlagTMem), 0x00), + ROW(F(MemUnspecified) | F(FlagMemBase) | F(FlagMemDs), 0x00), + ROW(F(RegYmm) | F(RegZmm), 0x00), + ROW(F(RegXmm) | F(RegYmm) | F(RegZmm), 0x00), + ROW(F(RegXmm) | F(RegYmm) | F(RegZmm) | F(Mem128) | F(Mem256) | F(Mem512), 0x00), + ROW(F(RegGpd) | F(RegXmm) | F(MemUnspecified) | F(Mem8), 0x00), + ROW(F(RegGpd) | F(RegXmm) | F(MemUnspecified) | F(Mem32), 0x00), + ROW(F(RegGpd) | F(RegXmm) | F(MemUnspecified) | F(Mem16), 0x00) }; -#undef M #undef F #undef ROW // ---------------------------------------------------------------------------- // ${InstSignatureTable:End} #endif // !ASMJIT_NO_VALIDATION -// ============================================================================ -// [asmjit::x86::InstInternal - QueryRWInfo] -// ============================================================================ +// x86::InstInternal - QueryRWInfo +// =============================== // ${InstRWInfoTable:Begin} // ------------------- Automatically generated, do not edit ------------------- @@ -3621,53 +3762,58 @@ const uint8_t InstDB::rwInfoIndexA[Inst::_kIdCount] = { 0, 0, 0, 0, 0, 62, 63, 63, 63, 58, 60, 0, 0, 0, 9, 0, 0, 4, 4, 5, 6, 0, 0, 4, 4, 5, 6, 0, 0, 64, 65, 66, 66, 67, 47, 24, 36, 67, 52, 66, 66, 68, 69, 69, 70, 71, 71, 72, 72, 59, 59, 67, 59, 59, 71, 71, 73, 48, 52, 74, 48, 7, 7, 47, 75, - 33, 66, 66, 75, 0, 35, 4, 4, 5, 6, 0, 76, 0, 0, 77, 0, 2, 4, 4, 78, 79, 9, - 9, 9, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 80, 3, 0, 0, 0, 3, 3, + 9, 66, 66, 75, 0, 35, 4, 4, 5, 6, 0, 76, 0, 0, 77, 0, 2, 4, 4, 78, 79, 9, 9, + 9, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 80, 3, 0, 0, 0, 3, 3, 4, 3, 0, 0, 3, 3, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 27, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 27, 80, 80, 80, 27, 27, 80, 80, 80, 3, 3, 3, 81, 3, 3, 3, 27, 27, 0, 0, 0, 0, 3, 3, 4, 4, 3, 3, 4, 4, 4, 4, 3, 3, 4, 4, 82, 83, 84, 24, - 24, 24, 83, 83, 84, 24, 24, 24, 83, 4, 3, 80, 3, 3, 4, 3, 3, 0, 0, 0, 9, 0, - 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 85, 3, 3, 0, 3, 3, + 24, 24, 83, 83, 84, 24, 24, 24, 83, 4, 3, 80, 3, 3, 4, 3, 3, 0, 0, 0, 9, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 3, 3, 3, 3, 85, 3, 3, 0, 3, 3, 3, 85, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 86, 0, 3, 3, 4, 3, 87, 87, 4, 87, 0, 0, 0, 0, 0, 0, 0, 3, 88, 7, 89, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 88, 88, 0, 0, 0, 0, 0, 0, 7, 89, 0, 0, 88, 88, 0, 0, 2, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 88, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 26, 89, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 2, 4, 4, 5, 6, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 93, 93, 0, 94, 0, 0, 9, 9, 20, 21, 95, 95, 0, - 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 28, 97, 98, 97, 98, 96, 28, 97, 98, 97, 98, 99, - 100, 0, 0, 0, 0, 20, 21, 101, 101, 102, 9, 0, 75, 103, 103, 9, 103, 9, 102, 9, - 102, 0, 102, 9, 102, 9, 103, 28, 0, 28, 0, 0, 0, 33, 33, 103, 9, 103, 9, 9, - 102, 9, 102, 28, 28, 33, 33, 102, 9, 9, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 104, 104, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 93, 93, 0, 94, 0, 0, 9, 9, 20, 21, 95, 95, 0, 0, + 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 28, 97, 98, 97, 98, 96, 28, 97, 98, 97, 98, + 99, 100, 0, 0, 0, 0, 0, 0, 20, 101, 21, 102, 102, 103, 75, 9, 0, 75, 104, 105, + 104, 9, 104, 9, 106, 107, 103, 106, 107, 106, 107, 9, 9, 9, 103, 0, 75, 103, + 9, 103, 9, 105, 104, 0, 28, 0, 28, 0, 108, 0, 108, 0, 0, 0, 0, 0, 33, 33, 104, + 9, 104, 9, 106, 107, 106, 107, 9, 9, 9, 103, 9, 103, 28, 28, 108, 108, 33, + 33, 103, 75, 9, 9, 105, 104, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 109, 109, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 27, 105, 60, 60, 0, 0, 0, 0, 0, 0, 0, 0, 60, 106, 9, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 47, 108, 107, 107, 107, 107, - 107, 107, 107, 107, 0, 109, 109, 0, 71, 71, 110, 111, 67, 67, 67, 67, 112, 71, - 9, 9, 73, 107, 107, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 114, 33, 115, 115, 28, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 101, 101, 101, 0, 0, 0, 0, 0, - 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 60, 60, 106, 60, 7, 7, 7, 0, 7, 0, 7, - 7, 7, 7, 7, 7, 0, 7, 7, 81, 7, 0, 7, 0, 0, 7, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 27, 110, 60, 60, 0, 0, 0, 0, + 0, 0, 0, 0, 60, 111, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 112, 47, 113, 112, 112, 112, 112, 112, 112, 112, + 112, 0, 114, 114, 0, 71, 71, 115, 116, 67, 67, 67, 67, 117, 71, 118, 9, 9, + 73, 112, 112, 49, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 120, 33, 121, 121, 28, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 60, 60, 111, 60, 7, 7, 7, 0, 7, 0, + 7, 7, 7, 7, 7, 7, 0, 7, 7, 81, 7, 0, 7, 0, 0, 7, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 117, 118, 119, 115, 115, 115, 115, 82, 117, 120, 119, 118, 118, - 119, 120, 119, 118, 119, 121, 122, 102, 102, 102, 121, 118, 119, 120, 119, 118, - 119, 117, 119, 121, 122, 102, 102, 102, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 123, 67, + 0, 0, 0, 0, 123, 123, 124, 125, 121, 121, 121, 121, 82, 123, 126, 125, 124, 124, + 125, 126, 125, 124, 125, 127, 128, 103, 103, 103, 127, 124, 125, 126, 125, + 124, 125, 123, 125, 127, 128, 103, 103, 103, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 129, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 9, 0, 0, 104, 104, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 0, 0, 104, 104, 0, 0, 9, 0, 0, 0, 0, 0, 67, 67, 0, 0, 0, 0, 0, 0, - 0, 0, 67, 123, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 113, 113, 20, 21, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 125, 124, 125, 0, 126, 0, 127, 0, - 0, 0, 2, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 0, 0, 109, 109, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 109, 109, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0, 67, 129, 0, 0, 0, 0, 0, 0, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 119, 119, 20, 101, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 130, 131, 0, 132, 0, 133, 0, 0, 0, 2, 4, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t InstDB::rwInfoIndexB[Inst::_kIdCount] = { @@ -3705,48 +3851,53 @@ const uint8_t InstDB::rwInfoIndexB[Inst::_kIdCount] = { 4, 0, 90, 4, 5, 5, 32, 19, 91, 79, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 91, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 94, 94, 94, 94, 0, 0, 0, 0, 0, 0, 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, 56, 96, 0, 0, 0, 0, 97, 98, 97, 98, 3, 3, - 99, 100, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 101, 101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 102, 103, 0, 0, 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 105, 0, 106, 107, 108, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 107, 3, 3, 3, 99, 100, 3, 109, - 3, 55, 55, 0, 0, 0, 0, 110, 111, 112, 111, 112, 110, 111, 112, 111, 112, 22, - 113, 113, 114, 115, 113, 113, 116, 117, 113, 113, 116, 117, 113, 113, 116, - 117, 118, 118, 119, 120, 113, 113, 113, 113, 113, 113, 118, 118, 113, 113, 116, - 117, 113, 113, 116, 117, 113, 113, 116, 117, 113, 113, 113, 113, 113, 113, 118, - 118, 118, 118, 119, 120, 113, 113, 116, 117, 113, 113, 116, 117, 113, 113, - 116, 117, 118, 118, 119, 120, 113, 113, 116, 117, 113, 113, 116, 117, 113, 113, - 121, 122, 118, 118, 119, 120, 123, 123, 77, 124, 0, 0, 0, 0, 125, 126, 10, - 10, 10, 10, 10, 10, 10, 10, 126, 127, 0, 0, 128, 129, 84, 84, 128, 129, 3, 3, - 3, 3, 3, 3, 3, 130, 131, 132, 131, 132, 130, 131, 132, 131, 132, 100, 0, 53, 58, - 133, 133, 3, 3, 99, 100, 0, 134, 0, 3, 3, 99, 100, 0, 135, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 136, 137, 137, 138, 139, 139, 0, 0, 0, 0, 0, 0, 0, 140, - 0, 0, 141, 0, 0, 3, 11, 134, 0, 0, 142, 135, 3, 3, 99, 100, 0, 11, 3, 3, 143, - 143, 144, 144, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 101, 3, 0, 0, 0, 0, 0, 0, 3, 118, 145, 145, 3, 3, - 3, 3, 66, 67, 3, 3, 3, 3, 68, 69, 145, 145, 145, 145, 145, 145, 109, 109, 0, 0, - 0, 0, 109, 109, 109, 109, 109, 109, 0, 0, 113, 113, 113, 113, 146, 146, 3, 3, - 3, 113, 3, 3, 113, 113, 118, 118, 147, 147, 147, 3, 147, 3, 113, 113, 113, 113, - 113, 3, 0, 0, 0, 0, 70, 22, 71, 148, 126, 125, 127, 126, 0, 0, 0, 3, 0, 3, - 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 3, 3, 0, 149, 100, 99, 150, 0, 0, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 113, 113, 3, 3, 133, 133, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 99, 100, 101, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 102, 102, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 103, 3, 104, 105, 106, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, + 0, 0, 0, 0, 0, 0, 0, 108, 0, 109, 0, 110, 0, 110, 0, 111, 112, 113, 114, 115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 111, 112, 113, 0, 0, 3, 3, 3, 3, 99, 110, 101, 3, 116, 3, 55, 55, 0, 0, + 0, 0, 117, 118, 119, 118, 119, 117, 118, 119, 118, 119, 22, 120, 121, 120, 121, + 120, 120, 122, 123, 120, 120, 120, 124, 125, 126, 120, 120, 120, 124, 125, + 126, 120, 120, 120, 124, 125, 126, 120, 121, 127, 127, 128, 129, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 127, 127, 120, 120, 120, 124, 130, 126, 120, + 120, 120, 124, 130, 126, 120, 120, 120, 124, 130, 126, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 127, 127, 127, 127, 128, 129, 120, 121, 120, 120, 120, 124, + 125, 126, 120, 120, 120, 124, 125, 126, 120, 120, 120, 124, 125, 126, 127, + 127, 128, 129, 120, 120, 120, 124, 130, 126, 120, 120, 120, 124, 130, 126, 120, + 120, 120, 131, 130, 132, 127, 127, 128, 129, 133, 133, 133, 77, 134, 135, 0, + 0, 0, 0, 136, 137, 10, 10, 10, 10, 10, 10, 10, 10, 137, 138, 0, 0, 0, 139, 140, + 141, 84, 84, 84, 139, 140, 141, 3, 3, 3, 3, 3, 3, 3, 142, 143, 144, 143, 144, + 142, 143, 144, 143, 144, 101, 0, 53, 58, 145, 145, 3, 3, 3, 99, 100, 101, + 0, 146, 0, 3, 3, 3, 99, 100, 101, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 148, 149, 149, 150, 151, 151, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, + 0, 0, 3, 11, 146, 0, 0, 155, 147, 3, 3, 3, 99, 100, 101, 0, 11, 3, 3, 156, 156, + 157, 157, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 102, 3, 0, 0, 0, 0, 0, 0, 3, 127, 103, 103, 3, 3, 3, 3, + 66, 67, 3, 3, 3, 3, 68, 69, 103, 103, 103, 103, 103, 103, 116, 116, 0, 0, 0, + 0, 116, 116, 116, 116, 116, 116, 0, 0, 120, 120, 120, 120, 158, 158, 3, 3, 3, + 120, 3, 3, 120, 120, 127, 127, 159, 159, 159, 3, 159, 3, 120, 120, 120, 120, + 120, 3, 0, 0, 0, 0, 70, 22, 71, 160, 137, 136, 138, 137, 0, 0, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 3, 3, 0, 161, 101, 99, 100, 0, 0, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 120, 120, 3, 3, 145, 145, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 3, 3, 152, 84, 84, 3, 3, - 84, 84, 3, 3, 153, 153, 153, 153, 3, 0, 0, 0, 0, 153, 153, 153, 153, 153, 153, - 3, 3, 113, 113, 113, 3, 153, 153, 3, 3, 113, 113, 113, 3, 3, 145, 84, 84, 84, - 3, 3, 3, 154, 155, 154, 3, 3, 3, 154, 154, 154, 3, 3, 3, 154, 154, 155, 154, - 3, 3, 3, 154, 3, 3, 3, 3, 3, 3, 3, 3, 113, 113, 0, 145, 145, 145, 145, 145, - 145, 145, 145, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 128, 129, 0, 0, 128, 129, - 0, 0, 128, 129, 0, 129, 84, 84, 128, 129, 84, 84, 128, 129, 84, 84, 128, 129, - 0, 0, 128, 129, 0, 0, 128, 129, 0, 129, 3, 3, 99, 100, 0, 0, 10, 10, 10, 10, - 10, 10, 10, 10, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 128, 129, 92, 3, 3, 99, 100, 0, - 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 56, 56, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 0, 0, 0, 0, 0, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, - 156, 0, 0 + 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 3, 3, 163, 84, 84, 3, 3, 84, + 84, 3, 3, 164, 164, 164, 164, 3, 0, 0, 0, 0, 164, 164, 164, 164, 164, 164, 3, + 3, 120, 120, 120, 3, 164, 164, 3, 3, 120, 120, 120, 3, 3, 103, 84, 84, 84, 3, + 3, 3, 165, 166, 165, 3, 3, 3, 165, 165, 165, 3, 3, 3, 165, 165, 166, 165, 3, + 3, 3, 165, 3, 3, 3, 3, 3, 3, 3, 3, 120, 120, 0, 103, 103, 103, 103, 103, 103, + 103, 103, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 139, 141, 0, 0, 139, 141, 0, + 0, 139, 141, 0, 0, 140, 141, 84, 84, 84, 139, 140, 141, 84, 84, 84, 139, 140, + 141, 84, 84, 139, 141, 0, 0, 139, 141, 0, 0, 139, 141, 0, 0, 140, 141, 3, 3, + 3, 99, 100, 101, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 3, 3, 3, 3, 3, 3, + 0, 0, 0, 139, 140, 141, 92, 3, 3, 3, 99, 100, 101, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 56, 56, 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, + 168, 168, 168, 168, 169, 169, 169, 169, 169, 169, 169, 169, 167, 0, 0 }; const InstDB::RWInfo InstDB::rwInfoA[] = { - { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=936x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=1008x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 1 , 0 , 0 , 0 , 0 , 0 } }, // #1 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 1 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #2 [ref=7x] { InstDB::RWInfo::kCategoryGeneric , 2 , { 2 , 3 , 0 , 0 , 0 , 0 } }, // #3 [ref=96x] @@ -3755,7 +3906,7 @@ const InstDB::RWInfo InstDB::rwInfoA[] = { { InstDB::RWInfo::kCategoryGeneric , 5 , { 8 , 9 , 0 , 0 , 0 , 0 } }, // #6 [ref=6x] { InstDB::RWInfo::kCategoryGeneric , 3 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #7 [ref=26x] { InstDB::RWInfo::kCategoryGeneric , 7 , { 12, 13, 0 , 0 , 0 , 0 } }, // #8 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #9 [ref=64x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #9 [ref=75x] { InstDB::RWInfo::kCategoryGeneric , 2 , { 5 , 3 , 0 , 0 , 0 , 0 } }, // #10 [ref=3x] { InstDB::RWInfo::kCategoryGeneric , 8 , { 10, 3 , 0 , 0 , 0 , 0 } }, // #11 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 9 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #12 [ref=1x] @@ -3779,7 +3930,7 @@ const InstDB::RWInfo InstDB::rwInfoA[] = { { InstDB::RWInfo::kCategoryGeneric , 14, { 36, 3 , 0 , 0 , 0 , 0 } }, // #30 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 14, { 37, 3 , 0 , 0 , 0 , 0 } }, // #31 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 5 , { 36, 9 , 0 , 0 , 0 , 0 } }, // #32 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 11, 9 , 0 , 0 , 0 , 0 } }, // #33 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 11, 9 , 0 , 0 , 0 , 0 } }, // #33 [ref=7x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 38, 39, 0 , 0 , 0 , 0 } }, // #34 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 15, { 1 , 40, 0 , 0 , 0 , 0 } }, // #35 [ref=3x] { InstDB::RWInfo::kCategoryGeneric , 16, { 11, 43, 0 , 0 , 0 , 0 } }, // #36 [ref=3x] @@ -3795,7 +3946,7 @@ const InstDB::RWInfo InstDB::rwInfoA[] = { { InstDB::RWInfo::kCategoryGeneric , 23, { 56, 40, 0 , 0 , 0 , 0 } }, // #46 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 24, { 44, 9 , 0 , 0 , 0 , 0 } }, // #47 [ref=4x] { InstDB::RWInfo::kCategoryGeneric , 25, { 35, 7 , 0 , 0 , 0 , 0 } }, // #48 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 26, { 48, 13, 0 , 0 , 0 , 0 } }, // #49 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 26, { 48, 13, 0 , 0 , 0 , 0 } }, // #49 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 40, 0 , 0 , 0 , 0 } }, // #50 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 9 , 0 , 0 , 0 , 0 } }, // #51 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 7 , 0 , 0 , 0 , 0 } }, // #52 [ref=3x] @@ -3821,7 +3972,7 @@ const InstDB::RWInfo InstDB::rwInfoA[] = { { InstDB::RWInfo::kCategoryGeneric , 0 , { 56, 5 , 0 , 0 , 0 , 0 } }, // #72 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 28, { 44, 9 , 0 , 0 , 0 , 0 } }, // #73 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 63, 20, 0 , 0 , 0 , 0 } }, // #74 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 11, 3 , 0 , 0 , 0 , 0 } }, // #75 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 11, 3 , 0 , 0 , 0 , 0 } }, // #75 [ref=6x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 17, 29, 0 , 0 , 0 , 0 } }, // #76 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 11, { 3 , 3 , 0 , 0 , 0 , 0 } }, // #77 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 52, 22, 0 , 0 , 0 , 0 } }, // #78 [ref=1x] @@ -3842,45 +3993,51 @@ const InstDB::RWInfo InstDB::rwInfoA[] = { { InstDB::RWInfo::kCategoryGeneric , 8 , { 74, 3 , 0 , 0 , 0 , 0 } }, // #93 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 43, 0 , 0 , 0 , 0 } }, // #94 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 5 , { 53, 9 , 0 , 0 , 0 , 0 } }, // #95 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 76, 5 , 0 , 0 , 0 , 0 } }, // #96 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 80, 5 , 0 , 0 , 0 , 0 } }, // #96 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 13, { 11, 5 , 0 , 0 , 0 , 0 } }, // #97 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 38, { 74, 77, 0 , 0 , 0 , 0 } }, // #98 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 39, { 11, 7 , 0 , 0 , 0 , 0 } }, // #99 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 40, { 11, 9 , 0 , 0 , 0 , 0 } }, // #100 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 11, { 11, 3 , 0 , 0 , 0 , 0 } }, // #101 [ref=7x] - { InstDB::RWInfo::kCategoryVmov2_1 , 41, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #102 [ref=14x] - { InstDB::RWInfo::kCategoryVmov1_2 , 14, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #103 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 45, { 74, 43, 0 , 0 , 0 , 0 } }, // #104 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 44, 9 , 0 , 0 , 0 , 0 } }, // #105 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #106 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 52, { 11, 3 , 0 , 0 , 0 , 0 } }, // #107 [ref=12x] - { InstDB::RWInfo::kCategoryVmovddup , 34, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #108 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 61, 0 , 0 , 0 , 0 } }, // #109 [ref=2x] - { InstDB::RWInfo::kCategoryVmovmskpd , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #110 [ref=1x] - { InstDB::RWInfo::kCategoryVmovmskps , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #111 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 53, { 35, 7 , 0 , 0 , 0 , 0 } }, // #112 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #113 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 15, { 11, 40, 0 , 0 , 0 , 0 } }, // #114 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 7 , 0 , 0 , 0 , 0 } }, // #115 [ref=6x] - { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 13, 0 , 0 , 0 , 0 } }, // #116 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 3 , 0 , 0 , 0 , 0 } }, // #117 [ref=4x] - { InstDB::RWInfo::kCategoryVmov1_4 , 57, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #118 [ref=6x] - { InstDB::RWInfo::kCategoryVmov1_2 , 42, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #119 [ref=9x] - { InstDB::RWInfo::kCategoryVmov1_8 , 58, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #120 [ref=3x] - { InstDB::RWInfo::kCategoryVmov4_1 , 59, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #121 [ref=4x] - { InstDB::RWInfo::kCategoryVmov8_1 , 60, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #122 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 11, 3 , 0 , 0 , 0 , 0 } }, // #123 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 17, { 44, 9 , 0 , 0 , 0 , 0 } }, // #124 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 32, { 35, 7 , 0 , 0 , 0 , 0 } }, // #125 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 2 , 0 , 0 , 0 , 0 } }, // #126 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 52, { 2 , 2 , 0 , 0 , 0 , 0 } } // #127 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 39, { 74, 81, 0 , 0 , 0 , 0 } }, // #98 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 40, { 11, 7 , 0 , 0 , 0 , 0 } }, // #99 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 41, { 11, 9 , 0 , 0 , 0 , 0 } }, // #100 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 13, 13, 0 , 0 , 0 , 0 } }, // #101 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 11, { 11, 3 , 0 , 0 , 0 , 0 } }, // #102 [ref=7x] + { InstDB::RWInfo::kCategoryVmov2_1 , 42, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #103 [ref=14x] + { InstDB::RWInfo::kCategoryVmov1_2 , 14, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #104 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 10, 3 , 0 , 0 , 0 , 0 } }, // #105 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 42, { 11, 3 , 0 , 0 , 0 , 0 } }, // #106 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 43, { 11, 5 , 0 , 0 , 0 , 0 } }, // #107 [ref=5x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 5 , 0 , 0 , 0 , 0 } }, // #108 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 47, { 74, 43, 0 , 0 , 0 , 0 } }, // #109 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 44, 9 , 0 , 0 , 0 , 0 } }, // #110 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 18, { 2 , 3 , 0 , 0 , 0 , 0 } }, // #111 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 54, { 11, 3 , 0 , 0 , 0 , 0 } }, // #112 [ref=12x] + { InstDB::RWInfo::kCategoryVmovddup , 34, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #113 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 61, 0 , 0 , 0 , 0 } }, // #114 [ref=2x] + { InstDB::RWInfo::kCategoryVmovmskpd , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #115 [ref=1x] + { InstDB::RWInfo::kCategoryVmovmskps , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #116 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 55, { 35, 7 , 0 , 0 , 0 , 0 } }, // #117 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 21, { 48, 13, 0 , 0 , 0 , 0 } }, // #118 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 3 , 3 , 0 , 0 , 0 , 0 } }, // #119 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 15, { 11, 40, 0 , 0 , 0 , 0 } }, // #120 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 11, 7 , 0 , 0 , 0 , 0 } }, // #121 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 11, 13, 0 , 0 , 0 , 0 } }, // #122 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 3 , 0 , 0 , 0 , 0 } }, // #123 [ref=4x] + { InstDB::RWInfo::kCategoryVmov1_4 , 58, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #124 [ref=6x] + { InstDB::RWInfo::kCategoryVmov1_2 , 44, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #125 [ref=9x] + { InstDB::RWInfo::kCategoryVmov1_8 , 59, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #126 [ref=3x] + { InstDB::RWInfo::kCategoryVmov4_1 , 43, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #127 [ref=4x] + { InstDB::RWInfo::kCategoryVmov8_1 , 60, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #128 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 18, { 11, 3 , 0 , 0 , 0 , 0 } }, // #129 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 17, { 44, 9 , 0 , 0 , 0 , 0 } }, // #130 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 32, { 35, 7 , 0 , 0 , 0 , 0 } }, // #131 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 11, { 2 , 2 , 0 , 0 , 0 , 0 } }, // #132 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 54, { 2 , 2 , 0 , 0 , 0 , 0 } } // #133 [ref=1x] }; const InstDB::RWInfo InstDB::rwInfoB[] = { - { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=742x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #0 [ref=775x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 1 , 0 , 0 , 0 , 0 , 0 } }, // #1 [ref=5x] { InstDB::RWInfo::kCategoryGeneric , 3 , { 10, 5 , 0 , 0 , 0 , 0 } }, // #2 [ref=7x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 0 , 0 , 0 } }, // #3 [ref=186x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 0 , 0 , 0 } }, // #3 [ref=193x] { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 3 , 0 , 0 , 0 } }, // #4 [ref=5x] { InstDB::RWInfo::kCategoryGeneric , 3 , { 4 , 5 , 0 , 0 , 0 , 0 } }, // #5 [ref=14x] { InstDB::RWInfo::kCategoryGeneric , 3 , { 4 , 5 , 14, 0 , 0 , 0 } }, // #6 [ref=4x] @@ -3961,7 +4118,7 @@ const InstDB::RWInfo InstDB::rwInfoB[] = { { InstDB::RWInfo::kCategoryGeneric , 0 , { 44, 0 , 0 , 0 , 0 , 0 } }, // #81 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 35, 0 , 0 , 0 , 0 , 0 } }, // #82 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 16, 50, 67, 0 , 0 , 0 } }, // #83 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #84 [ref=16x] + { InstDB::RWInfo::kCategoryGeneric , 2 , { 11, 3 , 0 , 0 , 0 , 0 } }, // #84 [ref=19x] { InstDB::RWInfo::kCategoryGeneric , 4 , { 36, 7 , 0 , 0 , 0 , 0 } }, // #85 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 5 , { 37, 9 , 0 , 0 , 0 , 0 } }, // #86 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 72, 0 , 0 , 0 , 0 , 0 } }, // #87 [ref=1x] @@ -3974,161 +4131,179 @@ const InstDB::RWInfo InstDB::rwInfoB[] = { { InstDB::RWInfo::kCategoryGeneric , 0 , { 75, 43, 43, 0 , 0 , 0 } }, // #94 [ref=5x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 74, 0 , 0 , 0 , 0 , 0 } }, // #95 [ref=1x] { InstDB::RWInfo::kCategoryGeneric , 0 , { 9 , 60, 17, 0 , 0 , 0 } }, // #96 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 75, 43, 43, 43, 43, 5 } }, // #97 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 4 , 5 , 5 , 5 , 5 , 5 } }, // #98 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 75, 76, 77, 77, 77, 5 } }, // #97 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 4 , 78, 79, 79, 79, 5 } }, // #98 [ref=2x] { InstDB::RWInfo::kCategoryGeneric , 36, { 10, 5 , 7 , 0 , 0 , 0 } }, // #99 [ref=8x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 10, 5 , 9 , 0 , 0 , 0 } }, // #100 [ref=9x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 3 , 0 , 0 } }, // #101 [ref=3x] - { InstDB::RWInfo::kCategoryGeneric , 36, { 11, 5 , 7 , 0 , 0 , 0 } }, // #102 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 11, 5 , 9 , 0 , 0 , 0 } }, // #103 [ref=1x] - { InstDB::RWInfo::kCategoryVmov1_2 , 42, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #104 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 36, { 10, 78, 7 , 0 , 0 , 0 } }, // #105 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 43, { 10, 61, 3 , 0 , 0 , 0 } }, // #106 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 43, { 10, 78, 3 , 0 , 0 , 0 } }, // #107 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 10, 61, 9 , 0 , 0 , 0 } }, // #108 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 44, { 10, 5 , 5 , 0 , 0 , 0 } }, // #109 [ref=9x] - { InstDB::RWInfo::kCategoryGeneric , 46, { 10, 77, 0 , 0 , 0 , 0 } }, // #110 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 46, { 10, 3 , 0 , 0 , 0 , 0 } }, // #111 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 47, { 76, 43, 0 , 0 , 0 , 0 } }, // #112 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 2 , 3 , 3 , 0 , 0 , 0 } }, // #113 [ref=60x] - { InstDB::RWInfo::kCategoryGeneric , 36, { 4 , 61, 7 , 0 , 0 , 0 } }, // #114 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 4 , 78, 9 , 0 , 0 , 0 } }, // #115 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 36, { 6 , 7 , 7 , 0 , 0 , 0 } }, // #116 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 8 , 9 , 9 , 0 , 0 , 0 } }, // #117 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 48, { 11, 3 , 3 , 3 , 0 , 0 } }, // #118 [ref=15x] - { InstDB::RWInfo::kCategoryGeneric , 49, { 35, 7 , 7 , 7 , 0 , 0 } }, // #119 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 50, { 44, 9 , 9 , 9 , 0 , 0 } }, // #120 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 36, { 26, 7 , 7 , 0 , 0 , 0 } }, // #121 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 53, 9 , 9 , 0 , 0 , 0 } }, // #122 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 14, { 35, 3 , 0 , 0 , 0 , 0 } }, // #123 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 5 , { 35, 9 , 0 , 0 , 0 , 0 } }, // #124 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #125 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #126 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 18, { 4 , 3 , 4 , 0 , 0 , 0 } }, // #127 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 36, { 10, 61, 7 , 0 , 0 , 0 } }, // #128 [ref=11x] - { InstDB::RWInfo::kCategoryGeneric , 37, { 10, 78, 9 , 0 , 0 , 0 } }, // #129 [ref=13x] - { InstDB::RWInfo::kCategoryGeneric , 44, { 76, 77, 5 , 0 , 0 , 0 } }, // #130 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 44, { 11, 3 , 5 , 0 , 0 , 0 } }, // #131 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 51, { 74, 43, 77, 0 , 0 , 0 } }, // #132 [ref=4x] - { InstDB::RWInfo::kCategoryVmaskmov , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #133 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 0 , 0 , 0 , 0 , 0 } }, // #134 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 0 , 0 , 0 , 0 , 0 } }, // #135 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 61, 61, 0 , 0 , 0 } }, // #136 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 7 , 7 , 0 , 0 , 0 } }, // #137 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 7 , 7 , 0 , 0 , 0 } }, // #138 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 61, 7 , 0 , 0 , 0 } }, // #139 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 61, 7 , 0 , 0 , 0 } }, // #140 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 78, 9 , 0 , 0 , 0 } }, // #141 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 79, 0 , 0 , 0 , 0 , 0 } }, // #142 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 54, { 35, 11, 3 , 3 , 0 , 0 } }, // #143 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 13, { 74, 43, 43, 43, 43, 5 } }, // #144 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 6 , { 35, 3 , 3 , 0 , 0 , 0 } }, // #145 [ref=17x] - { InstDB::RWInfo::kCategoryGeneric , 51, { 76, 77, 77, 0 , 0 , 0 } }, // #146 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 3 , 0 , 0 , 0 } }, // #147 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 7 , { 48, 5 , 0 , 0 , 0 , 0 } }, // #148 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 55, { 10, 5 , 40, 0 , 0 , 0 } }, // #149 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 56, { 10, 5 , 13, 0 , 0 , 0 } }, // #150 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 44, { 10, 5 , 5 , 5 , 0 , 0 } }, // #151 [ref=12x] - { InstDB::RWInfo::kCategoryGeneric , 61, { 10, 5 , 5 , 5 , 0 , 0 } }, // #152 [ref=1x] - { InstDB::RWInfo::kCategoryGeneric , 62, { 10, 5 , 5 , 0 , 0 , 0 } }, // #153 [ref=12x] - { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 5 , 0 , 0 , 0 } }, // #154 [ref=9x] - { InstDB::RWInfo::kCategoryGeneric , 63, { 11, 3 , 0 , 0 , 0 , 0 } }, // #155 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 0 , { 60, 17, 29, 0 , 0 , 0 } }, // #156 [ref=2x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 3 , 60, 17, 0 , 0 , 0 } }, // #157 [ref=4x] - { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 60, 17, 0 , 0 , 0 } } // #158 [ref=8x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 10, 5 , 13, 0 , 0 , 0 } }, // #100 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 10, 5 , 9 , 0 , 0 , 0 } }, // #101 [ref=9x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 11, 3 , 3 , 3 , 0 , 0 } }, // #102 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 35, 3 , 3 , 0 , 0 , 0 } }, // #103 [ref=18x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 11, 5 , 7 , 0 , 0 , 0 } }, // #104 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 35, 13, 13, 0 , 0 , 0 } }, // #105 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 11, 5 , 9 , 0 , 0 , 0 } }, // #106 [ref=1x] + { InstDB::RWInfo::kCategoryVmov1_2 , 44, { 0 , 0 , 0 , 0 , 0 , 0 } }, // #107 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 10, 5 , 5 , 0 , 0 , 0 } }, // #108 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 10, 82, 7 , 0 , 0 , 0 } }, // #109 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 10, 5 , 5 , 0 , 0 , 0 } }, // #110 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 45, { 10, 61, 3 , 0 , 0 , 0 } }, // #111 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 45, { 10, 3 , 3 , 0 , 0 , 0 } }, // #112 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 45, { 10, 82, 3 , 0 , 0 , 0 } }, // #113 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 10, 61, 9 , 0 , 0 , 0 } }, // #114 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 10, 5 , 5 , 0 , 0 , 0 } }, // #115 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 46, { 10, 5 , 5 , 0 , 0 , 0 } }, // #116 [ref=9x] + { InstDB::RWInfo::kCategoryGeneric , 48, { 10, 81, 0 , 0 , 0 , 0 } }, // #117 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 48, { 10, 3 , 0 , 0 , 0 , 0 } }, // #118 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 49, { 80, 43, 0 , 0 , 0 , 0 } }, // #119 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 6 , { 2 , 3 , 3 , 0 , 0 , 0 } }, // #120 [ref=82x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 4 , 5 , 5 , 0 , 0 , 0 } }, // #121 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 4 , 61, 7 , 0 , 0 , 0 } }, // #122 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 4 , 82, 9 , 0 , 0 , 0 } }, // #123 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 6 , 7 , 7 , 0 , 0 , 0 } }, // #124 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 4 , 5 , 5 , 0 , 0 , 0 } }, // #125 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 8 , 9 , 9 , 0 , 0 , 0 } }, // #126 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 50, { 11, 3 , 3 , 3 , 0 , 0 } }, // #127 [ref=15x] + { InstDB::RWInfo::kCategoryGeneric , 51, { 35, 7 , 7 , 7 , 0 , 0 } }, // #128 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 52, { 44, 9 , 9 , 9 , 0 , 0 } }, // #129 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 4 , 5 , 13, 0 , 0 , 0 } }, // #130 [ref=6x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 26, 7 , 7 , 0 , 0 , 0 } }, // #131 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 53, 9 , 9 , 0 , 0 , 0 } }, // #132 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 14, { 35, 3 , 0 , 0 , 0 , 0 } }, // #133 [ref=3x] + { InstDB::RWInfo::kCategoryGeneric , 27, { 35, 13, 0 , 0 , 0 , 0 } }, // #134 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 5 , { 35, 9 , 0 , 0 , 0 , 0 } }, // #135 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #136 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 2 , 3 , 2 , 0 , 0 , 0 } }, // #137 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 18, { 4 , 3 , 4 , 0 , 0 , 0 } }, // #138 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 36, { 10, 61, 7 , 0 , 0 , 0 } }, // #139 [ref=11x] + { InstDB::RWInfo::kCategoryGeneric , 37, { 10, 83, 13, 0 , 0 , 0 } }, // #140 [ref=7x] + { InstDB::RWInfo::kCategoryGeneric , 38, { 10, 82, 9 , 0 , 0 , 0 } }, // #141 [ref=13x] + { InstDB::RWInfo::kCategoryGeneric , 46, { 80, 81, 5 , 0 , 0 , 0 } }, // #142 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 46, { 11, 3 , 5 , 0 , 0 , 0 } }, // #143 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 53, { 74, 43, 81, 0 , 0 , 0 } }, // #144 [ref=4x] + { InstDB::RWInfo::kCategoryVmaskmov , 0 , { 0 , 0 , 0 , 0 , 0 , 0 } }, // #145 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 35, 0 , 0 , 0 , 0 , 0 } }, // #146 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 22, 0 , 0 , 0 , 0 , 0 } }, // #147 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 61, 61, 0 , 0 , 0 } }, // #148 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 7 , 7 , 0 , 0 , 0 } }, // #149 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 7 , 7 , 0 , 0 , 0 } }, // #150 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 12, { 10, 61, 7 , 0 , 0 , 0 } }, // #151 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 61, 7 , 0 , 0 , 0 } }, // #152 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 83, 13, 0 , 0 , 0 } }, // #153 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 10, 82, 9 , 0 , 0 , 0 } }, // #154 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 84, 0 , 0 , 0 , 0 , 0 } }, // #155 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 56, { 85, 86, 3 , 3 , 0 , 0 } }, // #156 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 13, { 74, 76, 77, 77, 77, 5 } }, // #157 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 53, { 80, 81, 81, 0 , 0 , 0 } }, // #158 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 3 , 0 , 0 , 0 } }, // #159 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 7 , { 48, 5 , 0 , 0 , 0 , 0 } }, // #160 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 57, { 10, 5 , 40, 0 , 0 , 0 } }, // #161 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 46, { 10, 5 , 5 , 5 , 0 , 0 } }, // #162 [ref=12x] + { InstDB::RWInfo::kCategoryGeneric , 61, { 10, 5 , 5 , 5 , 0 , 0 } }, // #163 [ref=1x] + { InstDB::RWInfo::kCategoryGeneric , 62, { 10, 5 , 5 , 0 , 0 , 0 } }, // #164 [ref=12x] + { InstDB::RWInfo::kCategoryGeneric , 22, { 11, 3 , 5 , 0 , 0 , 0 } }, // #165 [ref=9x] + { InstDB::RWInfo::kCategoryGeneric , 63, { 11, 3 , 0 , 0 , 0 , 0 } }, // #166 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 0 , { 60, 17, 29, 0 , 0 , 0 } }, // #167 [ref=2x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 3 , 60, 17, 0 , 0 , 0 } }, // #168 [ref=4x] + { InstDB::RWInfo::kCategoryGeneric , 8 , { 11, 60, 17, 0 , 0 , 0 } } // #169 [ref=8x] }; const InstDB::RWInfoOp InstDB::rwInfoOp[] = { - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, { 0 }, 0 }, // #0 [ref=15529x] - { 0x0000000000000003u, 0x0000000000000003u, 0x00, { 0 }, OpRWInfo::kRW | OpRWInfo::kRegPhysId }, // #1 [ref=10x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt }, // #2 [ref=214x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #3 [ref=987x] - { 0x000000000000FFFFu, 0x000000000000FFFFu, 0xFF, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt }, // #4 [ref=92x] - { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #5 [ref=305x] - { 0x00000000000000FFu, 0x00000000000000FFu, 0xFF, { 0 }, OpRWInfo::kRW }, // #6 [ref=18x] - { 0x00000000000000FFu, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #7 [ref=186x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, { 0 }, OpRWInfo::kRW }, // #8 [ref=18x] - { 0x000000000000000Fu, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #9 [ref=136x] - { 0x0000000000000000u, 0x000000000000FFFFu, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #10 [ref=160x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #11 [ref=420x] - { 0x0000000000000003u, 0x0000000000000003u, 0xFF, { 0 }, OpRWInfo::kRW }, // #12 [ref=1x] - { 0x0000000000000003u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #13 [ref=34x] - { 0x000000000000FFFFu, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #14 [ref=4x] - { 0x0000000000000000u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kMemBaseWrite | OpRWInfo::kMemIndexWrite }, // #15 [ref=1x] - { 0x0000000000000000u, 0x000000000000000Fu, 0x02, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #16 [ref=9x] - { 0x000000000000000Fu, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #17 [ref=23x] - { 0x00000000000000FFu, 0x00000000000000FFu, 0x00, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #18 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kMemPhysId }, // #19 [ref=3x] - { 0x0000000000000000u, 0x0000000000000000u, 0x06, { 0 }, OpRWInfo::kRead | OpRWInfo::kMemBaseRW | OpRWInfo::kMemBasePostModify | OpRWInfo::kMemPhysId }, // #20 [ref=3x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, { 0 }, OpRWInfo::kRead | OpRWInfo::kMemBaseRW | OpRWInfo::kMemBasePostModify | OpRWInfo::kMemPhysId }, // #21 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #22 [ref=7x] - { 0x00000000000000FFu, 0x00000000000000FFu, 0x02, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #23 [ref=1x] - { 0x00000000000000FFu, 0x0000000000000000u, 0x01, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #24 [ref=1x] - { 0x00000000000000FFu, 0x0000000000000000u, 0x03, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #25 [ref=1x] - { 0x00000000000000FFu, 0x00000000000000FFu, 0xFF, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt }, // #26 [ref=21x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0x02, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #27 [ref=1x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0x00, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #28 [ref=4x] - { 0x000000000000000Fu, 0x0000000000000000u, 0x01, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #29 [ref=13x] - { 0x000000000000000Fu, 0x0000000000000000u, 0x03, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #30 [ref=2x] - { 0x0000000000000000u, 0x000000000000000Fu, 0x03, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #31 [ref=1x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0x01, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #32 [ref=1x] - { 0x0000000000000000u, 0x00000000000000FFu, 0x02, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #33 [ref=1x] - { 0x00000000000000FFu, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #34 [ref=1x] - { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #35 [ref=80x] - { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, { 0 }, OpRWInfo::kWrite }, // #36 [ref=6x] - { 0x0000000000000000u, 0x000000000000000Fu, 0xFF, { 0 }, OpRWInfo::kWrite }, // #37 [ref=6x] - { 0x0000000000000000u, 0x0000000000000003u, 0x02, { 0 }, OpRWInfo::kWrite | OpRWInfo::kRegPhysId }, // #38 [ref=1x] - { 0x0000000000000003u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #39 [ref=1x] - { 0x0000000000000001u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #40 [ref=28x] - { 0x0000000000000000u, 0x0000000000000000u, 0x02, { 0 }, OpRWInfo::kRW | OpRWInfo::kRegPhysId | OpRWInfo::kZExt }, // #41 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRW | OpRWInfo::kRegPhysId | OpRWInfo::kZExt }, // #42 [ref=3x] - { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #43 [ref=45x] - { 0x0000000000000000u, 0x000000000000000Fu, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #44 [ref=30x] - { 0x00000000000003FFu, 0x00000000000003FFu, 0xFF, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt }, // #45 [ref=22x] - { 0x00000000000003FFu, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #46 [ref=13x] - { 0x0000000000000000u, 0x00000000000003FFu, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #47 [ref=1x] - { 0x0000000000000000u, 0x0000000000000003u, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #48 [ref=15x] - { 0x0000000000000000u, 0x0000000000000003u, 0x00, { 0 }, OpRWInfo::kWrite | OpRWInfo::kRegPhysId | OpRWInfo::kZExt }, // #49 [ref=2x] - { 0x0000000000000000u, 0x000000000000000Fu, 0x00, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #50 [ref=8x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kWrite | OpRWInfo::kRegPhysId | OpRWInfo::kZExt }, // #51 [ref=2x] - { 0x0000000000000003u, 0x0000000000000000u, 0x02, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #52 [ref=4x] - { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt }, // #53 [ref=4x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kMemPhysId }, // #54 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x01, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #55 [ref=1x] - { 0x0000000000000000u, 0x0000000000000001u, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #56 [ref=14x] - { 0x0000000000000000u, 0x0000000000000001u, 0x00, { 0 }, OpRWInfo::kWrite | OpRWInfo::kRegPhysId }, // #57 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x01, { 0 }, OpRWInfo::kRW | OpRWInfo::kRegPhysId | OpRWInfo::kZExt }, // #58 [ref=3x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kMemPhysId }, // #59 [ref=3x] - { 0x000000000000000Fu, 0x0000000000000000u, 0x02, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #60 [ref=22x] - { 0x000000000000FF00u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #61 [ref=23x] - { 0x0000000000000000u, 0x000000000000FF00u, 0xFF, { 0 }, OpRWInfo::kWrite }, // #62 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x07, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kMemBaseRW | OpRWInfo::kMemBasePostModify | OpRWInfo::kMemPhysId }, // #63 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x02, { 0 }, OpRWInfo::kWrite | OpRWInfo::kRegPhysId | OpRWInfo::kZExt }, // #64 [ref=1x] - { 0x0000000000000000u, 0x0000000000000000u, 0x02, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #65 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x06, { 0 }, OpRWInfo::kRead | OpRWInfo::kMemPhysId }, // #66 [ref=1x] - { 0x0000000000000000u, 0x000000000000000Fu, 0x01, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #67 [ref=5x] - { 0x0000000000000000u, 0x000000000000FFFFu, 0x00, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #68 [ref=4x] - { 0x0000000000000000u, 0x0000000000000007u, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #69 [ref=2x] - { 0x0000000000000000u, 0x0000000000000000u, 0x04, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt | OpRWInfo::kRegPhysId }, // #70 [ref=1x] - { 0x0000000000000001u, 0x0000000000000000u, 0x01, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #71 [ref=10x] - { 0x0000000000000001u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRead | OpRWInfo::kRegPhysId }, // #72 [ref=1x] - { 0x0000000000000000u, 0x0000000000000001u, 0xFF, { 0 }, OpRWInfo::kWrite }, // #73 [ref=30x] - { 0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #74 [ref=20x] - { 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFF, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt }, // #75 [ref=7x] - { 0x0000000000000000u, 0x00000000FFFFFFFFu, 0xFF, { 0 }, OpRWInfo::kWrite | OpRWInfo::kZExt }, // #76 [ref=10x] - { 0x00000000FFFFFFFFu, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #77 [ref=16x] - { 0x000000000000FFF0u, 0x0000000000000000u, 0xFF, { 0 }, OpRWInfo::kRead }, // #78 [ref=18x] - { 0x0000000000000000u, 0x0000000000000000u, 0x00, { 0 }, OpRWInfo::kRW | OpRWInfo::kZExt | OpRWInfo::kRegPhysId } // #79 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kNone }, // #0 [ref=16519x] + { 0x0000000000000003u, 0x0000000000000003u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId }, // #1 [ref=10x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #2 [ref=236x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #3 [ref=1077x] + { 0x000000000000FFFFu, 0x000000000000FFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #4 [ref=108x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #5 [ref=348x] + { 0x00000000000000FFu, 0x00000000000000FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW }, // #6 [ref=18x] + { 0x00000000000000FFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #7 [ref=186x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kRW }, // #8 [ref=18x] + { 0x000000000000000Fu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #9 [ref=135x] + { 0x0000000000000000u, 0x000000000000FFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #10 [ref=184x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #11 [ref=455x] + { 0x0000000000000003u, 0x0000000000000003u, 0xFF, 0, { 0 }, OpRWFlags::kRW }, // #12 [ref=1x] + { 0x0000000000000003u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #13 [ref=63x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #14 [ref=4x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemBaseWrite | OpRWFlags::kMemIndexWrite }, // #15 [ref=1x] + { 0x0000000000000000u, 0x000000000000000Fu, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #16 [ref=9x] + { 0x000000000000000Fu, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #17 [ref=23x] + { 0x00000000000000FFu, 0x00000000000000FFu, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #18 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #19 [ref=3x] + { 0x0000000000000000u, 0x0000000000000000u, 0x06, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #20 [ref=3x] + { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #21 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #22 [ref=7x] + { 0x00000000000000FFu, 0x00000000000000FFu, 0x02, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #23 [ref=1x] + { 0x00000000000000FFu, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #24 [ref=1x] + { 0x00000000000000FFu, 0x0000000000000000u, 0x03, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #25 [ref=1x] + { 0x00000000000000FFu, 0x00000000000000FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #26 [ref=21x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0x02, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #27 [ref=1x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #28 [ref=4x] + { 0x000000000000000Fu, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #29 [ref=13x] + { 0x000000000000000Fu, 0x0000000000000000u, 0x03, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #30 [ref=2x] + { 0x0000000000000000u, 0x000000000000000Fu, 0x03, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #31 [ref=1x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0x01, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #32 [ref=1x] + { 0x0000000000000000u, 0x00000000000000FFu, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #33 [ref=1x] + { 0x00000000000000FFu, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #34 [ref=1x] + { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #35 [ref=82x] + { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #36 [ref=6x] + { 0x0000000000000000u, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #37 [ref=6x] + { 0x0000000000000000u, 0x0000000000000003u, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId }, // #38 [ref=1x] + { 0x0000000000000003u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #39 [ref=1x] + { 0x0000000000000001u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #40 [ref=28x] + { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #41 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #42 [ref=3x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #43 [ref=29x] + { 0x0000000000000000u, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #44 [ref=30x] + { 0x00000000000003FFu, 0x00000000000003FFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #45 [ref=22x] + { 0x00000000000003FFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #46 [ref=13x] + { 0x0000000000000000u, 0x00000000000003FFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #47 [ref=1x] + { 0x0000000000000000u, 0x0000000000000003u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #48 [ref=17x] + { 0x0000000000000000u, 0x0000000000000003u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #49 [ref=2x] + { 0x0000000000000000u, 0x000000000000000Fu, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #50 [ref=8x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #51 [ref=2x] + { 0x0000000000000003u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #52 [ref=4x] + { 0x000000000000000Fu, 0x000000000000000Fu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #53 [ref=4x] + { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #54 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #55 [ref=1x] + { 0x0000000000000000u, 0x0000000000000001u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #56 [ref=14x] + { 0x0000000000000000u, 0x0000000000000001u, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId }, // #57 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #58 [ref=3x] + { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kMemPhysId }, // #59 [ref=3x] + { 0x000000000000000Fu, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #60 [ref=22x] + { 0x000000000000FF00u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #61 [ref=23x] + { 0x0000000000000000u, 0x000000000000FF00u, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #62 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x07, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kMemBaseRW | OpRWFlags::kMemBasePostModify | OpRWFlags::kMemPhysId }, // #63 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kRegPhysId | OpRWFlags::kZExt }, // #64 [ref=1x] + { 0x0000000000000000u, 0x0000000000000000u, 0x02, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #65 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x06, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kMemPhysId }, // #66 [ref=1x] + { 0x0000000000000000u, 0x000000000000000Fu, 0x01, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #67 [ref=5x] + { 0x0000000000000000u, 0x000000000000FFFFu, 0x00, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #68 [ref=4x] + { 0x0000000000000000u, 0x0000000000000007u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #69 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0x04, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #70 [ref=1x] + { 0x0000000000000001u, 0x0000000000000000u, 0x01, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #71 [ref=10x] + { 0x0000000000000001u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kRegPhysId }, // #72 [ref=1x] + { 0x0000000000000000u, 0x0000000000000001u, 0xFF, 0, { 0 }, OpRWFlags::kWrite }, // #73 [ref=30x] + { 0x0000000000000000u, 0xFFFFFFFFFFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #74 [ref=20x] + { 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt }, // #75 [ref=7x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 4, { 0 }, OpRWFlags::kRead }, // #76 [ref=4x] + { 0xFFFFFFFFFFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kConsecutive }, // #77 [ref=12x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 4, { 0 }, OpRWFlags::kRead }, // #78 [ref=2x] + { 0x000000000000FFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead | OpRWFlags::kConsecutive }, // #79 [ref=6x] + { 0x0000000000000000u, 0x00000000FFFFFFFFu, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #80 [ref=10x] + { 0x00000000FFFFFFFFu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #81 [ref=16x] + { 0x000000000000FFF0u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #82 [ref=18x] + { 0x000000000000FFFCu, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kRead }, // #83 [ref=8x] + { 0x0000000000000000u, 0x0000000000000000u, 0x00, 0, { 0 }, OpRWFlags::kRW | OpRWFlags::kZExt | OpRWFlags::kRegPhysId }, // #84 [ref=1x] + { 0x0000000000000000u, 0x00000000000000FFu, 0xFF, 2, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt }, // #85 [ref=2x] + { 0x0000000000000000u, 0x0000000000000000u, 0xFF, 0, { 0 }, OpRWFlags::kWrite | OpRWFlags::kZExt | OpRWFlags::kConsecutive } // #86 [ref=2x] }; const InstDB::RWInfoRm InstDB::rwInfoRm[] = { - { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , 0, 0 }, // #0 [ref=1894x] + { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , 0, 0 }, // #0 [ref=2000x] { InstDB::RWInfoRm::kCategoryConsistent, 0x03, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #1 [ref=8x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , 0, 0 }, // #2 [ref=190x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , 0, 0 }, // #2 [ref=204x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 16, 0, 0 }, // #3 [ref=122x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 8 , 0, 0 }, // #4 [ref=66x] - { InstDB::RWInfoRm::kCategoryFixed , 0x02, 4 , 0, 0 }, // #5 [ref=36x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , 0, 0 }, // #6 [ref=270x] + { InstDB::RWInfoRm::kCategoryFixed , 0x02, 4 , 0, 0 }, // #5 [ref=35x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , 0, 0 }, // #6 [ref=300x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 2 , 0, 0 }, // #7 [ref=9x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 0 , 0, 0 }, // #8 [ref=63x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 0 , 0, 0 }, // #9 [ref=1x] @@ -4136,78 +4311,76 @@ const InstDB::RWInfoRm InstDB::rwInfoRm[] = { { InstDB::RWInfoRm::kCategoryConsistent, 0x01, 0 , 0, 0 }, // #11 [ref=14x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 8 , 0, 0 }, // #12 [ref=22x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 16, 0, 0 }, // #13 [ref=21x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #14 [ref=15x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #14 [ref=22x] { InstDB::RWInfoRm::kCategoryFixed , 0x02, 1 , 0, 0 }, // #15 [ref=5x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 64, 0, 0 }, // #16 [ref=5x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 4 , 0, 0 }, // #17 [ref=6x] { InstDB::RWInfoRm::kCategoryNone , 0x00, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #18 [ref=26x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 10, 0, 0 }, // #19 [ref=2x] { InstDB::RWInfoRm::kCategoryNone , 0x01, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #20 [ref=5x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 2 , 0, 0 }, // #21 [ref=3x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 2 , 0, 0 }, // #21 [ref=4x] { InstDB::RWInfoRm::kCategoryConsistent, 0x06, 0 , 0, 0 }, // #22 [ref=14x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 1 , 0, 0 }, // #23 [ref=1x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 4 , 0, 0 }, // #24 [ref=4x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 8 , 0, 0 }, // #25 [ref=3x] - { InstDB::RWInfoRm::kCategoryFixed , 0x03, 2 , 0, 0 }, // #26 [ref=1x] - { InstDB::RWInfoRm::kCategoryFixed , 0x02, 2 , 0, 0 }, // #27 [ref=6x] + { InstDB::RWInfoRm::kCategoryFixed , 0x03, 2 , 0, 0 }, // #26 [ref=2x] + { InstDB::RWInfoRm::kCategoryFixed , 0x02, 2 , 0, 0 }, // #27 [ref=13x] { InstDB::RWInfoRm::kCategoryFixed , 0x00, 4 , 0, 0 }, // #28 [ref=6x] { InstDB::RWInfoRm::kCategoryNone , 0x03, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #29 [ref=1x] { InstDB::RWInfoRm::kCategoryFixed , 0x03, 16, 0, 0 }, // #30 [ref=6x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 1 , 0, 0 }, // #31 [ref=32x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 8 , 0, 0 }, // #32 [ref=4x] - { InstDB::RWInfoRm::kCategoryFixed , 0x01, 2 , 0, Features::kSSE4_1 }, // #33 [ref=1x] + { InstDB::RWInfoRm::kCategoryFixed , 0x01, 2 , 0, uint32_t(CpuFeatures::X86::kSSE4_1) }, // #33 [ref=1x] { InstDB::RWInfoRm::kCategoryNone , 0x02, 0 , 0, 0 }, // #34 [ref=4x] { InstDB::RWInfoRm::kCategoryFixed , 0x01, 2 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #35 [ref=3x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 8 , 0, 0 }, // #36 [ref=34x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 4 , 0, 0 }, // #37 [ref=37x] - { InstDB::RWInfoRm::kCategoryFixed , 0x00, 32, 0, 0 }, // #38 [ref=4x] - { InstDB::RWInfoRm::kCategoryFixed , 0x02, 8 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #39 [ref=1x] - { InstDB::RWInfoRm::kCategoryFixed , 0x02, 4 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #40 [ref=1x] - { InstDB::RWInfoRm::kCategoryHalf , 0x02, 0 , 0, 0 }, // #41 [ref=14x] - { InstDB::RWInfoRm::kCategoryHalf , 0x01, 0 , 0, 0 }, // #42 [ref=10x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #43 [ref=4x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 16, 0, 0 }, // #44 [ref=27x] - { InstDB::RWInfoRm::kCategoryFixed , 0x02, 64, 0, 0 }, // #45 [ref=6x] - { InstDB::RWInfoRm::kCategoryFixed , 0x01, 16, 0, 0 }, // #46 [ref=6x] - { InstDB::RWInfoRm::kCategoryFixed , 0x01, 32, 0, 0 }, // #47 [ref=4x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x0C, 0 , 0, 0 }, // #48 [ref=15x] - { InstDB::RWInfoRm::kCategoryFixed , 0x0C, 8 , 0, 0 }, // #49 [ref=4x] - { InstDB::RWInfoRm::kCategoryFixed , 0x0C, 4 , 0, 0 }, // #50 [ref=4x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 32, 0, 0 }, // #51 [ref=6x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x03, 0 , 0, 0 }, // #52 [ref=13x] - { InstDB::RWInfoRm::kCategoryFixed , 0x03, 8 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #53 [ref=1x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x08, 0 , 0, 0 }, // #54 [ref=2x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 1 , 0, 0 }, // #55 [ref=1x] - { InstDB::RWInfoRm::kCategoryFixed , 0x04, 2 , 0, 0 }, // #56 [ref=1x] - { InstDB::RWInfoRm::kCategoryQuarter , 0x01, 0 , 0, 0 }, // #57 [ref=6x] - { InstDB::RWInfoRm::kCategoryEighth , 0x01, 0 , 0, 0 }, // #58 [ref=3x] - { InstDB::RWInfoRm::kCategoryQuarter , 0x02, 0 , 0, 0 }, // #59 [ref=4x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 8 , 0, 0 }, // #36 [ref=35x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 2 , 0, 0 }, // #37 [ref=30x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 4 , 0, 0 }, // #38 [ref=42x] + { InstDB::RWInfoRm::kCategoryFixed , 0x00, 32, 0, 0 }, // #39 [ref=4x] + { InstDB::RWInfoRm::kCategoryFixed , 0x02, 8 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #40 [ref=1x] + { InstDB::RWInfoRm::kCategoryFixed , 0x02, 4 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #41 [ref=1x] + { InstDB::RWInfoRm::kCategoryHalf , 0x02, 0 , 0, 0 }, // #42 [ref=19x] + { InstDB::RWInfoRm::kCategoryQuarter , 0x02, 0 , 0, 0 }, // #43 [ref=9x] + { InstDB::RWInfoRm::kCategoryHalf , 0x01, 0 , 0, 0 }, // #44 [ref=10x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x04, 0 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #45 [ref=6x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 16, 0, 0 }, // #46 [ref=27x] + { InstDB::RWInfoRm::kCategoryFixed , 0x02, 64, 0, 0 }, // #47 [ref=6x] + { InstDB::RWInfoRm::kCategoryFixed , 0x01, 16, 0, 0 }, // #48 [ref=6x] + { InstDB::RWInfoRm::kCategoryFixed , 0x01, 32, 0, 0 }, // #49 [ref=4x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x0C, 0 , 0, 0 }, // #50 [ref=15x] + { InstDB::RWInfoRm::kCategoryFixed , 0x0C, 8 , 0, 0 }, // #51 [ref=4x] + { InstDB::RWInfoRm::kCategoryFixed , 0x0C, 4 , 0, 0 }, // #52 [ref=4x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 32, 0, 0 }, // #53 [ref=6x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x03, 0 , 0, 0 }, // #54 [ref=13x] + { InstDB::RWInfoRm::kCategoryFixed , 0x03, 8 , InstDB::RWInfoRm::kFlagAmbiguous, 0 }, // #55 [ref=1x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x08, 0 , 0, 0 }, // #56 [ref=2x] + { InstDB::RWInfoRm::kCategoryFixed , 0x04, 1 , 0, 0 }, // #57 [ref=1x] + { InstDB::RWInfoRm::kCategoryQuarter , 0x01, 0 , 0, 0 }, // #58 [ref=6x] + { InstDB::RWInfoRm::kCategoryEighth , 0x01, 0 , 0, 0 }, // #59 [ref=3x] { InstDB::RWInfoRm::kCategoryEighth , 0x02, 0 , 0, 0 }, // #60 [ref=2x] { InstDB::RWInfoRm::kCategoryFixed , 0x0C, 16, 0, 0 }, // #61 [ref=1x] { InstDB::RWInfoRm::kCategoryFixed , 0x06, 16, 0, 0 }, // #62 [ref=12x] - { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , 0, Features::kAVX512_BW } // #63 [ref=2x] + { InstDB::RWInfoRm::kCategoryConsistent, 0x02, 0 , 0, uint32_t(CpuFeatures::X86::kAVX512_BW) } // #63 [ref=2x] }; // ---------------------------------------------------------------------------- // ${InstRWInfoTable:End} -// ============================================================================ -// [asmjit::x86::InstDB - Unit] -// ============================================================================ +// x86::InstDB - Tests +// =================== #if defined(ASMJIT_TEST) UNIT(x86_inst_db) { INFO("Checking validity of Inst enums"); // Cross-validate prefixes. - EXPECT(Inst::kOptionRex == 0x40000000u, "REX prefix must be at 0x40000000"); - EXPECT(Inst::kOptionVex3 == 0x00000400u, "VEX3 prefix must be at 0x00000400"); - EXPECT(Inst::kOptionEvex == 0x00001000u, "EVEX prefix must be at 0x00001000"); + EXPECT(uint32_t(InstOptions::kX86_Rex ) == 0x40000000u, "REX prefix must be at 0x40000000"); + EXPECT(uint32_t(InstOptions::kX86_Evex) == 0x00001000u, "EVEX prefix must be at 0x00001000"); // These could be combined together to form a valid REX prefix, they must match. - EXPECT(uint32_t(Inst::kOptionOpCodeB) == uint32_t(Opcode::kB), "Opcode::kB must match Inst::kOptionOpCodeB"); - EXPECT(uint32_t(Inst::kOptionOpCodeX) == uint32_t(Opcode::kX), "Opcode::kX must match Inst::kOptionOpCodeX"); - EXPECT(uint32_t(Inst::kOptionOpCodeR) == uint32_t(Opcode::kR), "Opcode::kR must match Inst::kOptionOpCodeR"); - EXPECT(uint32_t(Inst::kOptionOpCodeW) == uint32_t(Opcode::kW), "Opcode::kW must match Inst::kOptionOpCodeW"); + EXPECT(uint32_t(InstOptions::kX86_OpCodeB) == uint32_t(Opcode::kB), "Opcode::kB must match InstOptions::kX86_OpCodeB"); + EXPECT(uint32_t(InstOptions::kX86_OpCodeX) == uint32_t(Opcode::kX), "Opcode::kX must match InstOptions::kX86_OpCodeX"); + EXPECT(uint32_t(InstOptions::kX86_OpCodeR) == uint32_t(Opcode::kR), "Opcode::kR must match InstOptions::kX86_OpCodeR"); + EXPECT(uint32_t(InstOptions::kX86_OpCodeW) == uint32_t(Opcode::kW), "Opcode::kW must match InstOptions::kX86_OpCodeW"); uint32_t rex_rb = (Opcode::kR >> Opcode::kREX_Shift) | (Opcode::kB >> Opcode::kREX_Shift) | 0x40; uint32_t rex_rw = (Opcode::kR >> Opcode::kREX_Shift) | (Opcode::kW >> Opcode::kREX_Shift) | 0x40; diff --git a/src/asmjit/x86/x86instdb.h b/src/asmjit/x86/x86instdb.h index 4c86c9f..9911289 100644 --- a/src/asmjit/x86/x86instdb.h +++ b/src/asmjit/x86/x86instdb.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86INSTDB_H_INCLUDED #define ASMJIT_X86_X86INSTDB_H_INCLUDED @@ -34,241 +16,318 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! Instruction database (X86). namespace InstDB { -// ============================================================================ -// [asmjit::x86::InstDB::Mode] -// ============================================================================ - -//! Describes which mode is supported by an instruction or instruction signature. -enum Mode : uint32_t { +//! Describes which operation mode is supported by an instruction. +enum class Mode : uint8_t { //! Invalid mode. - kModeNone = 0x00u, + kNone = 0x00u, //! X86 mode supported. - kModeX86 = 0x01u, + kX86 = 0x01u, //! X64 mode supported. - kModeX64 = 0x02u, + kX64 = 0x02u, //! Both X86 and X64 modes supported. - kModeAny = 0x03u + kAny = 0x03u }; +ASMJIT_DEFINE_ENUM_FLAGS(Mode) -static constexpr uint32_t modeFromArch(uint32_t arch) noexcept { - return arch == Environment::kArchX86 ? kModeX86 : - arch == Environment::kArchX64 ? kModeX64 : kModeNone; +//! Converts architecture to operation mode, see \ref Mode. +static constexpr Mode modeFromArch(Arch arch) noexcept { + return arch == Arch::kX86 ? Mode::kX86 : + arch == Arch::kX64 ? Mode::kX64 : Mode::kNone; } -// ============================================================================ -// [asmjit::x86::InstDB::OpFlags] -// ============================================================================ - -//! Operand flags (X86). -enum OpFlags : uint32_t { - kOpNone = 0x00000000u, //!< No flags. - - kOpGpbLo = 0x00000001u, //!< Operand can be low 8-bit GPB register. - kOpGpbHi = 0x00000002u, //!< Operand can be high 8-bit GPB register. - kOpGpw = 0x00000004u, //!< Operand can be 16-bit GPW register. - kOpGpd = 0x00000008u, //!< Operand can be 32-bit GPD register. - kOpGpq = 0x00000010u, //!< Operand can be 64-bit GPQ register. - kOpXmm = 0x00000020u, //!< Operand can be 128-bit XMM register. - kOpYmm = 0x00000040u, //!< Operand can be 256-bit YMM register. - kOpZmm = 0x00000080u, //!< Operand can be 512-bit ZMM register. - kOpMm = 0x00000100u, //!< Operand can be 64-bit MM register. - kOpKReg = 0x00000200u, //!< Operand can be 64-bit K register. - kOpSReg = 0x00000400u, //!< Operand can be SReg (segment register). - kOpCReg = 0x00000800u, //!< Operand can be CReg (control register). - kOpDReg = 0x00001000u, //!< Operand can be DReg (debug register). - kOpSt = 0x00002000u, //!< Operand can be 80-bit ST register (X87). - kOpBnd = 0x00004000u, //!< Operand can be 128-bit BND register. - kOpTmm = 0x00008000u, //!< Operand can be 0..8192-bit TMM register. - kOpAllRegs = 0x0000FFFFu, //!< Combination of all possible registers. - - kOpI4 = 0x00010000u, //!< Operand can be unsigned 4-bit immediate. - kOpU4 = 0x00020000u, //!< Operand can be unsigned 4-bit immediate. - kOpI8 = 0x00040000u, //!< Operand can be signed 8-bit immediate. - kOpU8 = 0x00080000u, //!< Operand can be unsigned 8-bit immediate. - kOpI16 = 0x00100000u, //!< Operand can be signed 16-bit immediate. - kOpU16 = 0x00200000u, //!< Operand can be unsigned 16-bit immediate. - kOpI32 = 0x00400000u, //!< Operand can be signed 32-bit immediate. - kOpU32 = 0x00800000u, //!< Operand can be unsigned 32-bit immediate. - kOpI64 = 0x01000000u, //!< Operand can be signed 64-bit immediate. - kOpU64 = 0x02000000u, //!< Operand can be unsigned 64-bit immediate. - kOpAllImm = 0x03FF0000u, //!< Operand can be any immediate. - - kOpMem = 0x04000000u, //!< Operand can be a scalar memory pointer. - kOpVm = 0x08000000u, //!< Operand can be a vector memory pointer. - - kOpRel8 = 0x10000000u, //!< Operand can be relative 8-bit displacement. - kOpRel32 = 0x20000000u, //!< Operand can be relative 32-bit displacement. - - kOpImplicit = 0x80000000u //!< Operand is implicit. -}; - -// ============================================================================ -// [asmjit::x86::InstDB::MemFlags] -// ============================================================================ - -//! Memory operand flags (X86). -enum MemFlags : uint32_t { - // NOTE: Instruction uses either scalar or vector memory operands, they never - // collide. This allows us to share bits between "M" and "Vm" enums. - - kMemOpAny = 0x0001u, //!< Operand can be any scalar memory pointer. - kMemOpM8 = 0x0002u, //!< Operand can be an 8-bit memory pointer. - kMemOpM16 = 0x0004u, //!< Operand can be a 16-bit memory pointer. - kMemOpM32 = 0x0008u, //!< Operand can be a 32-bit memory pointer. - kMemOpM48 = 0x0010u, //!< Operand can be a 48-bit memory pointer (FAR pointers only). - kMemOpM64 = 0x0020u, //!< Operand can be a 64-bit memory pointer. - kMemOpM80 = 0x0040u, //!< Operand can be an 80-bit memory pointer. - kMemOpM128 = 0x0080u, //!< Operand can be a 128-bit memory pointer. - kMemOpM256 = 0x0100u, //!< Operand can be a 256-bit memory pointer. - kMemOpM512 = 0x0200u, //!< Operand can be a 512-bit memory pointer. - kMemOpM1024 = 0x0400u, //!< Operand can be a 1024-bit memory pointer. - - kMemOpVm32x = 0x0002u, //!< Operand can be a vm32x (vector) pointer. - kMemOpVm32y = 0x0004u, //!< Operand can be a vm32y (vector) pointer. - kMemOpVm32z = 0x0008u, //!< Operand can be a vm32z (vector) pointer. - kMemOpVm64x = 0x0020u, //!< Operand can be a vm64x (vector) pointer. - kMemOpVm64y = 0x0040u, //!< Operand can be a vm64y (vector) pointer. - kMemOpVm64z = 0x0080u, //!< Operand can be a vm64z (vector) pointer. - - kMemOpBaseOnly = 0x0800u, //!< Only memory base is allowed (no index, no offset). - kMemOpDs = 0x1000u, //!< Implicit memory operand's DS segment. - kMemOpEs = 0x2000u, //!< Implicit memory operand's ES segment. - - kMemOpMib = 0x4000u, //!< Operand must be MIB (base+index) pointer. - kMemOpTMem = 0x8000u //!< Operand is a sib_mem (ADX memory operand). +//! Operand signature flags used by \ref OpSignature. +enum class OpFlags : uint64_t { + //! No operand flags. + kNone = 0u, + + kRegGpbLo = 0x0000000000000001u, //!< Operand can be low 8-bit GPB register. + kRegGpbHi = 0x0000000000000002u, //!< Operand can be high 8-bit GPB register. + kRegGpw = 0x0000000000000004u, //!< Operand can be 16-bit GPW register. + kRegGpd = 0x0000000000000008u, //!< Operand can be 32-bit GPD register. + kRegGpq = 0x0000000000000010u, //!< Operand can be 64-bit GPQ register. + kRegXmm = 0x0000000000000020u, //!< Operand can be 128-bit XMM register. + kRegYmm = 0x0000000000000040u, //!< Operand can be 256-bit YMM register. + kRegZmm = 0x0000000000000080u, //!< Operand can be 512-bit ZMM register. + kRegMm = 0x0000000000000100u, //!< Operand can be 64-bit MM register. + kRegKReg = 0x0000000000000200u, //!< Operand can be 64-bit K register. + kRegSReg = 0x0000000000000400u, //!< Operand can be SReg (segment register). + kRegCReg = 0x0000000000000800u, //!< Operand can be CReg (control register). + kRegDReg = 0x0000000000001000u, //!< Operand can be DReg (debug register). + kRegSt = 0x0000000000002000u, //!< Operand can be 80-bit ST register (X87). + kRegBnd = 0x0000000000004000u, //!< Operand can be 128-bit BND register. + kRegTmm = 0x0000000000008000u, //!< Operand can be 0..8192-bit TMM register. + kRegMask = 0x000000000000FFFFu, //!< Mask of all possible register types. + + kMemUnspecified = 0x0000000000040000u, //!< Operand can be a scalar memory pointer without size. + kMem8 = 0x0000000000080000u, //!< Operand can be an 8-bit memory pointer. + kMem16 = 0x0000000000100000u, //!< Operand can be a 16-bit memory pointer. + kMem32 = 0x0000000000200000u, //!< Operand can be a 32-bit memory pointer. + kMem48 = 0x0000000000400000u, //!< Operand can be a 48-bit memory pointer (FAR pointers only). + kMem64 = 0x0000000000800000u, //!< Operand can be a 64-bit memory pointer. + kMem80 = 0x0000000001000000u, //!< Operand can be an 80-bit memory pointer. + kMem128 = 0x0000000002000000u, //!< Operand can be a 128-bit memory pointer. + kMem256 = 0x0000000004000000u, //!< Operand can be a 256-bit memory pointer. + kMem512 = 0x0000000008000000u, //!< Operand can be a 512-bit memory pointer. + kMem1024 = 0x0000000010000000u, //!< Operand can be a 1024-bit memory pointer. + kMemMask = 0x000000001FFC0000u, //!< Mask of all possible scalar memory types. + + kVm32x = 0x0000000040000000u, //!< Operand can be a vm32x (vector) pointer. + kVm32y = 0x0000000080000000u, //!< Operand can be a vm32y (vector) pointer. + kVm32z = 0x0000000100000000u, //!< Operand can be a vm32z (vector) pointer. + kVm64x = 0x0000000200000000u, //!< Operand can be a vm64x (vector) pointer. + kVm64y = 0x0000000400000000u, //!< Operand can be a vm64y (vector) pointer. + kVm64z = 0x0000000800000000u, //!< Operand can be a vm64z (vector) pointer. + kVmMask = 0x0000000FC0000000u, //!< Mask of all possible vector memory types. + + kImmI4 = 0x0000001000000000u, //!< Operand can be signed 4-bit immediate. + kImmU4 = 0x0000002000000000u, //!< Operand can be unsigned 4-bit immediate. + kImmI8 = 0x0000004000000000u, //!< Operand can be signed 8-bit immediate. + kImmU8 = 0x0000008000000000u, //!< Operand can be unsigned 8-bit immediate. + kImmI16 = 0x0000010000000000u, //!< Operand can be signed 16-bit immediate. + kImmU16 = 0x0000020000000000u, //!< Operand can be unsigned 16-bit immediate. + kImmI32 = 0x0000040000000000u, //!< Operand can be signed 32-bit immediate. + kImmU32 = 0x0000080000000000u, //!< Operand can be unsigned 32-bit immediate. + kImmI64 = 0x0000100000000000u, //!< Operand can be signed 64-bit immediate. + kImmU64 = 0x0000200000000000u, //!< Operand can be unsigned 64-bit immediate. + kImmMask = 0x00003FF000000000u, //!< Mask of all immediate types. + + kRel8 = 0x0000400000000000u, //!< Operand can be relative 8-bit displacement. + kRel32 = 0x0000800000000000u, //!< Operand can be relative 32-bit displacement. + kRelMask = 0x0000C00000000000u, //!< Mask of all relative displacement types. + + kFlagMemBase = 0x0001000000000000u, //!< Flag: Only memory base is allowed (no index, no offset). + kFlagMemDs = 0x0002000000000000u, //!< Flag: Implicit memory operand's DS segment. + kFlagMemEs = 0x0004000000000000u, //!< Flag: Implicit memory operand's ES segment. + + kFlagMib = 0x0008000000000000u, //!< Flag: Operand is MIB (base+index) pointer. + kFlagTMem = 0x0010000000000000u, //!< Flag: Operand is TMEM (sib_mem), AMX memory pointer. + + kFlagImplicit = 0x0080000000000000u, //!< Flag: Operand is implicit. + kFlagMask = 0x009F000000000000u, //!< Mask of all flags. + + //! Contains mask of all registers, memory operands, immediate operands, and displacement operands. + kOpMask = kRegMask | kMemMask | kVmMask | kImmMask | kRelMask }; +ASMJIT_DEFINE_ENUM_FLAGS(OpFlags) -// ============================================================================ -// [asmjit::x86::InstDB::Flags] -// ============================================================================ - -//! Instruction flags (X86). +//! Operand signature. //! -//! Details about instruction encoding, operation, features, and some limitations. -enum Flags : uint32_t { - kFlagNone = 0x00000000u, //!< No flags. - - // Instruction Family - // ------------------ - // - // Instruction family information. +//! Contains all possible operand combinations, memory size information, and a fixed register id (or `BaseReg::kIdBad` +//! if fixed id isn't required). +struct OpSignature { + //! \name Members + //! \{ - kFlagFpu = 0x00000100u, //!< Instruction that accesses FPU registers. - kFlagMmx = 0x00000200u, //!< Instruction that accesses MMX registers (including 3DNOW and GEODE) and EMMS. - kFlagVec = 0x00000400u, //!< Instruction that accesses XMM registers (SSE, AVX, AVX512). + uint64_t _flags : 56; + uint64_t _regMask : 8; - // FPU Flags - // --------- - // - // Used to tell the encoder which memory operand sizes are encodable. + //! \} - kFlagFpuM16 = 0x00000800u, //!< FPU instruction can address `word_ptr` (shared with M80). - kFlagFpuM32 = 0x00001000u, //!< FPU instruction can address `dword_ptr`. - kFlagFpuM64 = 0x00002000u, //!< FPU instruction can address `qword_ptr`. - kFlagFpuM80 = 0x00000800u, //!< FPU instruction can address `tword_ptr` (shared with M16). + //! \name Accessors + //! \{ - // Prefixes and Encoding Flags - // --------------------------- - // - // These describe optional X86 prefixes that can be used to change the instruction's operation. + //! Returns operand signature flags. + inline OpFlags flags() const noexcept { return (OpFlags)_flags; } - kFlagTsib = 0x00004000u, //!< Instruction uses TSIB (or SIB_MEM) encoding (MODRM followed by SIB). - kFlagRep = 0x00008000u, //!< Instruction can be prefixed with using the REP(REPE) or REPNE prefix. - kFlagRepIgnored = 0x00010000u, //!< Instruction ignores REP|REPNE prefixes, but they are accepted. - kFlagLock = 0x00020000u, //!< Instruction can be prefixed with using the LOCK prefix. - kFlagXAcquire = 0x00040000u, //!< Instruction can be prefixed with using the XACQUIRE prefix. - kFlagXRelease = 0x00080000u, //!< Instruction can be prefixed with using the XRELEASE prefix. - kFlagMib = 0x00100000u, //!< Instruction uses MIB (BNDLDX|BNDSTX) to encode two registers. - kFlagVsib = 0x00200000u, //!< Instruction uses VSIB instead of legacy SIB. - - // If both `kFlagPrefixVex` and `kFlagPrefixEvex` flags are specified it - // means that the instructions can be encoded by either VEX or EVEX prefix. - // In that case AsmJit checks global options and also instruction options - // to decide whether to emit VEX or EVEX prefix. - - kFlagVex = 0x00400000u, //!< Instruction can be encoded by VEX|XOP (AVX|AVX2|BMI|XOP|...). - kFlagEvex = 0x00800000u, //!< Instruction can be encoded by EVEX (AVX512). - kFlagPreferEvex = 0x01000000u, //!< EVEX encoding is preferred over VEX encoding (AVX515_VNNI vs AVX_VNNI). - kFlagEvexCompat = 0x02000000u, //!< EVEX and VEX signatures are compatible. - kFlagEvexKReg = 0x04000000u, //!< EVEX instruction requires K register in the first operand (compare instructions). - kFlagEvexTwoOp = 0x08000000u, //!< EVEX instruction requires two operands and K register as a selector (gather instructions). - kFlagEvexTransformable = 0x10000000u //!< VEX instruction that can be transformed to a compatible EVEX instruction. -}; + //! Tests whether the given `flag` is set. + inline bool hasFlag(OpFlags flag) const noexcept { return (_flags & uint64_t(flag)) != 0; } -// ============================================================================ -// [asmjit::x86::InstDB::Avx512Flags] -// ============================================================================ - -//! AVX512 flags. -enum Avx512Flags : uint32_t { - kAvx512Flag_ = 0x00000000u, //!< Internally used in tables, has no meaning. - kAvx512FlagK = 0x00000001u, //!< Supports masking {k1..k7}. - kAvx512FlagZ = 0x00000002u, //!< Supports zeroing {z}, must be used together with `kAvx512k`. - kAvx512FlagER = 0x00000004u, //!< Supports 'embedded-rounding' {er} with implicit {sae}, - kAvx512FlagSAE = 0x00000008u, //!< Supports 'suppress-all-exceptions' {sae}. - kAvx512FlagB32 = 0x00000010u, //!< Supports 32-bit broadcast 'b32'. - kAvx512FlagB64 = 0x00000020u, //!< Supports 64-bit broadcast 'b64'. - kAvx512FlagT4X = 0x00000080u //!< Operates on a vector of consecutive registers (AVX512_4FMAPS and AVX512_4VNNIW). -}; + //! Tests whether this signature contains at least one register operand of any type. + inline bool hasReg() const noexcept { return hasFlag(OpFlags::kRegMask); } + //! Tests whether this signature contains at least one scalar memory operand of any type. + inline bool hasMem() const noexcept { return hasFlag(OpFlags::kMemMask); } + //! Tests whether this signature contains at least one vector memory operand of any type. + inline bool hasVm() const noexcept { return hasFlag(OpFlags::kVmMask); } + //! Tests whether this signature contains at least one immediate operand of any type. + inline bool hasImm() const noexcept { return hasFlag(OpFlags::kImmMask); } + //! Tests whether this signature contains at least one relative displacement operand of any type. + inline bool hasRel() const noexcept { return hasFlag(OpFlags::kRelMask); } -// ============================================================================ -// [asmjit::x86::InstDB::SingleRegCase] -// ============================================================================ - -enum SingleRegCase : uint32_t { - //! No special handling. - kSingleRegNone = 0, - //! Operands become read-only - `REG & REG` and similar. - kSingleRegRO = 1, - //! Operands become write-only - `REG ^ REG` and similar. - kSingleRegWO = 2 -}; + //! Tests whether the operand is implicit. + inline bool isImplicit() const noexcept { return hasFlag(OpFlags::kFlagImplicit); } -// ============================================================================ -// [asmjit::x86::InstDB::InstSignature / OpSignature] -// ============================================================================ + //! Returns a physical register mask. + inline RegMask regMask() const noexcept { return _regMask; } -//! Operand signature (X86). -//! -//! Contains all possible operand combinations, memory size information, and -//! a fixed register id (or `BaseReg::kIdBad` if fixed id isn't required). -struct OpSignature { - //! Operand flags. - uint32_t opFlags; - //! Memory flags. - uint16_t memFlags; - //! Extra flags. - uint8_t extFlags; - //! Mask of possible register IDs. - uint8_t regMask; + //! \} }; ASMJIT_VARAPI const OpSignature _opSignatureTable[]; -//! Instruction signature (X86). +//! Instruction signature. //! -//! Contains a sequence of operands' combinations and other metadata that defines -//! a single instruction. This data is used by instruction validator. +//! Contains a sequence of operands' combinations and other metadata that defines a single instruction. This data is +//! used by instruction validator. struct InstSignature { + //! \name Members + //! \{ + //! Count of operands in `opIndex` (0..6). - uint8_t opCount : 3; + uint8_t _opCount : 3; //! Architecture modes supported (X86 / X64). - uint8_t modes : 2; + uint8_t _mode : 2; //! Number of implicit operands. - uint8_t implicit : 3; + uint8_t _implicitOpCount : 3; //! Reserved for future use. - uint8_t reserved; + uint8_t _reserved; //! Indexes to `OpSignature` table. - uint8_t operands[Globals::kMaxOpCount]; + uint8_t _opSignatureIndexes[Globals::kMaxOpCount]; + + //! \} + + //! \name Accessors + //! \{ + + //! Returns instruction operation mode. + inline Mode mode() const noexcept { return (Mode)_mode; } + //! Tests whether the instruction supports the given operating mode. + inline bool supportsMode(Mode mode) const noexcept { return (uint8_t(_mode) & uint8_t(mode)) != 0; } + + //! Returns the number of operands of this signature. + inline uint32_t opCount() const noexcept { return _opCount; } + //! Returns the number of implicit operands this signature has. + inline uint32_t implicitOpCount() const noexcept { return _implicitOpCount; } + //! Tests whether this instruction signature has at least one implicit operand. + inline bool hasImplicitOperands() const noexcept { return _implicitOpCount != 0; } + + //! Returns indexes to \ref _opSignatureTable for each operand of the instruction. + //! + //! \note The returned array always provides indexes for all operands (see \ref Globals::kMaxOpCount) even if the + //! instruction provides less operands. Undefined operands have always index of zero. + inline const uint8_t* opSignatureIndexes() const noexcept { return _opSignatureIndexes; } + + //! Returns index to \ref _opSignatureTable, corresponding to the requested operand `index` of the instruction. + inline uint8_t opSignatureIndex(size_t index) const noexcept { + ASMJIT_ASSERT(index < Globals::kMaxOpCount); + return _opSignatureIndexes[index]; + } + + //! Returns \ref OpSignature corresponding to the requested operand `index` of the instruction. + inline const OpSignature& opSignature(size_t index) const noexcept { + ASMJIT_ASSERT(index < Globals::kMaxOpCount); + return _opSignatureTable[_opSignatureIndexes[index]]; + } + + //! \} }; ASMJIT_VARAPI const InstSignature _instSignatureTable[]; -// ============================================================================ -// [asmjit::x86::InstDB::CommonInfo] -// ============================================================================ +//! Instruction flags. +//! +//! Details about instruction encoding, operation, features, and some limitations. +enum class InstFlags : uint32_t { + //! No flags. + kNone = 0x00000000u, + + // Instruction Family + // ------------------ + // + // Instruction family information. -//! Instruction common information (X86) + //! Instruction that accesses FPU registers. + kFpu = 0x00000100u, + //! Instruction that accesses MMX registers (including 3DNOW and GEODE) and EMMS. + kMmx = 0x00000200u, + //! Instruction that accesses XMM registers (SSE, AVX, AVX512). + kVec = 0x00000400u, + + // FPU Flags + // --------- + // + // Used to tell the encoder which memory operand sizes are encodable. + + //! FPU instruction can address `word_ptr` (shared with M80). + kFpuM16 = 0x00000800u, + //! FPU instruction can address `dword_ptr`. + kFpuM32 = 0x00001000u, + //! FPU instruction can address `qword_ptr`. + kFpuM64 = 0x00002000u, + //! FPU instruction can address `tword_ptr` (shared with M16). + kFpuM80 = 0x00000800u, + + // Prefixes and Encoding Flags + // --------------------------- + // + // These describe optional X86 prefixes that can be used to change the instruction's operation. + + //! Instruction can be prefixed with using the REP(REPE) or REPNE prefix. + kRep = 0x00004000u, + //! Rep prefix is accepted, but it has no effect other than being emitted with the instruction (as an extra byte). + kRepIgnored = 0x00008000u, + //! Instruction can be prefixed with using the LOCK prefix. + kLock = 0x00010000u, + //! Instruction can be prefixed with using the XACQUIRE prefix. + kXAcquire = 0x00020000u, + //! Instruction can be prefixed with using the XRELEASE prefix. + kXRelease = 0x00040000u, + //! Instruction uses MIB (BNDLDX|BNDSTX) to encode two registers. + kMib = 0x00080000u, + //! Instruction uses VSIB instead of legacy SIB. + kVsib = 0x00100000u, + //! Instruction uses TSIB (or SIB_MEM) encoding (MODRM followed by SIB). + kTsib = 0x00200000u, + + // If both `kPrefixVex` and `kPrefixEvex` flags are specified it means that the instructions can be encoded + // by either VEX or EVEX prefix. In that case AsmJit checks global options and also instruction options to decide + // whether to emit VEX or EVEX prefix. + + //! Instruction can be encoded by VEX|XOP (AVX|AVX2|BMI|XOP|...). + kVex = 0x00400000u, + //! Instruction can be encoded by EVEX (AVX512). + kEvex = 0x00800000u, + //! EVEX encoding is preferred over VEX encoding (AVX515_VNNI vs AVX_VNNI). + kPreferEvex = 0x01000000u, + //! EVEX and VEX signatures are compatible. + kEvexCompat = 0x02000000u, + //! EVEX instruction requires K register in the first operand (compare instructions). + kEvexKReg = 0x04000000u, + //! EVEX instruction requires two operands and K register as a selector (gather instructions). + kEvexTwoOp = 0x08000000u, + //! VEX instruction that can be transformed to a compatible EVEX instruction. + kEvexTransformable = 0x10000000u, + + // Other Flags + // ----------- + + //! Instruction uses consecutive registers. + //! + //! Used by V4FMADDPS, V4FMADDSS, V4FNMADDPS, V4FNMADDSS, VP4DPWSSD, VP4DPWSSDS, VP2INTERSECTD, and VP2INTERSECTQ + //! instructions + kConsecutiveRegs = 0x20000000u +}; +ASMJIT_DEFINE_ENUM_FLAGS(InstFlags) + +//! AVX-512 flags. +enum class Avx512Flags : uint32_t { + //! No AVX-512 flags. + kNone = 0, + + //! Internally used in tables, has no meaning. + k_ = 0x00000000u, + //! Supports masking {k1..k7}. + kK = 0x00000001u, + //! Supports zeroing {z}, must be used together with `kAvx512k`. + kZ = 0x00000002u, + //! Supports 'embedded-rounding' {er} with implicit {sae}, + kER = 0x00000004u, + //! Supports 'suppress-all-exceptions' {sae}. + kSAE = 0x00000008u, + //! Supports 16-bit broadcast 'b16'. + kB16 = 0x00000010u, + //! Supports 32-bit broadcast 'b32'. + kB32 = 0x00000020u, + //! Supports 64-bit broadcast 'b64'. + kB64 = 0x00000040u, + //! Operates on a vector of consecutive registers (AVX512_4FMAPS and AVX512_4VNNIW). + kT4X = 0x00000080u, + + //! Implicit zeroing if {k} masking is used. Using {z} is not valid in this case as it's implicit. + kImplicitZ = 0x00000100, +}; +ASMJIT_DEFINE_ENUM_FLAGS(Avx512Flags) + +//! Instruction common information. //! //! Aggregated information shared across one or more instruction. struct CommonInfo { @@ -280,82 +339,89 @@ struct CommonInfo { uint32_t _iSignatureIndex : 11; //! Number of relevant `ISignature` entries. uint32_t _iSignatureCount : 5; - //! Control type, see `ControlType`. - uint32_t _controlType : 3; + //! Instruction control flow category, see \ref InstControlFlow. + uint32_t _controlFlow : 3; //! Specifies what happens if all source operands share the same register. - uint32_t _singleRegCase : 2; + uint32_t _sameRegHint : 2; - // -------------------------------------------------------------------------- - // [Accessors] - // -------------------------------------------------------------------------- + //! \name Accessors + //! \{ - //! Returns instruction flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } - //! Tests whether the instruction has a `flag`, see \ref Flags. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } + //! Returns instruction flags. + inline InstFlags flags() const noexcept { return (InstFlags)_flags; } + //! Tests whether the instruction has a `flag`. + inline bool hasFlag(InstFlags flag) const noexcept { return Support::test(_flags, flag); } - //! Returns instruction AVX-512 flags, see \ref Avx512Flags. - inline uint32_t avx512Flags() const noexcept { return _avx512Flags; } - //! Tests whether the instruction has an AVX-512 `flag`, see \ref Avx512Flags. - inline bool hasAvx512Flag(uint32_t flag) const noexcept { return (_avx512Flags & flag) != 0; } + //! Returns instruction AVX-512 flags. + inline Avx512Flags avx512Flags() const noexcept { return (Avx512Flags)_avx512Flags; } + //! Tests whether the instruction has an AVX-512 `flag`. + inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return Support::test(_avx512Flags, flag); } //! Tests whether the instruction is FPU instruction. - inline bool isFpu() const noexcept { return hasFlag(kFlagFpu); } + inline bool isFpu() const noexcept { return hasFlag(InstFlags::kFpu); } //! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS). - inline bool isMmx() const noexcept { return hasFlag(kFlagMmx); } + inline bool isMmx() const noexcept { return hasFlag(InstFlags::kMmx); } //! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers. - inline bool isVec() const noexcept { return hasFlag(kFlagVec); } + inline bool isVec() const noexcept { return hasFlag(InstFlags::kVec); } //! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers. - inline bool isSse() const noexcept { return (flags() & (kFlagVec | kFlagVex | kFlagEvex)) == kFlagVec; } + inline bool isSse() const noexcept { return (flags() & (InstFlags::kVec | InstFlags::kVex | InstFlags::kEvex)) == InstFlags::kVec; } //! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers. inline bool isAvx() const noexcept { return isVec() && isVexOrEvex(); } //! Tests whether the instruction can be prefixed with LOCK prefix. - inline bool hasLockPrefix() const noexcept { return hasFlag(kFlagLock); } + inline bool hasLockPrefix() const noexcept { return hasFlag(InstFlags::kLock); } //! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix. - inline bool hasRepPrefix() const noexcept { return hasFlag(kFlagRep); } + inline bool hasRepPrefix() const noexcept { return hasFlag(InstFlags::kRep); } //! Tests whether the instruction can be prefixed with XACQUIRE prefix. - inline bool hasXAcquirePrefix() const noexcept { return hasFlag(kFlagXAcquire); } + inline bool hasXAcquirePrefix() const noexcept { return hasFlag(InstFlags::kXAcquire); } //! Tests whether the instruction can be prefixed with XRELEASE prefix. - inline bool hasXReleasePrefix() const noexcept { return hasFlag(kFlagXRelease); } + inline bool hasXReleasePrefix() const noexcept { return hasFlag(InstFlags::kXRelease); } //! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect). - inline bool isRepIgnored() const noexcept { return hasFlag(kFlagRepIgnored); } + inline bool isRepIgnored() const noexcept { return hasFlag(InstFlags::kRepIgnored); } //! Tests whether the instruction uses MIB. - inline bool isMibOp() const noexcept { return hasFlag(kFlagMib); } + inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); } //! Tests whether the instruction uses VSIB. - inline bool isVsibOp() const noexcept { return hasFlag(kFlagVsib); } + inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); } //! Tests whether the instruction uses TSIB (AMX, instruction requires MOD+SIB). - inline bool isTsibOp() const noexcept { return hasFlag(kFlagTsib); } + inline bool isTsibOp() const noexcept { return hasFlag(InstFlags::kTsib); } //! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable). - inline bool isVex() const noexcept { return hasFlag(kFlagVex); } + inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isEvex() const noexcept { return hasFlag(kFlagEvex); } + inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isVexOrEvex() const noexcept { return hasFlag(kFlagVex | kFlagEvex); } + inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); } //! Tests whether the instruction should prefer EVEX prefix instead of VEX prefix. - inline bool preferEvex() const noexcept { return hasFlag(kFlagPreferEvex); } + inline bool preferEvex() const noexcept { return hasFlag(InstFlags::kPreferEvex); } - inline bool isEvexCompatible() const noexcept { return hasFlag(kFlagEvexCompat); } - inline bool isEvexKRegOnly() const noexcept { return hasFlag(kFlagEvexKReg); } - inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(kFlagEvexTwoOp); } - inline bool isEvexTransformable() const noexcept { return hasFlag(kFlagEvexTransformable); } + inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); } + inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); } + inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); } + inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); } //! Tests whether the instruction supports AVX512 masking {k}. - inline bool hasAvx512K() const noexcept { return hasAvx512Flag(kAvx512FlagK); } + inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); } //! Tests whether the instruction supports AVX512 zeroing {k}{z}. - inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(kAvx512FlagZ); } + inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); } //! Tests whether the instruction supports AVX512 embedded-rounding {er}. - inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(kAvx512FlagER); } + inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); } //! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}. - inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(kAvx512FlagSAE); } + inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); } //! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit). - inline bool hasAvx512B() const noexcept { return hasAvx512Flag(kAvx512FlagB32 | kAvx512FlagB64); } + inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); } + //! Tests whether the instruction supports AVX512 broadcast (16-bit). + inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); } //! Tests whether the instruction supports AVX512 broadcast (32-bit). - inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(kAvx512FlagB32); } + inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); } //! Tests whether the instruction supports AVX512 broadcast (64-bit). - inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(kAvx512FlagB64); } + inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); } + + // Returns the size of the broadcast - either 2, 4, or 8, or 0 if broadcast is not supported. + inline uint32_t broadcastSize() const noexcept { + constexpr uint32_t kShift = Support::ConstCTZ<uint32_t(Avx512Flags::kB16)>::value; + return (uint32_t(_avx512Flags) & uint32_t(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64)) >> (kShift - 1); + } inline uint32_t signatureIndex() const noexcept { return _iSignatureIndex; } inline uint32_t signatureCount() const noexcept { return _iSignatureCount; } @@ -363,53 +429,50 @@ struct CommonInfo { inline const InstSignature* signatureData() const noexcept { return _instSignatureTable + _iSignatureIndex; } inline const InstSignature* signatureEnd() const noexcept { return _instSignatureTable + _iSignatureIndex + _iSignatureCount; } - //! Returns the control-flow type of the instruction. - inline uint32_t controlType() const noexcept { return _controlType; } + //! Returns a control flow category of the instruction. + inline InstControlFlow controlFlow() const noexcept { return (InstControlFlow)_controlFlow; } + + //! Returns a hint that can be used when both inputs are the same register. + inline InstSameRegHint sameRegHint() const noexcept { return (InstSameRegHint)_sameRegHint; } - inline uint32_t singleRegCase() const noexcept { return _singleRegCase; } + //! \} }; ASMJIT_VARAPI const CommonInfo _commonInfoTable[]; -// ============================================================================ -// [asmjit::x86::InstDB::InstInfo] -// ============================================================================ - -//! Instruction information (X86). +//! Instruction information. struct InstInfo { //! Index to \ref _nameData. uint32_t _nameDataIndex : 14; //! Index to \ref _commonInfoTable. uint32_t _commonInfoIndex : 10; - //! Index to \ref _commonInfoTableB. - uint32_t _commonInfoIndexB : 8; + //! Index to \ref _additionalInfoTable. + uint32_t _additionalInfoIndex : 8; //! Instruction encoding (internal encoding identifier used by \ref Assembler). uint8_t _encoding; //! Main opcode value (0..255). uint8_t _mainOpcodeValue; - //! Index to \ref _mainOpcodeTable` that is combined with \ref _mainOpcodeValue - //! to form the final opcode. + //! Index to \ref _mainOpcodeTable` that is combined with \ref _mainOpcodeValue to form the final opcode. uint8_t _mainOpcodeIndex; //! Index to \ref _altOpcodeTable that contains a full alternative opcode. uint8_t _altOpcodeIndex; - // -------------------------------------------------------------------------- - // [Accessors] - // -------------------------------------------------------------------------- + //! \name Accessors + //! \{ //! Returns common information, see `CommonInfo`. inline const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; } //! Returns instruction flags, see \ref Flags. - inline uint32_t flags() const noexcept { return commonInfo().flags(); } + inline InstFlags flags() const noexcept { return commonInfo().flags(); } //! Tests whether the instruction has flag `flag`, see \ref Flags. - inline bool hasFlag(uint32_t flag) const noexcept { return commonInfo().hasFlag(flag); } + inline bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); } //! Returns instruction AVX-512 flags, see \ref Avx512Flags. - inline uint32_t avx512Flags() const noexcept { return commonInfo().avx512Flags(); } + inline Avx512Flags avx512Flags() const noexcept { return commonInfo().avx512Flags(); } //! Tests whether the instruction has an AVX-512 `flag`, see \ref Avx512Flags. - inline bool hasAvx512Flag(uint32_t flag) const noexcept { return commonInfo().hasAvx512Flag(flag); } + inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return commonInfo().hasAvx512Flag(flag); } //! Tests whether the instruction is FPU instruction. inline bool isFpu() const noexcept { return commonInfo().isFpu(); } @@ -434,54 +497,63 @@ struct InstInfo { //! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect). inline bool isRepIgnored() const noexcept { return commonInfo().isRepIgnored(); } //! Tests whether the instruction uses MIB. - inline bool isMibOp() const noexcept { return hasFlag(kFlagMib); } + inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); } //! Tests whether the instruction uses VSIB. - inline bool isVsibOp() const noexcept { return hasFlag(kFlagVsib); } + inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); } //! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable). - inline bool isVex() const noexcept { return hasFlag(kFlagVex); } + inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isEvex() const noexcept { return hasFlag(kFlagEvex); } + inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); } //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable). - inline bool isVexOrEvex() const noexcept { return hasFlag(kFlagVex | kFlagEvex); } + inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); } - inline bool isEvexCompatible() const noexcept { return hasFlag(kFlagEvexCompat); } - inline bool isEvexKRegOnly() const noexcept { return hasFlag(kFlagEvexKReg); } - inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(kFlagEvexTwoOp); } - inline bool isEvexTransformable() const noexcept { return hasFlag(kFlagEvexTransformable); } + inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); } + inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); } + inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); } + inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); } //! Tests whether the instruction supports AVX512 masking {k}. - inline bool hasAvx512K() const noexcept { return hasAvx512Flag(kAvx512FlagK); } + inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); } //! Tests whether the instruction supports AVX512 zeroing {k}{z}. - inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(kAvx512FlagZ); } + inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); } //! Tests whether the instruction supports AVX512 embedded-rounding {er}. - inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(kAvx512FlagER); } + inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); } //! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}. - inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(kAvx512FlagSAE); } + inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); } //! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit). - inline bool hasAvx512B() const noexcept { return hasAvx512Flag(kAvx512FlagB32 | kAvx512FlagB64); } + inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); } + //! Tests whether the instruction supports AVX512 broadcast (16-bit). + inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); } //! Tests whether the instruction supports AVX512 broadcast (32-bit). - inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(kAvx512FlagB32); } + inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); } //! Tests whether the instruction supports AVX512 broadcast (64-bit). - inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(kAvx512FlagB64); } + inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); } - //! Gets the control-flow type of the instruction. - inline uint32_t controlType() const noexcept { return commonInfo().controlType(); } - inline uint32_t singleRegCase() const noexcept { return commonInfo().singleRegCase(); } + //! Returns a control flow category of the instruction. + inline InstControlFlow controlFlow() const noexcept { return commonInfo().controlFlow(); } + //! Returns a hint that can be used when both inputs are the same register. + inline InstSameRegHint sameRegHint() const noexcept { return commonInfo().sameRegHint(); } inline uint32_t signatureIndex() const noexcept { return commonInfo().signatureIndex(); } inline uint32_t signatureCount() const noexcept { return commonInfo().signatureCount(); } inline const InstSignature* signatureData() const noexcept { return commonInfo().signatureData(); } inline const InstSignature* signatureEnd() const noexcept { return commonInfo().signatureEnd(); } + + //! \} }; ASMJIT_VARAPI const InstInfo _instInfoTable[]; -static inline const InstInfo& infoById(uint32_t instId) noexcept { +static inline const InstInfo& infoById(InstId instId) noexcept { ASMJIT_ASSERT(Inst::isDefinedId(instId)); return _instInfoTable[instId]; } +//! \cond INTERNAL +static_assert(sizeof(OpSignature) == 8, "InstDB::OpSignature must be 8 bytes long"); +//! \endcond + } // {InstDB} //! \} diff --git a/src/asmjit/x86/x86instdb_p.h b/src/asmjit/x86/x86instdb_p.h index 4573794..9a6f780 100644 --- a/src/asmjit/x86/x86instdb_p.h +++ b/src/asmjit/x86/x86instdb_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86INSTDB_P_H_INCLUDED #define ASMJIT_X86_X86INSTDB_P_H_INCLUDED @@ -34,17 +16,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace InstDB { -// ============================================================================ -// [asmjit::x86::InstDB::Encoding] -// ============================================================================ - //! Instruction encoding (X86). //! -//! This is a specific identifier that is used by AsmJit to describe the way -//! each instruction is encoded. Some encodings are special only for a single -//! instruction as X86 instruction set contains a lot of legacy encodings, and -//! some encodings describe a group of instructions that share some commons, -//! like MMX, SSE, AVX, AVX512 instructions, etc... +//! This is a specific identifier that is used by AsmJit to describe the way each instruction is encoded. Some +//! encodings are special only for a single instruction as X86 instruction set contains a lot of legacy encodings, +//! and some encodings describe a group of instructions that share some commons, like MMX, SSE, AVX, AVX512 +//! instructions, etc... enum EncodingId : uint32_t { kEncodingNone = 0, //!< Never used. kEncodingX86Op, //!< X86 [OP]. @@ -210,12 +187,8 @@ enum EncodingId : uint32_t { kEncodingCount //!< Count of instruction encodings. }; -// ============================================================================ -// [asmjit::x86::InstDB - CommonInfoTableB] -// ============================================================================ - -//! CPU extensions required to execute instruction. -struct CommonInfoTableB { +//! Additional information table, provides CPU extensions required to execute an instruction and RW flags. +struct AdditionalInfo { //! Features vector. uint8_t _features[6]; //! Index to `_rwFlagsTable`. @@ -227,10 +200,6 @@ struct CommonInfoTableB { inline const uint8_t* featuresEnd() const noexcept { return _features + ASMJIT_ARRAY_SIZE(_features); } }; -// ============================================================================ -// [asmjit::x86::InstDB - InstNameIndex] -// ============================================================================ - // ${NameLimits:Begin} // ------------------- Automatically generated, do not edit ------------------- enum : uint32_t { kMaxNameSize = 17 }; @@ -242,10 +211,6 @@ struct InstNameIndex { uint16_t end; }; -// ============================================================================ -// [asmjit::x86::InstDB - RWInfo] -// ============================================================================ - struct RWInfo { enum Category : uint8_t { kCategoryGeneric, @@ -275,8 +240,9 @@ struct RWInfoOp { uint64_t rByteMask; uint64_t wByteMask; uint8_t physId; - uint8_t reserved[3]; - uint32_t flags; + uint8_t consecutiveLeadCount; + uint8_t reserved[2]; + OpRWFlags flags; }; //! R/M information. @@ -318,10 +284,6 @@ extern const RWInfoOp rwInfoOp[]; extern const RWInfoRm rwInfoRm[]; extern const RWFlagsInfoTable _rwFlagsInfoTable[]; -// ============================================================================ -// [asmjit::x86::InstDB::Tables] -// ============================================================================ - extern const uint32_t _mainOpcodeTable[]; extern const uint32_t _altOpcodeTable[]; @@ -330,7 +292,7 @@ extern const char _nameData[]; extern const InstNameIndex instNameIndex[26]; #endif // !ASMJIT_NO_TEXT -extern const CommonInfoTableB _commonInfoTableB[]; +extern const AdditionalInfo _additionalInfoTable[]; } // {InstDB} diff --git a/src/asmjit/x86/x86opcode_p.h b/src/asmjit/x86/x86opcode_p.h index 80c38fb..94a76f0 100644 --- a/src/asmjit/x86/x86opcode_p.h +++ b/src/asmjit/x86/x86opcode_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86OPCODE_P_H_INCLUDED #define ASMJIT_X86_X86OPCODE_P_H_INCLUDED @@ -32,85 +14,66 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::x86::Opcode] -// ============================================================================ - //! Helper class to store and manipulate X86 opcodes. //! -//! The first 8 least significant bits describe the opcode byte as defined in -//! ISA manuals, all other bits describe other properties like prefixes, see -//! `Opcode::Bits` for more information. +//! The first 8 least significant bits describe the opcode byte as defined in ISA manuals, all other bits +//! describe other properties like prefixes, see `Opcode::Bits` for more information. struct Opcode { uint32_t v; //! Describes a meaning of all bits of AsmJit's 32-bit opcode value. //! - //! This schema is AsmJit specific and has been designed to allow encoding of - //! all X86 instructions available. X86, MMX, and SSE+ instructions always use - //! `MM` and `PP` fields, which are encoded to corresponding prefixes needed - //! by X86 or SIMD instructions. AVX+ instructions embed `MMMMM` and `PP` fields - //! in a VEX prefix, and AVX-512 instructions embed `MM` and `PP` in EVEX prefix. + //! This schema is AsmJit specific and has been designed to allow encoding of all X86 instructions available. X86, + //! MMX, and SSE+ instructions always use `MM` and `PP` fields, which are encoded to corresponding prefixes needed + //! by X86 or SIMD instructions. AVX+ instructions embed `MMMMM` and `PP` fields in a VEX prefix, and AVX-512 + //! instructions embed `MM` and `PP` in EVEX prefix. //! - //! The instruction opcode definition uses 1 or 2 bytes as an opcode value. 1 - //! byte is needed by most of the instructions, 2 bytes are only used by legacy - //! X87-FPU instructions. This means that a second byte is free to by used by - //! instructions encoded by using VEX and/or EVEX prefix. + //! The instruction opcode definition uses 1 or 2 bytes as an opcode value. 1 byte is needed by most of the + //! instructions, 2 bytes are only used by legacy X87-FPU instructions. This means that a second byte is free to + //! by used by instructions encoded by using VEX and/or EVEX prefix. //! //! The fields description: //! - //! - `MM` field is used to encode prefixes needed by the instruction or as - //! a part of VEX/EVEX prefix. Described as `mm` and `mmmmm` in instruction - //! manuals. + //! - `MM` field is used to encode prefixes needed by the instruction or as a part of VEX/EVEX prefix. Described as + //! `mm` and `mmmmm` in instruction manuals. //! - //! NOTE: Since `MM` field is defined as `mmmmm` (5 bits), but only 2 least - //! significant bits are used by VEX and EVEX prefixes, and additional 4th - //! bit is used by XOP prefix, AsmJit uses the 3rd and 5th bit for it's own - //! purposes. These bits will probably never be used in future encodings as - //! AVX512 uses only `000mm` from `mmmmm`. + //! NOTE: Since `MM` field is defined as `mmmmm` (5 bits), but only 2 least significant bits are used by VEX and + //! EVEX prefixes, and additional 4th bit is used by XOP prefix, AsmJit uses the 3rd and 5th bit for it's own + //! purposes. These bits will probably never be used in future encodings as AVX512 uses only `000mm` from `mmmmm`. //! - //! - `PP` field is used to encode prefixes needed by the instruction or as a - //! part of VEX/EVEX prefix. Described as `pp` in instruction manuals. + //! - `PP` field is used to encode prefixes needed by the instruction or as a part of VEX/EVEX prefix. Described as + //! `pp` in instruction manuals. //! - //! - `LL` field is used exclusively by AVX+ and AVX512+ instruction sets. It - //! describes vector size, which is `L.128` for XMM register, `L.256` for - //! for YMM register, and `L.512` for ZMM register. The `LL` field is omitted - //! in case that instruction supports multiple vector lengths, however, if the - //! instruction requires specific `L` value it must be specified as a part of - //! the opcode. + //! - `LL` field is used exclusively by AVX+ and AVX512+ instruction sets. It describes vector size, which is `L.128` + //! for XMM register, `L.256` for for YMM register, and `L.512` for ZMM register. The `LL` field is omitted in case + //! that instruction supports multiple vector lengths, however, if the instruction requires specific `L` value it + //! must be specified as a part of the opcode. //! //! NOTE: `LL` having value `11` is not defined yet. //! - //! - `W` field is the most complicated. It was added by 64-bit architecture - //! to promote default operation width (instructions that perform 32-bit - //! operation by default require to override the width to 64-bit explicitly). - //! There is nothing wrong on this, however, some instructions introduced - //! implicit `W` override, for example a `cdqe` instruction is basically a - //! `cwde` instruction with overridden `W` (set to 1). There are some others - //! in the base X86 instruction set. More recent instruction sets started - //! using `W` field more often: + //! - `W` field is the most complicated. It was added by 64-bit architecture to promote default operation width + //! (instructions that perform 32-bit operation by default require to override the width to 64-bit explicitly). + //! There is nothing wrong on this, however, some instructions introduced implicit `W` override, for example a + //! `cdqe` instruction is basically a `cwde` instruction with overridden `W` (set to 1). There are some others + //! in the base X86 instruction set. More recent instruction sets started using `W` field more often: //! - //! - AVX instructions started using `W` field as an extended opcode for FMA, - //! GATHER, PERM, and other instructions. It also uses `W` field to override - //! the default operation width in instructions like `vmovq`. + //! - AVX instructions started using `W` field as an extended opcode for FMA, GATHER, PERM, and other instructions. + //! It also uses `W` field to override the default operation width in instructions like `vmovq`. //! - //! - AVX-512 instructions started using `W` field as an extended opcode for - //! all new instructions. This wouldn't have been an issue if the `W` field - //! of AVX-512 have matched AVX, but this is not always the case. + //! - AVX-512 instructions started using `W` field as an extended opcode for all new instructions. This wouldn't + //! have been an issue if the `W` field of AVX-512 have matched AVX, but this is not always the case. //! //! - `O` field is an extended opcode field (3 bits) embedded in ModR/M BYTE. //! - //! - `CDSHL` and `CDTT` fields describe 'compressed-displacement'. `CDSHL` is - //! defined for each instruction that is AVX-512 encodable (EVEX) and contains - //! a base N shift (base shift to perform the calculation). The `CDTT` field - //! is derived from instruction specification and describes additional shift - //! to calculate the final `CDSHL` that will be used in SIB byte. + //! - `CDSHL` and `CDTT` fields describe 'compressed-displacement'. `CDSHL` is defined for each instruction that is + //! AVX-512 encodable (EVEX) and contains a base N shift (base shift to perform the calculation). The `CDTT` field + //! is derived from instruction specification and describes additional shift to calculate the final `CDSHL` that + //! will be used in SIB byte. //! - //! \note Don't reorder any fields here, the shifts and masks were defined - //! carefully to make encoding of X86 instructions fast, especially to construct - //! REX, VEX, and EVEX prefixes in the most efficient way. Changing values defined - //! by these enums many cause AsmJit to emit invalid binary representations of - //! instructions passed to `x86::Assembler::_emit`. + //! \note Don't reorder any fields here, the shifts and masks were defined carefully to make encoding of X86 + //! instructions fast, especially to construct REX, VEX, and EVEX prefixes in the most efficient way. Changing + //! values defined by these enums many cause AsmJit to emit invalid binary representations of instructions passed to + //! `x86::Assembler::_emit`. enum Bits : uint32_t { // MM & VEX & EVEX & XOP // --------------------- @@ -119,22 +82,15 @@ struct Opcode { // * Part of a legacy opcode (prefixes emitted before the main opcode byte). // * `MMMMM` field in VEX|EVEX|XOP instruction. // - // AVX reserves 5 bits for `MMMMM` field, however AVX instructions only use - // 2 bits and XOP 3 bits. AVX-512 shrinks `MMMMM` field into `MM` so it's - // safe to assume that bits [4:2] of `MM` field won't be used in future - // extensions, which will most probably use EVEX encoding. AsmJit divides - // MM field into this layout: + // AVX reserves 5 bits for `MMMMM` field, however AVX instructions only use 2 bits and XOP 3 bits. AVX-512 shrinks + // `MMMMM` field into `MMM` so it's safe to use [4:3] bits of `MMMMM` field for internal payload. // - // [1:0] - Used to describe 0F, 0F38 and 0F3A legacy prefix bytes and - // 2 bits of MM field. - // [2] - Used to force 3-BYTE VEX prefix, but then cleared to zero before - // the prefix is emitted. This bit is not used by any instruction - // so it can be used for any purpose by AsmJit. Also, this bit is - // used as an extension to `MM` field describing 0F|0F38|0F3A to also - // describe 0F01 as used by some legacy instructions (instructions - // not using VEX/EVEX prefix). - // [3] - Required by XOP instructions, so we use this bit also to indicate - // that this is a XOP opcode. + // AsmJit divides MMMMM field into this layout: + // + // [2:0] - Used to describe 0F, 0F38 and 0F3A legacy prefix bytes and 3 bits of MMMMM field for XOP/AVX/AVX512. + // [3] - Required by XOP instructions, so we use this bit also to indicate that this is a XOP opcode. + // [4] - Used to force EVEX prefix - this bit is not used by any X86 instruction yet, so AsmJit uses it to + // describe EVEX only instructions or sets its bit when user uses InstOptions::kX86_Evex to force EVEX. kMM_Shift = 8, kMM_Mask = 0x1Fu << kMM_Shift, kMM_00 = 0x00u << kMM_Shift, @@ -143,11 +99,12 @@ struct Opcode { kMM_0F3A = 0x03u << kMM_Shift, // Described also as XOP.M3 in AMD manuals. kMM_0F01 = 0x04u << kMM_Shift, // AsmJit way to describe 0F01 (never VEX/EVEX). - // `XOP` field is only used to force XOP prefix instead of VEX3 prefix. We - // know that only XOP encoding uses bit 0b1000 of MM field and that no VEX - // and EVEX instruction uses such bit, so we can use this bit to force XOP - // prefix to be emitted instead of VEX3 prefix. See `x86VEXPrefix` defined - // in `x86assembler.cpp`. + kMM_MAP5 = 0x05u << kMM_Shift, // EVEX.MAP5. + kMM_MAP6 = 0x06u << kMM_Shift, // EVEX.MAP6. + + // `XOP` field is only used to force XOP prefix instead of VEX3 prefix. We know XOP encodings always use 0b1000 + // bit of MM field and that no VEX and EVEX instruction use such bit yet, so we can use this bit to force XOP + // prefix to be emitted instead of VEX3 prefix. See `x86VEXPrefix` defined in `x86assembler.cpp`. kMM_XOP08 = 0x08u << kMM_Shift, // XOP.M8. kMM_XOP09 = 0x09u << kMM_Shift, // XOP.M9. kMM_XOP0A = 0x0Au << kMM_Shift, // XOP.MA. @@ -155,21 +112,17 @@ struct Opcode { kMM_IsXOP_Shift= kMM_Shift + 3, kMM_IsXOP = kMM_XOP08, - // NOTE: Force VEX3 allows to force to emit VEX3 instead of VEX2 in some - // cases (similar to forcing REX prefix). Force EVEX will force emitting - // EVEX prefix instead of VEX2|VEX3. EVEX-only instructions will have - // ForceEvex always set, however. instructions that can be encoded by - // either VEX or EVEX prefix should not have ForceEvex set. - - kMM_ForceVex3 = 0x04u << kMM_Shift, // Force 3-BYTE VEX prefix. + // NOTE: Force VEX3 allows to force to emit VEX3 instead of VEX2 in some cases (similar to forcing REX prefix). + // Force EVEX will force emitting EVEX prefix instead of VEX2|VEX3. EVEX-only instructions will have ForceEvex + // always set, however. instructions that can be encoded by either VEX or EVEX prefix should not have ForceEvex + // set. kMM_ForceEvex = 0x10u << kMM_Shift, // Force 4-BYTE EVEX prefix. // FPU_2B - Second-Byte of the Opcode used by FPU // ---------------------------------------------- // - // Second byte opcode. This BYTE is ONLY used by FPU instructions and - // collides with 3 bits from `MM` and 5 bits from 'CDSHL' and 'CDTT'. - // It's fine as FPU and AVX512 flags are never used at the same time. + // Second byte opcode. This BYTE is ONLY used by FPU instructions and collides with 3 bits from `MM` and 5 bits + // from 'CDSHL' and 'CDTT'. It's fine as FPU and AVX512 flags are never used at the same time. kFPU_2B_Shift = 10, kFPU_2B_Mask = 0xFF << kFPU_2B_Shift, @@ -203,8 +156,8 @@ struct Opcode { // Compressed displacement tuple-type (specific to AsmJit). // - // Since we store the base offset independently of CDTT we can simplify the - // number of 'TUPLE_TYPE' groups significantly and just handle special cases. + // Since we store the base offset independently of CDTT we can simplify the number of 'TUPLE_TYPE' groups + // significantly and just handle special cases. kCDTT_Shift = 16, kCDTT_Mask = 0x3u << kCDTT_Shift, kCDTT_None = 0x0u << kCDTT_Shift, // Does nothing. @@ -216,10 +169,12 @@ struct Opcode { kCDTT__ = kCDTT_None, kCDTT_FV = kCDTT_ByLL, kCDTT_HV = kCDTT_ByLL, + kCDTT_QV = kCDTT_ByLL, kCDTT_FVM = kCDTT_ByLL, kCDTT_T1S = kCDTT_None, kCDTT_T1F = kCDTT_None, kCDTT_T1_4X = kCDTT_None, + kCDTT_T4X = kCDTT_None, // Alias to have only 3 letters. kCDTT_T2 = kCDTT_None, kCDTT_T4 = kCDTT_None, kCDTT_T8 = kCDTT_None, @@ -228,8 +183,6 @@ struct Opcode { kCDTT_OVM = kCDTT_ByLL, kCDTT_128 = kCDTT_None, - kCDTT_T4X = kCDTT_T1_4X, // Alias to have only 3 letters. - // `O` Field in ModR/M (??:xxx:???) // -------------------------------- @@ -249,9 +202,8 @@ struct Opcode { // `RM` Field in ModR/M (??:???:xxx) // --------------------------------- // - // Second data field used by ModR/M byte. This is only used by few - // instructions that use OPCODE+MOD/RM where both values in Mod/RM - // are part of the opcode. + // Second data field used by ModR/M byte. This is only used by few instructions that use OPCODE+MOD/RM where both + // values in Mod/RM are part of the opcode. kModRM_Shift = 13, kModRM_Mask = 0x7u << kModRM_Shift, @@ -269,16 +221,15 @@ struct Opcode { // `PP` Field // ---------- // - // These fields are stored deliberately right after each other as it makes - // it easier to construct VEX prefix from the opcode value stored in the - // instruction database. + // These fields are stored deliberately right after each other as it makes it easier to construct VEX prefix from + // the opcode value stored in the instruction database. // // Two meanings: // * "PP" field in AVX/XOP/AVX-512 instruction. // * Mandatory Prefix in legacy encoding. // - // AVX reserves 2 bits for `PP` field, but AsmJit extends the storage by 1 - // more bit that is used to emit 9B prefix for some X87-FPU instructions. + // AVX reserves 2 bits for `PP` field, but AsmJit extends the storage by 1 more bit that is used to emit 9B prefix + // for some X87-FPU instructions. kPP_Shift = 21, kPP_VEXMask = 0x03u << kPP_Shift, // PP field mask used by VEX/EVEX. @@ -293,9 +244,8 @@ struct Opcode { // REX|VEX|EVEX B|X|R|W Bits // ------------------------- // - // NOTE: REX.[B|X|R] are never stored within the opcode itself, they are - // reserved by AsmJit are are added dynamically to the opcode to represent - // [REX|VEX|EVEX].[B|X|R] bits. REX.W can be stored in DB as it's sometimes + // NOTE: REX.[B|X|R] are never stored within the opcode itself, they are reserved by AsmJit are are added + // dynamically to the opcode to represent [REX|VEX|EVEX].[B|X|R] bits. REX.W can be stored in DB as it's sometimes // part of the opcode itself. // These must be binary compatible with instruction options. @@ -330,11 +280,9 @@ struct Opcode { // `L` or `LL` field in AVX/XOP/AVX-512 // ------------------------------------ // - // VEX/XOP prefix can only use the first bit `L.128` or `L.256`. EVEX prefix - // prefix makes it possible to use also `L.512`. - // - // If the instruction set manual describes an instruction by `LIG` it means - // that the `L` field is ignored and AsmJit defaults to `0` in such case. + // VEX/XOP prefix can only use the first bit `L.128` or `L.256`. EVEX prefix prefix makes it possible to use also + // `L.512`. If the instruction set manual describes an instruction by `LIG` it means that the `L` field is ignored + // and AsmJit defaults to `0` in such case. kLL_Shift = 29, kLL_Mask = 0x3u << kLL_Shift, @@ -353,23 +301,31 @@ struct Opcode { k000F00 = kPP_00 | kMM_0F, // '0F' k000F01 = kPP_00 | kMM_0F01, // '0F01' k000F0F = kPP_00 | kMM_0F, // '0F0F' - 3DNOW, equal to 0x0F, must have special encoding to take effect. - k000F38 = kPP_00 | kMM_0F38, // '0F38' - k000F3A = kPP_00 | kMM_0F3A, // '0F3A' + k000F38 = kPP_00 | kMM_0F38, // 'NP.0F38' + k000F3A = kPP_00 | kMM_0F3A, // 'NP.0F3A' + k00MAP5 = kPP_00 | kMM_MAP5, // 'NP.MAP5' + k00MAP6 = kPP_00 | kMM_MAP6, // 'NP.MAP5' k660000 = kPP_66 | kMM_00, // '66' - k660F00 = kPP_66 | kMM_0F, // '660F' - k660F01 = kPP_66 | kMM_0F01, // '660F01' - k660F38 = kPP_66 | kMM_0F38, // '660F38' - k660F3A = kPP_66 | kMM_0F3A, // '660F3A' + k660F00 = kPP_66 | kMM_0F, // '66.0F' + k660F01 = kPP_66 | kMM_0F01, // '66.0F01' + k660F38 = kPP_66 | kMM_0F38, // '66.0F38' + k660F3A = kPP_66 | kMM_0F3A, // '66.0F3A' + k66MAP5 = kPP_66 | kMM_MAP5, // '66.MAP5' + k66MAP6 = kPP_66 | kMM_MAP6, // '66.MAP5' kF20000 = kPP_F2 | kMM_00, // 'F2' - kF20F00 = kPP_F2 | kMM_0F, // 'F20F' - kF20F01 = kPP_F2 | kMM_0F01, // 'F20F01' - kF20F38 = kPP_F2 | kMM_0F38, // 'F20F38' - kF20F3A = kPP_F2 | kMM_0F3A, // 'F20F3A' + kF20F00 = kPP_F2 | kMM_0F, // 'F2.0F' + kF20F01 = kPP_F2 | kMM_0F01, // 'F2.0F01' + kF20F38 = kPP_F2 | kMM_0F38, // 'F2.0F38' + kF20F3A = kPP_F2 | kMM_0F3A, // 'F2.0F3A' + kF2MAP5 = kPP_F2 | kMM_MAP5, // 'F2.MAP5' + kF2MAP6 = kPP_F2 | kMM_MAP6, // 'F2.MAP5' kF30000 = kPP_F3 | kMM_00, // 'F3' - kF30F00 = kPP_F3 | kMM_0F, // 'F30F' - kF30F01 = kPP_F3 | kMM_0F01, // 'F30F01' - kF30F38 = kPP_F3 | kMM_0F38, // 'F30F38' - kF30F3A = kPP_F3 | kMM_0F3A, // 'F30F3A' + kF30F00 = kPP_F3 | kMM_0F, // 'F3.0F' + kF30F01 = kPP_F3 | kMM_0F01, // 'F3.0F01' + kF30F38 = kPP_F3 | kMM_0F38, // 'F3.0F38' + kF30F3A = kPP_F3 | kMM_0F3A, // 'F3.0F3A' + kF3MAP5 = kPP_F3 | kMM_MAP5, // 'F3.MAP5' + kF3MAP6 = kPP_F3 | kMM_MAP6, // 'F3.MAP5' kFPU_00 = kPP_00 | kMM_00, // '__' (FPU) kFPU_9B = kPP_9B | kMM_00, // '9B' (FPU) kXOP_M8 = kPP_00 | kMM_XOP08, // 'M8' (XOP) @@ -377,31 +333,30 @@ struct Opcode { kXOP_MA = kPP_00 | kMM_XOP0A // 'MA' (XOP) }; - // -------------------------------------------------------------------------- - // [Opcode Builder] - // -------------------------------------------------------------------------- + // Opcode Builder + // -------------- - ASMJIT_INLINE uint32_t get() const noexcept { return v; } + inline uint32_t get() const noexcept { return v; } - ASMJIT_INLINE bool hasW() const noexcept { return (v & kW) != 0; } - ASMJIT_INLINE bool has66h() const noexcept { return (v & kPP_66) != 0; } + inline bool hasW() const noexcept { return (v & kW) != 0; } + inline bool has66h() const noexcept { return (v & kPP_66) != 0; } - ASMJIT_INLINE Opcode& add(uint32_t x) noexcept { return operator+=(x); } + inline Opcode& add(uint32_t x) noexcept { return operator+=(x); } - ASMJIT_INLINE Opcode& add66h() noexcept { return operator|=(kPP_66); } + inline Opcode& add66h() noexcept { return operator|=(kPP_66); } template<typename T> - ASMJIT_INLINE Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); } + inline Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); } template<typename T> - ASMJIT_INLINE Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); } + inline Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); } - ASMJIT_INLINE Opcode& addW() noexcept { return operator|=(kW); } + inline Opcode& addW() noexcept { return operator|=(kW); } template<typename T> - ASMJIT_INLINE Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); } + inline Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); } template<typename T> - ASMJIT_INLINE Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); } + inline Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); } template<typename T> - ASMJIT_INLINE Opcode& addPrefixBySize(T size) noexcept { + inline Opcode& addPrefixBySize(T size) noexcept { static const uint32_t mask[16] = { 0, // #0 0, // #1 -> nothing (already handled or not possible) @@ -417,7 +372,7 @@ struct Opcode { } template<typename T> - ASMJIT_INLINE Opcode& addArithBySize(T size) noexcept { + inline Opcode& addArithBySize(T size) noexcept { static const uint32_t mask[16] = { 0, // #0 0, // #1 -> nothing @@ -432,46 +387,45 @@ struct Opcode { return operator|=(mask[size & 0xF]); } - ASMJIT_INLINE Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); } + inline Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); } template<typename T> - ASMJIT_INLINE Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::constCtz(uint32_t(kMM_ForceEvex))); } + inline Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); } //! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals). - ASMJIT_INLINE uint32_t extractModO() const noexcept { + inline uint32_t extractModO() const noexcept { return (v >> kModO_Shift) & 0x07; } //! Extract `RM` field (RM) from the opcode (usually specified as another opcode value). - ASMJIT_INLINE uint32_t extractModRM() const noexcept { + inline uint32_t extractModRM() const noexcept { return (v >> kModRM_Shift) & 0x07; } //! Extract `REX` prefix from opcode combined with `options`. - ASMJIT_INLINE uint32_t extractRex(uint32_t options) const noexcept { - // kREX was designed in a way that when shifted there will be no bytes - // set except REX.[B|X|R|W]. The returned value forms a real REX prefix byte. - // This case should be unit-tested as well. - return (v | options) >> kREX_Shift; + inline uint32_t extractRex(InstOptions options) const noexcept { + // kREX was designed in a way that when shifted there will be no bytes set except REX.[B|X|R|W]. + // The returned value forms a real REX prefix byte. This case should be unit-tested as well. + return (v | uint32_t(options)) >> kREX_Shift; } - ASMJIT_INLINE uint32_t extractLLMM(uint32_t options) const noexcept { - uint32_t x = v & (kLL_Mask | kMM_Mask); - uint32_t y = options & (Inst::kOptionVex3 | Inst::kOptionEvex); - return (x | y) >> kMM_Shift; + inline uint32_t extractLLMMMMM(InstOptions options) const noexcept { + uint32_t llMmmmm = uint32_t(v & (kLL_Mask | kMM_Mask)); + uint32_t vexEvex = uint32_t(options & InstOptions::kX86_Evex); + return (llMmmmm | vexEvex) >> kMM_Shift; } - ASMJIT_INLINE Opcode& operator=(uint32_t x) noexcept { v = x; return *this; } - ASMJIT_INLINE Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; } - ASMJIT_INLINE Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; } - ASMJIT_INLINE Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; } - ASMJIT_INLINE Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; } - ASMJIT_INLINE Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; } - - ASMJIT_INLINE uint32_t operator&(uint32_t x) const noexcept { return v & x; } - ASMJIT_INLINE uint32_t operator|(uint32_t x) const noexcept { return v | x; } - ASMJIT_INLINE uint32_t operator^(uint32_t x) const noexcept { return v ^ x; } - ASMJIT_INLINE uint32_t operator<<(uint32_t x) const noexcept { return v << x; } - ASMJIT_INLINE uint32_t operator>>(uint32_t x) const noexcept { return v >> x; } + inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; } + inline Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; } + inline Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; } + inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; } + inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; } + inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; } + + inline uint32_t operator&(uint32_t x) const noexcept { return v & x; } + inline uint32_t operator|(uint32_t x) const noexcept { return v | x; } + inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; } + inline uint32_t operator<<(uint32_t x) const noexcept { return v << x; } + inline uint32_t operator>>(uint32_t x) const noexcept { return v >> x; } }; //! \} diff --git a/src/asmjit/x86/x86operand.cpp b/src/asmjit/x86/x86operand.cpp index 47270c0..a47fec2 100644 --- a/src/asmjit/x86/x86operand.cpp +++ b/src/asmjit/x86/x86operand.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) @@ -29,9 +11,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::Operand - Unit] -// ============================================================================ +// x86::Operand - Tests +// ==================== #if defined(ASMJIT_TEST) UNIT(x86_operand) { @@ -92,16 +73,16 @@ UNIT(x86_operand) { EXPECT(eax.isReg() == true); EXPECT(eax.id() == 0); EXPECT(eax.size() == 4); - EXPECT(eax.type() == Reg::kTypeGpd); - EXPECT(eax.group() == Reg::kGroupGp); + EXPECT(eax.type() == RegType::kX86_Gpd); + EXPECT(eax.group() == RegGroup::kGp); INFO("Checking x86::Xmm register properties"); EXPECT(Xmm().isReg() == true); EXPECT(xmm4.isReg() == true); EXPECT(xmm4.id() == 4); EXPECT(xmm4.size() == 16); - EXPECT(xmm4.type() == Reg::kTypeXmm); - EXPECT(xmm4.group() == Reg::kGroupVec); + EXPECT(xmm4.type() == RegType::kX86_Xmm); + EXPECT(xmm4.group() == RegGroup::kVec); EXPECT(xmm4.isVec()); INFO("Checking x86::Ymm register properties"); @@ -109,8 +90,8 @@ UNIT(x86_operand) { EXPECT(ymm5.isReg() == true); EXPECT(ymm5.id() == 5); EXPECT(ymm5.size() == 32); - EXPECT(ymm5.type() == Reg::kTypeYmm); - EXPECT(ymm5.group() == Reg::kGroupVec); + EXPECT(ymm5.type() == RegType::kX86_Ymm); + EXPECT(ymm5.group() == RegGroup::kVec); EXPECT(ymm5.isVec()); INFO("Checking x86::Zmm register properties"); @@ -118,8 +99,8 @@ UNIT(x86_operand) { EXPECT(zmm6.isReg() == true); EXPECT(zmm6.id() == 6); EXPECT(zmm6.size() == 64); - EXPECT(zmm6.type() == Reg::kTypeZmm); - EXPECT(zmm6.group() == Reg::kGroupVec); + EXPECT(zmm6.type() == RegType::kX86_Zmm); + EXPECT(zmm6.group() == RegGroup::kVec); EXPECT(zmm6.isVec()); INFO("Checking x86::Vec register properties"); @@ -149,24 +130,24 @@ UNIT(x86_operand) { EXPECT(mm2.isReg() == true); EXPECT(mm2.id() == 2); EXPECT(mm2.size() == 8); - EXPECT(mm2.type() == Reg::kTypeMm); - EXPECT(mm2.group() == Reg::kGroupMm); + EXPECT(mm2.type() == RegType::kX86_Mm); + EXPECT(mm2.group() == RegGroup::kX86_MM); INFO("Checking x86::KReg register properties"); EXPECT(KReg().isReg() == true); EXPECT(k3.isReg() == true); EXPECT(k3.id() == 3); EXPECT(k3.size() == 0); - EXPECT(k3.type() == Reg::kTypeKReg); - EXPECT(k3.group() == Reg::kGroupKReg); + EXPECT(k3.type() == RegType::kX86_KReg); + EXPECT(k3.group() == RegGroup::kX86_K); INFO("Checking x86::St register properties"); EXPECT(St().isReg() == true); EXPECT(st1.isReg() == true); EXPECT(st1.id() == 1); EXPECT(st1.size() == 10); - EXPECT(st1.type() == Reg::kTypeSt); - EXPECT(st1.group() == Reg::kGroupSt); + EXPECT(st1.type() == RegType::kX86_St); + EXPECT(st1.group() == RegGroup::kX86_St); INFO("Checking if default constructed regs behave as expected"); EXPECT(Reg().isValid() == false); @@ -207,13 +188,15 @@ UNIT(x86_operand) { m.addOffset(1); EXPECT(m.offset() == int64_t(0x0123456789ABCDF0u)); - m = ptr(0x0123456789ABCDEFu, rdi, 4); + m = ptr(0x0123456789ABCDEFu, rdi, 3); + EXPECT(m.hasSegment() == false); EXPECT(m.hasBase() == false); EXPECT(m.hasBaseReg() == false); EXPECT(m.hasIndex() == true); EXPECT(m.hasIndexReg() == true); EXPECT(m.indexType() == rdi.type()); EXPECT(m.indexId() == rdi.id()); + EXPECT(m.shift() == 3); EXPECT(m.hasOffset() == true); EXPECT(m.isOffset64Bit() == true); EXPECT(m.offset() == int64_t(0x0123456789ABCDEFu)); @@ -229,7 +212,7 @@ UNIT(x86_operand) { EXPECT(m.baseId() == rax.id()); EXPECT(m.hasIndex() == false); EXPECT(m.hasIndexReg() == false); - EXPECT(m.indexType() == 0); + EXPECT(m.indexType() == RegType::kNone); EXPECT(m.indexId() == 0); EXPECT(m.hasOffset() == false); EXPECT(m.isOffset64Bit() == false); diff --git a/src/asmjit/x86/x86operand.h b/src/asmjit/x86/x86operand.h index 917c0f9..bfd09bd 100644 --- a/src/asmjit/x86/x86operand.h +++ b/src/asmjit/x86/x86operand.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86OPERAND_H_INCLUDED #define ASMJIT_X86_X86OPERAND_H_INCLUDED @@ -31,62 +13,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -#define ASMJIT_MEM_PTR(FUNC, SIZE) \ - static constexpr Mem FUNC(const Gp& base, int32_t offset = 0) noexcept { \ - return Mem(base, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ - return Mem(base, index, shift, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ - return Mem(base, index, shift, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Label& base, int32_t offset = 0) noexcept { \ - return Mem(base, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ - return Mem(base, index, shift, offset, SIZE); \ - } \ - static constexpr Mem FUNC(const Rip& rip_, int32_t offset = 0) noexcept { \ - return Mem(rip_, offset, SIZE); \ - } \ - static constexpr Mem FUNC(uint64_t base) noexcept { \ - return Mem(base, SIZE); \ - } \ - static constexpr Mem FUNC(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE); \ - } \ - static constexpr Mem FUNC(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE); \ - } \ - \ - static constexpr Mem FUNC##_abs(uint64_t base) noexcept { \ - return Mem(base, SIZE, Mem::kSignatureMemAbs); \ - } \ - static constexpr Mem FUNC##_abs(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs); \ - } \ - static constexpr Mem FUNC##_abs(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs); \ - } \ - \ - static constexpr Mem FUNC##_rel(uint64_t base) noexcept { \ - return Mem(base, SIZE, Mem::kSignatureMemRel); \ - } \ - static constexpr Mem FUNC##_rel(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, Mem::kSignatureMemRel); \ - } \ - static constexpr Mem FUNC##_rel(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ - return Mem(base, index, shift, SIZE, Mem::kSignatureMemRel); \ - } - //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - class Reg; class Mem; @@ -111,40 +40,35 @@ class Bnd; class Tmm; class Rip; -// ============================================================================ -// [asmjit::x86::Reg] -// ============================================================================ - //! Register traits (X86). //! -//! Register traits contains information about a particular register type. It's -//! used by asmjit to setup register information on-the-fly and to populate -//! tables that contain register information (this way it's possible to change +//! Register traits contains information about a particular register type. It's used by asmjit to setup register +//! information on-the-fly and to populate tables that contain register information (this way it's possible to change //! register types and groups without having to reorder these tables). -template<uint32_t REG_TYPE> +template<RegType kRegType> struct RegTraits : public BaseRegTraits {}; //! \cond -// <--------------------+-----+-------------------------+------------------------+---+---+----------------+ -// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | -// <--------------------+-----+-------------------------+------------------------+---+---+----------------+ -ASMJIT_DEFINE_REG_TRAITS(GpbLo, BaseReg::kTypeGp8Lo , BaseReg::kGroupGp , 1 , 16, Type::kIdI8 ); -ASMJIT_DEFINE_REG_TRAITS(GpbHi, BaseReg::kTypeGp8Hi , BaseReg::kGroupGp , 1 , 4 , Type::kIdI8 ); -ASMJIT_DEFINE_REG_TRAITS(Gpw , BaseReg::kTypeGp16 , BaseReg::kGroupGp , 2 , 16, Type::kIdI16 ); -ASMJIT_DEFINE_REG_TRAITS(Gpd , BaseReg::kTypeGp32 , BaseReg::kGroupGp , 4 , 16, Type::kIdI32 ); -ASMJIT_DEFINE_REG_TRAITS(Gpq , BaseReg::kTypeGp64 , BaseReg::kGroupGp , 8 , 16, Type::kIdI64 ); -ASMJIT_DEFINE_REG_TRAITS(Xmm , BaseReg::kTypeVec128 , BaseReg::kGroupVec , 16, 32, Type::kIdI32x4 ); -ASMJIT_DEFINE_REG_TRAITS(Ymm , BaseReg::kTypeVec256 , BaseReg::kGroupVec , 32, 32, Type::kIdI32x8 ); -ASMJIT_DEFINE_REG_TRAITS(Zmm , BaseReg::kTypeVec512 , BaseReg::kGroupVec , 64, 32, Type::kIdI32x16); -ASMJIT_DEFINE_REG_TRAITS(Mm , BaseReg::kTypeOther0 , BaseReg::kGroupOther0 , 8 , 8 , Type::kIdMmx64 ); -ASMJIT_DEFINE_REG_TRAITS(KReg , BaseReg::kTypeOther1 , BaseReg::kGroupOther1 , 0 , 8 , Type::kIdVoid ); -ASMJIT_DEFINE_REG_TRAITS(SReg , BaseReg::kTypeCustom + 0, BaseReg::kGroupVirt + 0, 2 , 7 , Type::kIdVoid ); -ASMJIT_DEFINE_REG_TRAITS(CReg , BaseReg::kTypeCustom + 1, BaseReg::kGroupVirt + 1, 0 , 16, Type::kIdVoid ); -ASMJIT_DEFINE_REG_TRAITS(DReg , BaseReg::kTypeCustom + 2, BaseReg::kGroupVirt + 2, 0 , 16, Type::kIdVoid ); -ASMJIT_DEFINE_REG_TRAITS(St , BaseReg::kTypeCustom + 3, BaseReg::kGroupVirt + 3, 10, 8 , Type::kIdF80 ); -ASMJIT_DEFINE_REG_TRAITS(Bnd , BaseReg::kTypeCustom + 4, BaseReg::kGroupVirt + 4, 16, 4 , Type::kIdVoid ); -ASMJIT_DEFINE_REG_TRAITS(Tmm , BaseReg::kTypeCustom + 5, BaseReg::kGroupVirt + 5, 0 , 8 , Type::kIdVoid ); -ASMJIT_DEFINE_REG_TRAITS(Rip , BaseReg::kTypeIP , BaseReg::kGroupVirt + 6, 0 , 1 , Type::kIdVoid ); +// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ +// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | +// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ +ASMJIT_DEFINE_REG_TRAITS(Rip , RegType::kX86_Rip , RegGroup::kX86_Rip , 0 , 1 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(GpbLo, RegType::kX86_GpbLo , RegGroup::kGp , 1 , 16, TypeId::kInt8 ); +ASMJIT_DEFINE_REG_TRAITS(GpbHi, RegType::kX86_GpbHi , RegGroup::kGp , 1 , 4 , TypeId::kInt8 ); +ASMJIT_DEFINE_REG_TRAITS(Gpw , RegType::kX86_Gpw , RegGroup::kGp , 2 , 16, TypeId::kInt16 ); +ASMJIT_DEFINE_REG_TRAITS(Gpd , RegType::kX86_Gpd , RegGroup::kGp , 4 , 16, TypeId::kInt32 ); +ASMJIT_DEFINE_REG_TRAITS(Gpq , RegType::kX86_Gpq , RegGroup::kGp , 8 , 16, TypeId::kInt64 ); +ASMJIT_DEFINE_REG_TRAITS(Xmm , RegType::kX86_Xmm , RegGroup::kVec , 16, 32, TypeId::kInt32x4 ); +ASMJIT_DEFINE_REG_TRAITS(Ymm , RegType::kX86_Ymm , RegGroup::kVec , 32, 32, TypeId::kInt32x8 ); +ASMJIT_DEFINE_REG_TRAITS(Zmm , RegType::kX86_Zmm , RegGroup::kVec , 64, 32, TypeId::kInt32x16); +ASMJIT_DEFINE_REG_TRAITS(KReg , RegType::kX86_KReg , RegGroup::kX86_K , 0 , 8 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(Mm , RegType::kX86_Mm , RegGroup::kX86_MM , 8 , 8 , TypeId::kMmx64 ); +ASMJIT_DEFINE_REG_TRAITS(SReg , RegType::kX86_SReg , RegGroup::kX86_SReg , 2 , 7 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(CReg , RegType::kX86_CReg , RegGroup::kX86_CReg , 0 , 16, TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(DReg , RegType::kX86_DReg , RegGroup::kX86_DReg , 0 , 16, TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(St , RegType::kX86_St , RegGroup::kX86_St , 10, 8 , TypeId::kFloat80 ); +ASMJIT_DEFINE_REG_TRAITS(Bnd , RegType::kX86_Bnd , RegGroup::kX86_Bnd , 16, 4 , TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(Tmm , RegType::kX86_Tmm , RegGroup::kX86_Tmm , 0 , 8 , TypeId::kVoid ); //! \endcond //! Register (X86). @@ -152,160 +76,84 @@ class Reg : public BaseReg { public: ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg) - //! Register type. - enum RegType : uint32_t { - //! No register type or invalid register. - kTypeNone = BaseReg::kTypeNone, - - //! Low GPB register (AL, BL, CL, DL, ...). - kTypeGpbLo = BaseReg::kTypeGp8Lo, - //! High GPB register (AH, BH, CH, DH only). - kTypeGpbHi = BaseReg::kTypeGp8Hi, - //! GPW register. - kTypeGpw = BaseReg::kTypeGp16, - //! GPD register. - kTypeGpd = BaseReg::kTypeGp32, - //! GPQ register (64-bit). - kTypeGpq = BaseReg::kTypeGp64, - //! XMM register (SSE+). - kTypeXmm = BaseReg::kTypeVec128, - //! YMM register (AVX+). - kTypeYmm = BaseReg::kTypeVec256, - //! ZMM register (AVX512+). - kTypeZmm = BaseReg::kTypeVec512, - //! MMX register. - kTypeMm = BaseReg::kTypeOther0, - //! K register (AVX512+). - kTypeKReg = BaseReg::kTypeOther1, - //! Instruction pointer (EIP, RIP). - kTypeRip = BaseReg::kTypeIP, - //! Segment register (None, ES, CS, SS, DS, FS, GS). - kTypeSReg = BaseReg::kTypeCustom + 0, - //! Control register (CR). - kTypeCReg = BaseReg::kTypeCustom + 1, - //! Debug register (DR). - kTypeDReg = BaseReg::kTypeCustom + 2, - //! FPU (x87) register. - kTypeSt = BaseReg::kTypeCustom + 3, - //! Bound register (BND). - kTypeBnd = BaseReg::kTypeCustom + 4, - //! TMM register (AMX_TILE) - kTypeTmm = BaseReg::kTypeCustom + 5, - - //! Count of register types. - kTypeCount = BaseReg::kTypeCustom + 6 - }; - - //! Register group. - enum RegGroup : uint32_t { - //! GP register group or none (universal). - kGroupGp = BaseReg::kGroupGp, - //! XMM|YMM|ZMM register group (universal). - kGroupVec = BaseReg::kGroupVec, - //! MMX register group (legacy). - kGroupMm = BaseReg::kGroupOther0, - //! K register group. - kGroupKReg = BaseReg::kGroupOther1, - - // These are not managed by Compiler nor used by Func-API: - - //! Segment register group. - kGroupSReg = BaseReg::kGroupVirt+0, - //! Control register group. - kGroupCReg = BaseReg::kGroupVirt+1, - //! Debug register group. - kGroupDReg = BaseReg::kGroupVirt+2, - //! FPU register group. - kGroupSt = BaseReg::kGroupVirt+3, - //! Bound register group. - kGroupBnd = BaseReg::kGroupVirt+4, - //! TMM register group. - kGroupTmm = BaseReg::kGroupVirt+5, - //! Instruction pointer (IP). - kGroupRip = BaseReg::kGroupVirt+6, - - //! Count of all register groups. - kGroupCount - }; - //! Tests whether the register is a GPB register (8-bit). - constexpr bool isGpb() const noexcept { return size() == 1; } + inline constexpr bool isGpb() const noexcept { return size() == 1; } //! Tests whether the register is a low GPB register (8-bit). - constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<kTypeGpbLo>::kSignature); } + inline constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbLo>::kSignature); } //! Tests whether the register is a high GPB register (8-bit). - constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<kTypeGpbHi>::kSignature); } + inline constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbHi>::kSignature); } //! Tests whether the register is a GPW register (16-bit). - constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<kTypeGpw>::kSignature); } + inline constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpw>::kSignature); } //! Tests whether the register is a GPD register (32-bit). - constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<kTypeGpd>::kSignature); } + inline constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); } //! Tests whether the register is a GPQ register (64-bit). - constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<kTypeGpq>::kSignature); } + inline constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); } //! Tests whether the register is an XMM register (128-bit). - constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<kTypeXmm>::kSignature); } + inline constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); } //! Tests whether the register is a YMM register (256-bit). - constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<kTypeYmm>::kSignature); } + inline constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); } //! Tests whether the register is a ZMM register (512-bit). - constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<kTypeZmm>::kSignature); } + inline constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); } //! Tests whether the register is an MMX register (64-bit). - constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<kTypeMm>::kSignature); } + inline constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); } //! Tests whether the register is a K register (64-bit). - constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<kTypeKReg>::kSignature); } + inline constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_KReg>::kSignature); } //! Tests whether the register is a segment register. - constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<kTypeSReg>::kSignature); } + inline constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_SReg>::kSignature); } //! Tests whether the register is a control register. - constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<kTypeCReg>::kSignature); } + inline constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_CReg>::kSignature); } //! Tests whether the register is a debug register. - constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<kTypeDReg>::kSignature); } + inline constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_DReg>::kSignature); } //! Tests whether the register is an FPU register (80-bit). - constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<kTypeSt>::kSignature); } + inline constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_St>::kSignature); } //! Tests whether the register is a bound register. - constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<kTypeBnd>::kSignature); } + inline constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Bnd>::kSignature); } //! Tests whether the register is a TMM register. - constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<kTypeTmm>::kSignature); } + inline constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Tmm>::kSignature); } //! Tests whether the register is RIP. - constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<kTypeRip>::kSignature); } + inline constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Rip>::kSignature); } - template<uint32_t REG_TYPE> + template<RegType REG_TYPE> inline void setRegT(uint32_t rId) noexcept { - setSignature(RegTraits<REG_TYPE>::kSignature); + setSignature(OperandSignature(RegTraits<REG_TYPE>::kSignature)); setId(rId); } - inline void setTypeAndId(uint32_t rType, uint32_t rId) noexcept { - ASMJIT_ASSERT(rType < kTypeCount); - setSignature(signatureOf(rType)); - setId(rId); + inline void setTypeAndId(RegType type, uint32_t id) noexcept { + setSignature(signatureOf(type)); + setId(id); } - static inline uint32_t groupOf(uint32_t rType) noexcept { return _archTraits[Environment::kArchX86].regTypeToGroup(rType); } - static inline uint32_t typeIdOf(uint32_t rType) noexcept { return _archTraits[Environment::kArchX86].regTypeToTypeId(rType); } - static inline uint32_t signatureOf(uint32_t rType) noexcept { return _archTraits[Environment::kArchX86].regTypeToSignature(rType); } + static inline RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToGroup(type); } + static inline TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToTypeId(type); } + static inline OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToSignature(type); } - template<uint32_t REG_TYPE> - static inline uint32_t groupOfT() noexcept { return RegTraits<REG_TYPE>::kGroup; } + template<RegType REG_TYPE> + static inline RegGroup groupOfT() noexcept { return RegGroup(RegTraits<REG_TYPE>::kGroup); } - template<uint32_t REG_TYPE> - static inline uint32_t typeIdOfT() noexcept { return RegTraits<REG_TYPE>::kTypeId; } + template<RegType REG_TYPE> + static inline TypeId typeIdOfT() noexcept { return TypeId(RegTraits<REG_TYPE>::kTypeId); } - template<uint32_t REG_TYPE> - static inline uint32_t signatureOfT() noexcept { return RegTraits<REG_TYPE>::kSignature; } + template<RegType REG_TYPE> + static inline OperandSignature signatureOfT() noexcept { return OperandSignature(RegTraits<REG_TYPE>::kSignature); } - static inline uint32_t signatureOfVecByType(uint32_t typeId) noexcept { - return typeId <= Type::_kIdVec128End ? RegTraits<kTypeXmm>::kSignature : - typeId <= Type::_kIdVec256End ? RegTraits<kTypeYmm>::kSignature : RegTraits<kTypeZmm>::kSignature; + static inline OperandSignature signatureOfVecByType(TypeId typeId) noexcept { + return OperandSignature(typeId <= TypeId::_kVec128End ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) : + typeId <= TypeId::_kVec256End ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) : + uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)); } - static inline uint32_t signatureOfVecBySize(uint32_t size) noexcept { - return size <= 16 ? RegTraits<kTypeXmm>::kSignature : - size <= 32 ? RegTraits<kTypeYmm>::kSignature : RegTraits<kTypeZmm>::kSignature; + static inline OperandSignature signatureOfVecBySize(uint32_t size) noexcept { + return OperandSignature(size <= 16 ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) : + size <= 32 ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) : + uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)); } //! Tests whether the `op` operand is either a low or high 8-bit GPB register. static inline bool isGpb(const Operand_& op) noexcept { // Check operand type, register group, and size. Not interested in register type. - const uint32_t kSgn = (Operand::kOpReg << kSignatureOpTypeShift) | - (1 << kSignatureSizeShift ) ; - return (op.signature() & (kSignatureOpTypeMask | kSignatureSizeMask)) == kSgn; + return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask | Signature::kSizeMask) == + (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp) | Signature::fromSize(1)); } static inline bool isGpbLo(const Operand_& op) noexcept { return op.as<Reg>().isGpbLo(); } @@ -353,9 +201,8 @@ public: //! Physical id (X86). //! - //! \note Register indexes have been reduced to only support general purpose - //! registers. There is no need to have enumerations with number suffix that - //! expands to the exactly same value as the suffix value itself. + //! \note Register indexes have been reduced to only support general purpose registers. There is no need to + //! have enumerations with number suffix that expands to the exactly same value as the suffix value itself. enum Id : uint32_t { kIdAx = 0, //!< Physical id of AL|AH|AX|EAX|RAX registers. kIdCx = 1, //!< Physical id of CL|CH|CX|ECX|RCX registers. @@ -402,13 +249,13 @@ class Vec : public Reg { //! Casts this register to a register that has half the size (or XMM if it's already XMM). inline Vec half() const noexcept { - return Vec::fromSignatureAndId(type() == kTypeZmm ? signatureOfT<kTypeYmm>() : signatureOfT<kTypeXmm>(), id()); + return Vec(type() == RegType::kX86_Zmm ? signatureOfT<RegType::kX86_Ymm>() : signatureOfT<RegType::kX86_Xmm>(), id()); } }; //! Segment register (X86). class SReg : public Reg { - ASMJIT_DEFINE_FINAL_REG(SReg, Reg, RegTraits<kTypeSReg>) + ASMJIT_DEFINE_FINAL_REG(SReg, Reg, RegTraits<RegType::kX86_SReg>) //! X86 segment id. enum Id : uint32_t { @@ -429,11 +276,9 @@ class SReg : public Reg { //! Count of X86 segment registers supported by AsmJit. //! - //! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS. - //! X64 architecture lowers them down to just FS and GS. AsmJit supports 7 - //! segment registers - all addressable in both X86 and X64 modes and one - //! extra called `SReg::kIdNone`, which is AsmJit specific and means that - //! there is no segment register specified. + //! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS. X64 architecture lowers them down to + //! just FS and GS. AsmJit supports 7 segment registers - all addressable in both X86 and X64 modes and one extra + //! called `SReg::kIdNone`, which is AsmJit specific and means that there is no segment register specified. kIdCount = 7 }; }; @@ -441,53 +286,53 @@ class SReg : public Reg { //! GPB low or high register (X86). class Gpb : public Gp { ASMJIT_DEFINE_ABSTRACT_REG(Gpb, Gp) }; //! GPB low register (X86). -class GpbLo : public Gpb { ASMJIT_DEFINE_FINAL_REG(GpbLo, Gpb, RegTraits<kTypeGpbLo>) }; +class GpbLo : public Gpb { ASMJIT_DEFINE_FINAL_REG(GpbLo, Gpb, RegTraits<RegType::kX86_GpbLo>) }; //! GPB high register (X86). -class GpbHi : public Gpb { ASMJIT_DEFINE_FINAL_REG(GpbHi, Gpb, RegTraits<kTypeGpbHi>) }; +class GpbHi : public Gpb { ASMJIT_DEFINE_FINAL_REG(GpbHi, Gpb, RegTraits<RegType::kX86_GpbHi>) }; //! GPW register (X86). -class Gpw : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpw, Gp, RegTraits<kTypeGpw>) }; +class Gpw : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpw, Gp, RegTraits<RegType::kX86_Gpw>) }; //! GPD register (X86). -class Gpd : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpd, Gp, RegTraits<kTypeGpd>) }; +class Gpd : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpd, Gp, RegTraits<RegType::kX86_Gpd>) }; //! GPQ register (X86_64). -class Gpq : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpq, Gp, RegTraits<kTypeGpq>) }; +class Gpq : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpq, Gp, RegTraits<RegType::kX86_Gpq>) }; //! 128-bit XMM register (SSE+). class Xmm : public Vec { - ASMJIT_DEFINE_FINAL_REG(Xmm, Vec, RegTraits<kTypeXmm>) + ASMJIT_DEFINE_FINAL_REG(Xmm, Vec, RegTraits<RegType::kX86_Xmm>) //! Casts this register to a register that has half the size (XMM). inline Xmm half() const noexcept { return Xmm(id()); } }; //! 256-bit YMM register (AVX+). class Ymm : public Vec { - ASMJIT_DEFINE_FINAL_REG(Ymm, Vec, RegTraits<kTypeYmm>) + ASMJIT_DEFINE_FINAL_REG(Ymm, Vec, RegTraits<RegType::kX86_Ymm>) //! Casts this register to a register that has half the size (XMM). inline Xmm half() const noexcept { return Xmm(id()); } }; //! 512-bit ZMM register (AVX512+). class Zmm : public Vec { - ASMJIT_DEFINE_FINAL_REG(Zmm, Vec, RegTraits<kTypeZmm>) + ASMJIT_DEFINE_FINAL_REG(Zmm, Vec, RegTraits<RegType::kX86_Zmm>) //! Casts this register to a register that has half the size (YMM). inline Ymm half() const noexcept { return Ymm(id()); } }; //! 64-bit MMX register (MMX+). -class Mm : public Reg { ASMJIT_DEFINE_FINAL_REG(Mm, Reg, RegTraits<kTypeMm>) }; +class Mm : public Reg { ASMJIT_DEFINE_FINAL_REG(Mm, Reg, RegTraits<RegType::kX86_Mm>) }; //! 64-bit K register (AVX512+). -class KReg : public Reg { ASMJIT_DEFINE_FINAL_REG(KReg, Reg, RegTraits<kTypeKReg>) }; +class KReg : public Reg { ASMJIT_DEFINE_FINAL_REG(KReg, Reg, RegTraits<RegType::kX86_KReg>) }; //! 32-bit or 64-bit control register (X86). -class CReg : public Reg { ASMJIT_DEFINE_FINAL_REG(CReg, Reg, RegTraits<kTypeCReg>) }; +class CReg : public Reg { ASMJIT_DEFINE_FINAL_REG(CReg, Reg, RegTraits<RegType::kX86_CReg>) }; //! 32-bit or 64-bit debug register (X86). -class DReg : public Reg { ASMJIT_DEFINE_FINAL_REG(DReg, Reg, RegTraits<kTypeDReg>) }; +class DReg : public Reg { ASMJIT_DEFINE_FINAL_REG(DReg, Reg, RegTraits<RegType::kX86_DReg>) }; //! 80-bit FPU register (X86). -class St : public Reg { ASMJIT_DEFINE_FINAL_REG(St, Reg, RegTraits<kTypeSt>) }; +class St : public Reg { ASMJIT_DEFINE_FINAL_REG(St, Reg, RegTraits<RegType::kX86_St>) }; //! 128-bit BND register (BND+). -class Bnd : public Reg { ASMJIT_DEFINE_FINAL_REG(Bnd, Reg, RegTraits<kTypeBnd>) }; +class Bnd : public Reg { ASMJIT_DEFINE_FINAL_REG(Bnd, Reg, RegTraits<RegType::kX86_Bnd>) }; //! 8192-bit TMM register (AMX). -class Tmm : public Reg { ASMJIT_DEFINE_FINAL_REG(Tmm, Reg, RegTraits<kTypeTmm>) }; +class Tmm : public Reg { ASMJIT_DEFINE_FINAL_REG(Tmm, Reg, RegTraits<RegType::kX86_Tmm>) }; //! RIP register (X86). -class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<kTypeRip>) }; +class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<RegType::kX86_Rip>) }; //! \cond inline GpbLo Gp::r8() const noexcept { return GpbLo(id()); } @@ -809,13 +654,12 @@ static constexpr Rip rip = Rip(0); using namespace regs; #endif -// ============================================================================ -// [asmjit::x86::Mem] -// ============================================================================ - -//! Memory operand. +//! Memory operand specific to X86 and X86_64 architecture. class Mem : public BaseMem { public: + //! \name Constants + //! \{ + //! Additional bits of operand's signature used by `x86::Mem`. enum AdditionalBits : uint32_t { // Memory address type (2 bits). @@ -840,85 +684,111 @@ public: }; //! Address type. - enum AddrType : uint32_t { + enum class AddrType : uint32_t { //! Default address type, Assembler will select the best type when necessary. - kAddrTypeDefault = 0, + kDefault = 0, //! Absolute address type. - kAddrTypeAbs = 1, + kAbs = 1, //! Relative address type. - kAddrTypeRel = 2 + kRel = 2, + + //! Maximum value of `AddrType`. + kMaxValue = kRel }; //! Memory broadcast type. - enum Broadcast : uint32_t { - //! Broadcast {1to1}. - kBroadcast1To1 = 0, + enum class Broadcast : uint32_t { + //! No broadcast (regular memory operand). + kNone = 0, //! Broadcast {1to2}. - kBroadcast1To2 = 1, + k1To2 = 1, //! Broadcast {1to4}. - kBroadcast1To4 = 2, + k1To4 = 2, //! Broadcast {1to8}. - kBroadcast1To8 = 3, + k1To8 = 3, //! Broadcast {1to16}. - kBroadcast1To16 = 4, + k1To16 = 4, //! Broadcast {1to32}. - kBroadcast1To32 = 5, + k1To32 = 5, //! Broadcast {1to64}. - kBroadcast1To64 = 6 - }; + k1To64 = 6, - //! \cond - //! Shortcuts. - enum SignatureMem : uint32_t { - kSignatureMemAbs = kAddrTypeAbs << kSignatureMemAddrTypeShift, - kSignatureMemRel = kAddrTypeRel << kSignatureMemAddrTypeShift + //! Maximum value of `Broadcast`. + kMaxValue = k1To64 }; - //! \endcond - // -------------------------------------------------------------------------- - // [Construction / Destruction] - // -------------------------------------------------------------------------- + //! \} + + //! \name Construction & Destruction + //! \{ //! Creates a default `Mem` operand that points to [0]. - constexpr Mem() noexcept + inline constexpr Mem() noexcept : BaseMem() {} - constexpr Mem(const Mem& other) noexcept + inline constexpr Mem(const Mem& other) noexcept : BaseMem(other) {} - //! \cond INTERNAL - //! - //! A constructor used internally to create `Mem` operand from `Decomposed` data. - constexpr explicit Mem(const Decomposed& d) noexcept - : BaseMem(d) {} - //! \endcond - - constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept - : BaseMem(Decomposed { Label::kLabelTag, base.id(), 0, 0, off, size, flags }) {} - - constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept - : BaseMem(Decomposed { Label::kLabelTag, base.id(), index.type(), index.id(), off, size, flags | (shift << kSignatureMemShiftValueShift) }) {} - - constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept - : BaseMem(Decomposed { base.type(), base.id(), 0, 0, off, size, flags }) {} - - constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept - : BaseMem(Decomposed { base.type(), base.id(), index.type(), index.id(), off, size, flags | (shift << kSignatureMemShiftValueShift) }) {} + inline explicit Mem(Globals::NoInit_) noexcept + : BaseMem(Globals::NoInit) {} - constexpr explicit Mem(uint64_t base, uint32_t size = 0, uint32_t flags = 0) noexcept - : BaseMem(Decomposed { 0, uint32_t(base >> 32), 0, 0, int32_t(uint32_t(base & 0xFFFFFFFFu)), size, flags }) {} + inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept + : BaseMem(signature, baseId, indexId, offset) {} + + inline constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(RegType::kLabelTag) | + Signature::fromSize(size) | + signature, base.id(), 0, off) {} + + inline constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(RegType::kLabelTag) | + Signature::fromMemIndexType(index.type()) | + Signature::fromValue<kSignatureMemShiftValueMask>(shift) | + Signature::fromSize(size) | + signature, base.id(), index.id(), off) {} + + inline constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(base.type()) | + Signature::fromSize(size) | + signature, base.id(), 0, off) {} + + inline constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(base.type()) | + Signature::fromMemIndexType(index.type()) | + Signature::fromValue<kSignatureMemShiftValueMask>(shift) | + Signature::fromSize(size) | + signature, base.id(), index.id(), off) {} + + inline constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromSize(size) | + signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {} + + inline constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemIndexType(index.type()) | + Signature::fromValue<kSignatureMemShiftValueMask>(shift) | + Signature::fromSize(size) | + signature, uint32_t(base >> 32), index.id(), int32_t(uint32_t(base & 0xFFFFFFFFu))) {} + + //! \} + + //! \name Overloaded Operators + //! \{ - constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, uint32_t flags = 0) noexcept - : BaseMem(Decomposed { 0, uint32_t(base >> 32), index.type(), index.id(), int32_t(uint32_t(base & 0xFFFFFFFFu)), size, flags | (shift << kSignatureMemShiftValueShift) }) {} + inline Mem& operator=(const Mem& other) noexcept = default; - constexpr Mem(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : BaseMem(Globals::Init, u0, u1, u2, u3) {} + //! \} - inline explicit Mem(Globals::NoInit_) noexcept - : BaseMem(Globals::NoInit) {} + //! \name Clone + //! \{ //! Clones the memory operand. - constexpr Mem clone() const noexcept { return Mem(*this); } + inline constexpr Mem clone() const noexcept { return Mem(*this); } //! Creates a new copy of this memory operand adjusted by `off`. inline Mem cloneAdjusted(int64_t off) const noexcept { @@ -927,6 +797,15 @@ public: return result; } + inline constexpr Mem cloneBroadcasted(Broadcast b) const noexcept { + return Mem((_signature & ~Signature(kSignatureMemBroadcastMask)) | Signature::fromValue<kSignatureMemBroadcastMask>(b), _baseId, _data[0], int32_t(_data[1])); + } + + //! \} + + //! \name Base & Index + //! \{ + //! Converts memory `baseType` and `baseId` to `x86::Reg` instance. //! //! The memory must have a valid base register otherwise the result will be wrong. @@ -937,18 +816,6 @@ public: //! The memory must have a valid index register otherwise the result will be wrong. inline Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); } - constexpr Mem _1to1() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To1 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - constexpr Mem _1to2() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To2 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - constexpr Mem _1to4() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To4 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - constexpr Mem _1to8() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To8 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - constexpr Mem _1to16() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To16 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - constexpr Mem _1to32() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To32 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - constexpr Mem _1to64() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To64 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); } - - // -------------------------------------------------------------------------- - // [Mem] - // -------------------------------------------------------------------------- - using BaseMem::setIndex; inline void setIndex(const BaseReg& index, uint32_t shift) noexcept { @@ -956,134 +823,220 @@ public: setShift(shift); } - //! Returns the address type (see \ref AddrType) of the memory operand. + //! \} + + //! \name Address Type + //! \{ + + //! Returns the address type of the memory operand. //! - //! By default, address type of newly created memory operands is always \ref kAddrTypeDefault. - constexpr uint32_t addrType() const noexcept { return _getSignaturePart<kSignatureMemAddrTypeMask>(); } - //! Sets the address type to `addrType`, see \ref AddrType. - inline void setAddrType(uint32_t addrType) noexcept { _setSignaturePart<kSignatureMemAddrTypeMask>(addrType); } - //! Resets the address type to \ref kAddrTypeDefault. - inline void resetAddrType() noexcept { _setSignaturePart<kSignatureMemAddrTypeMask>(0); } - - //! Tests whether the address type is \ref kAddrTypeAbs. - constexpr bool isAbs() const noexcept { return addrType() == kAddrTypeAbs; } - //! Sets the address type to \ref kAddrTypeAbs. - inline void setAbs() noexcept { setAddrType(kAddrTypeAbs); } - - //! Tests whether the address type is \ref kAddrTypeRel. - constexpr bool isRel() const noexcept { return addrType() == kAddrTypeRel; } - //! Sets the address type to \ref kAddrTypeRel. - inline void setRel() noexcept { setAddrType(kAddrTypeRel); } + //! By default, address type of newly created memory operands is always \ref AddrType::kDefault. + inline constexpr AddrType addrType() const noexcept { return (AddrType)_signature.getField<kSignatureMemAddrTypeMask>(); } + //! Sets the address type to `addrType`. + inline void setAddrType(AddrType addrType) noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(addrType)); } + //! Resets the address type to \ref AddrType::kDefault. + inline void resetAddrType() noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(AddrType::kDefault)); } + + //! Tests whether the address type is \ref AddrType::kAbs. + inline constexpr bool isAbs() const noexcept { return addrType() == AddrType::kAbs; } + //! Sets the address type to \ref AddrType::kAbs. + inline void setAbs() noexcept { setAddrType(AddrType::kAbs); } + + //! Tests whether the address type is \ref AddrType::kRel. + inline constexpr bool isRel() const noexcept { return addrType() == AddrType::kRel; } + //! Sets the address type to \ref AddrType::kRel. + inline void setRel() noexcept { setAddrType(AddrType::kRel); } + + //! \} + + //! \name Segment + //! \{ //! Tests whether the memory operand has a segment override. - constexpr bool hasSegment() const noexcept { return _hasSignaturePart<kSignatureMemSegmentMask>(); } + inline constexpr bool hasSegment() const noexcept { return _signature.hasField<kSignatureMemSegmentMask>(); } //! Returns the associated segment override as `SReg` operand. - constexpr SReg segment() const noexcept { return SReg(segmentId()); } + inline constexpr SReg segment() const noexcept { return SReg(segmentId()); } //! Returns segment override register id, see `SReg::Id`. - constexpr uint32_t segmentId() const noexcept { return _getSignaturePart<kSignatureMemSegmentMask>(); } + inline constexpr uint32_t segmentId() const noexcept { return _signature.getField<kSignatureMemSegmentMask>(); } //! Sets the segment override to `seg`. inline void setSegment(const SReg& seg) noexcept { setSegment(seg.id()); } //! Sets the segment override to `id`. - inline void setSegment(uint32_t rId) noexcept { _setSignaturePart<kSignatureMemSegmentMask>(rId); } + inline void setSegment(uint32_t rId) noexcept { _signature.setField<kSignatureMemSegmentMask>(rId); } //! Resets the segment override. - inline void resetSegment() noexcept { _setSignaturePart<kSignatureMemSegmentMask>(0); } + inline void resetSegment() noexcept { _signature.setField<kSignatureMemSegmentMask>(0); } + + //! \} + + //! \name Shift + //! \{ //! Tests whether the memory operand has shift (aka scale) value. - constexpr bool hasShift() const noexcept { return _hasSignaturePart<kSignatureMemShiftValueMask>(); } + inline constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); } //! Returns the memory operand's shift (aka scale) value. - constexpr uint32_t shift() const noexcept { return _getSignaturePart<kSignatureMemShiftValueMask>(); } + inline constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); } //! Sets the memory operand's shift (aka scale) value. - inline void setShift(uint32_t shift) noexcept { _setSignaturePart<kSignatureMemShiftValueMask>(shift); } + inline void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); } //! Resets the memory operand's shift (aka scale) value to zero. - inline void resetShift() noexcept { _setSignaturePart<kSignatureMemShiftValueMask>(0); } + inline void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); } + + //! \} + + //! \name Broadcast + //! \{ //! Tests whether the memory operand has broadcast {1tox}. - constexpr bool hasBroadcast() const noexcept { return _hasSignaturePart<kSignatureMemBroadcastMask>(); } + inline constexpr bool hasBroadcast() const noexcept { return _signature.hasField<kSignatureMemBroadcastMask>(); } //! Returns the memory operand's broadcast. - constexpr uint32_t getBroadcast() const noexcept { return _getSignaturePart<kSignatureMemBroadcastMask>(); } + inline constexpr Broadcast getBroadcast() const noexcept { return (Broadcast)_signature.getField<kSignatureMemBroadcastMask>(); } //! Sets the memory operand's broadcast. - inline void setBroadcast(uint32_t bcst) noexcept { _setSignaturePart<kSignatureMemBroadcastMask>(bcst); } + inline void setBroadcast(Broadcast b) noexcept { _signature.setField<kSignatureMemBroadcastMask>(uint32_t(b)); } //! Resets the memory operand's broadcast to none. - inline void resetBroadcast() noexcept { _setSignaturePart<kSignatureMemBroadcastMask>(0); } - - // -------------------------------------------------------------------------- - // [Operator Overload] - // -------------------------------------------------------------------------- - - inline Mem& operator=(const Mem& other) noexcept = default; + inline void resetBroadcast() noexcept { _signature.setField<kSignatureMemBroadcastMask>(0); } + + //! Returns a new `Mem` without a broadcast (the possible broadcast is cleared). + inline constexpr Mem _1to1() const noexcept { return cloneBroadcasted(Broadcast::kNone); } + //! Returns a new `Mem` with {1to2} broadcast (AVX-512). + inline constexpr Mem _1to2() const noexcept { return cloneBroadcasted(Broadcast::k1To2); } + //! Returns a new `Mem` with {1to4} broadcast (AVX-512). + inline constexpr Mem _1to4() const noexcept { return cloneBroadcasted(Broadcast::k1To4); } + //! Returns a new `Mem` with {1to8} broadcast (AVX-512). + inline constexpr Mem _1to8() const noexcept { return cloneBroadcasted(Broadcast::k1To8); } + //! Returns a new `Mem` with {1to16} broadcast (AVX-512). + inline constexpr Mem _1to16() const noexcept { return cloneBroadcasted(Broadcast::k1To16); } + //! Returns a new `Mem` with {1to32} broadcast (AVX-512). + inline constexpr Mem _1to32() const noexcept { return cloneBroadcasted(Broadcast::k1To32); } + //! Returns a new `Mem` with {1to64} broadcast (AVX-512). + inline constexpr Mem _1to64() const noexcept { return cloneBroadcasted(Broadcast::k1To64); } + + //! \} }; //! Creates `[base.reg + offset]` memory operand. -static constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, offset, size); } //! Creates `[base.reg + (index << shift) + offset]` memory operand (scalar index). -static constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[base.reg + (index << shift) + offset]` memory operand (vector index). -static constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[base + offset]` memory operand. -static constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, offset, size); } //! Creates `[base + (index << shift) + offset]` memory operand. -static constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[base + (index << shift) + offset]` memory operand. -static constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, offset, size); } //! Creates `[rip + offset]` memory operand. -static constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept { return Mem(rip_, offset, size); } //! Creates `[base]` absolute memory operand. -static constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept { return Mem(base, size); } //! Creates `[base + (index.reg << shift)]` absolute memory operand. -static constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size); } //! Creates `[base + (index.reg << shift)]` absolute memory operand. -static constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { +static inline constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { return Mem(base, index, shift, size); } //! Creates `[base]` absolute memory operand (absolute). -static constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept { - return Mem(base, size, Mem::kSignatureMemAbs); +static inline constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept { + return Mem(base, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute). -static constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { - return Mem(base, index, shift, size, Mem::kSignatureMemAbs); +static inline constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { + return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute). -static constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { - return Mem(base, index, shift, size, Mem::kSignatureMemAbs); +static inline constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { + return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } //! Creates `[base]` relative memory operand (relative). -static constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept { - return Mem(base, size, Mem::kSignatureMemRel); +static inline constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept { + return Mem(base, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } //! Creates `[base + (index.reg << shift)]` relative memory operand (relative). -static constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { - return Mem(base, index, shift, size, Mem::kSignatureMemRel); +static inline constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept { + return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } //! Creates `[base + (index.reg << shift)]` relative memory operand (relative). -static constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { - return Mem(base, index, shift, size, Mem::kSignatureMemRel); +static inline constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept { + return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } +#define ASMJIT_MEM_PTR(FUNC, SIZE) \ + static constexpr Mem FUNC(const Gp& base, int32_t offset = 0) noexcept { \ + return Mem(base, offset, SIZE); \ + } \ + static constexpr Mem FUNC(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ + return Mem(base, index, shift, offset, SIZE); \ + } \ + static constexpr Mem FUNC(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ + return Mem(base, index, shift, offset, SIZE); \ + } \ + static constexpr Mem FUNC(const Label& base, int32_t offset = 0) noexcept { \ + return Mem(base, offset, SIZE); \ + } \ + static constexpr Mem FUNC(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \ + return Mem(base, index, shift, offset, SIZE); \ + } \ + static constexpr Mem FUNC(const Rip& rip_, int32_t offset = 0) noexcept { \ + return Mem(rip_, offset, SIZE); \ + } \ + static constexpr Mem FUNC(uint64_t base) noexcept { \ + return Mem(base, SIZE); \ + } \ + static constexpr Mem FUNC(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ + return Mem(base, index, shift, SIZE); \ + } \ + static constexpr Mem FUNC(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ + return Mem(base, index, shift, SIZE); \ + } \ + \ + static constexpr Mem FUNC##_abs(uint64_t base) noexcept { \ + return Mem(base, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \ + } \ + static constexpr Mem FUNC##_abs(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ + return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \ + } \ + static constexpr Mem FUNC##_abs(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ + return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \ + } \ + \ + static constexpr Mem FUNC##_rel(uint64_t base) noexcept { \ + return Mem(base, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \ + } \ + static constexpr Mem FUNC##_rel(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \ + return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \ + } \ + static constexpr Mem FUNC##_rel(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \ + return Mem(base, index, shift, SIZE, \ + OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \ + } + // Definition of memory operand constructors that use platform independent naming. ASMJIT_MEM_PTR(ptr_8, 1) ASMJIT_MEM_PTR(ptr_16, 2) @@ -1110,27 +1063,23 @@ ASMJIT_MEM_PTR(xmmword_ptr, 16) ASMJIT_MEM_PTR(ymmword_ptr, 32) ASMJIT_MEM_PTR(zmmword_ptr, 64) +#undef ASMJIT_MEM_PTR + //! \} ASMJIT_END_SUB_NAMESPACE -// ============================================================================ -// [asmjit::Type::IdOfT<x86::Reg>] -// ============================================================================ - //! \cond INTERNAL ASMJIT_BEGIN_NAMESPACE -ASMJIT_DEFINE_TYPE_ID(x86::Gpb, kIdI8); -ASMJIT_DEFINE_TYPE_ID(x86::Gpw, kIdI16); -ASMJIT_DEFINE_TYPE_ID(x86::Gpd, kIdI32); -ASMJIT_DEFINE_TYPE_ID(x86::Gpq, kIdI64); -ASMJIT_DEFINE_TYPE_ID(x86::Mm , kIdMmx64); -ASMJIT_DEFINE_TYPE_ID(x86::Xmm, kIdI32x4); -ASMJIT_DEFINE_TYPE_ID(x86::Ymm, kIdI32x8); -ASMJIT_DEFINE_TYPE_ID(x86::Zmm, kIdI32x16); +ASMJIT_DEFINE_TYPE_ID(x86::Gpb, TypeId::kInt8); +ASMJIT_DEFINE_TYPE_ID(x86::Gpw, TypeId::kInt16); +ASMJIT_DEFINE_TYPE_ID(x86::Gpd, TypeId::kInt32); +ASMJIT_DEFINE_TYPE_ID(x86::Gpq, TypeId::kInt64); +ASMJIT_DEFINE_TYPE_ID(x86::Mm , TypeId::kMmx64); +ASMJIT_DEFINE_TYPE_ID(x86::Xmm, TypeId::kInt32x4); +ASMJIT_DEFINE_TYPE_ID(x86::Ymm, TypeId::kInt32x8); +ASMJIT_DEFINE_TYPE_ID(x86::Zmm, TypeId::kInt32x16); ASMJIT_END_NAMESPACE //! \endcond -#undef ASMJIT_MEM_PTR - #endif // ASMJIT_X86_X86OPERAND_H_INCLUDED diff --git a/src/asmjit/x86/x86rapass.cpp b/src/asmjit/x86/x86rapass.cpp index 8fa1c6c..3a63c08 100644 --- a/src/asmjit/x86/x86rapass.cpp +++ b/src/asmjit/x86/x86rapass.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_COMPILER) @@ -36,13 +18,12 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::X86RAPass - Helpers] -// ============================================================================ +// x86::X86RAPass - Utilities +// ========================== -static ASMJIT_INLINE uint64_t raImmMaskFromSize(uint32_t size) noexcept { +static ASMJIT_FORCE_INLINE uint64_t raImmMaskFromSize(uint32_t size) noexcept { ASMJIT_ASSERT(size > 0 && size < 256); - static const uint64_t masks[] = { + static constexpr uint64_t masks[] = { 0x00000000000000FFu, // 1 0x000000000000FFFFu, // 2 0x00000000FFFFFFFFu, // 4 @@ -56,42 +37,49 @@ static ASMJIT_INLINE uint64_t raImmMaskFromSize(uint32_t size) noexcept { return masks[Support::ctz(size)]; } -static ASMJIT_INLINE uint32_t raUseOutFlagsFromRWFlags(uint32_t rwFlags) noexcept { - static const uint32_t map[] = { - 0, - RATiedReg::kRead | RATiedReg::kUse, // kRead - RATiedReg::kWrite | RATiedReg::kOut, // kWrite - RATiedReg::kRW | RATiedReg::kUse, // kRW - 0, - RATiedReg::kRead | RATiedReg::kUse | RATiedReg::kUseRM, // kRead | kRegMem - RATiedReg::kWrite | RATiedReg::kOut | RATiedReg::kOutRM, // kWrite | kRegMem - RATiedReg::kRW | RATiedReg::kUse | RATiedReg::kUseRM // kRW | kRegMem +static const RegMask raConsecutiveLeadCountToRegMaskFilter[5] = { + 0xFFFFFFFFu, // [0] No consecutive. + 0x00000000u, // [1] Invalid, never used. + 0x55555555u, // [2] Even registers. + 0x00000000u, // [3] Invalid, never used. + 0x11111111u // [4] Every fourth register. +}; + +static ASMJIT_FORCE_INLINE RATiedFlags raUseOutFlagsFromRWFlags(OpRWFlags rwFlags) noexcept { + static constexpr RATiedFlags map[] = { + RATiedFlags::kNone, + RATiedFlags::kRead | RATiedFlags::kUse, // kRead + RATiedFlags::kWrite | RATiedFlags::kOut, // kWrite + RATiedFlags::kRW | RATiedFlags::kUse, // kRW + RATiedFlags::kNone, + RATiedFlags::kRead | RATiedFlags::kUse | RATiedFlags::kUseRM, // kRead | kRegMem + RATiedFlags::kWrite | RATiedFlags::kOut | RATiedFlags::kOutRM, // kWrite | kRegMem + RATiedFlags::kRW | RATiedFlags::kUse | RATiedFlags::kUseRM // kRW | kRegMem }; - return map[rwFlags & (OpRWInfo::kRW | OpRWInfo::kRegMem)]; + return map[uint32_t(rwFlags & (OpRWFlags::kRW | OpRWFlags::kRegMem))]; } -static ASMJIT_INLINE uint32_t raRegRwFlags(uint32_t flags) noexcept { - return raUseOutFlagsFromRWFlags(flags); +static ASMJIT_FORCE_INLINE RATiedFlags raRegRwFlags(OpRWFlags flags) noexcept { + return (RATiedFlags)raUseOutFlagsFromRWFlags(flags); } -static ASMJIT_INLINE uint32_t raMemBaseRwFlags(uint32_t flags) noexcept { - constexpr uint32_t shift = Support::constCtz(OpRWInfo::kMemBaseRW); - return raUseOutFlagsFromRWFlags((flags >> shift) & OpRWInfo::kRW); +static ASMJIT_FORCE_INLINE RATiedFlags raMemBaseRwFlags(OpRWFlags flags) noexcept { + constexpr uint32_t kShift = Support::ConstCTZ<uint32_t(OpRWFlags::kMemBaseRW)>::value; + return (RATiedFlags)raUseOutFlagsFromRWFlags(OpRWFlags(uint32_t(flags) >> kShift) & OpRWFlags::kRW); } -static ASMJIT_INLINE uint32_t raMemIndexRwFlags(uint32_t flags) noexcept { - constexpr uint32_t shift = Support::constCtz(OpRWInfo::kMemIndexRW); - return raUseOutFlagsFromRWFlags((flags >> shift) & OpRWInfo::kRW); +static ASMJIT_FORCE_INLINE RATiedFlags raMemIndexRwFlags(OpRWFlags flags) noexcept { + constexpr uint32_t kShift = Support::ConstCTZ<uint32_t(OpRWFlags::kMemIndexRW)>::value; + return (RATiedFlags)raUseOutFlagsFromRWFlags(OpRWFlags(uint32_t(flags) >> kShift) & OpRWFlags::kRW); } -// ============================================================================ -// [asmjit::x86::RACFGBuilder] -// ============================================================================ +// x86::RACFGBuilder +// ================= class RACFGBuilder : public RACFGBuilderT<RACFGBuilder> { public: - uint32_t _arch; + Arch _arch; bool _is64Bit; bool _avxEnabled; @@ -108,7 +96,7 @@ public: return _avxEnabled ? avxInst : sseInst; } - Error onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& ib) noexcept; + Error onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& ib) noexcept; Error onBeforeInvoke(InvokeNode* invokeNode) noexcept; Error onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept; @@ -122,14 +110,13 @@ public: Error onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept; }; -// ============================================================================ -// [asmjit::x86::RACFGBuilder - OnInst] -// ============================================================================ +// x86::RACFGBuilder - OnInst +// ========================== -Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& ib) noexcept { +Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& ib) noexcept { InstRWInfo rwInfo; - uint32_t instId = inst->id(); + InstId instId = inst->id(); if (Inst::isDefinedId(instId)) { uint32_t opCount = inst->opCount(); const Operand* opArray = inst->operands(); @@ -140,15 +127,18 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& uint32_t singleRegOps = 0; if (opCount) { - // The mask is for all registers, but we are mostly interested in AVX-512 - // registers at the moment. The mask will be combined with all available - // registers of the Compiler at the end so we it never use more registers + // The mask is for all registers, but we are mostly interested in AVX-512 registers at the moment. The mask + // will be combined with all available registers of the Compiler at the end so we it never use more registers // than available. - uint32_t instructionAllowedRegs = 0xFFFFFFFFu; + RegMask instructionAllowedRegs = 0xFFFFFFFFu; + + uint32_t consecutiveOffset = 0; + uint32_t consecutiveLeadId = Globals::kInvalidId; + uint32_t consecutiveParent = Globals::kInvalidId; if (instInfo.isEvex()) { - // EVEX instruction and VEX instructions that can be encoded with EVEX - // have the possibility to use 32 SIMD registers (XMM/YMM/ZMM). + // EVEX instruction and VEX instructions that can be encoded with EVEX have the possibility to use 32 SIMD + // registers (XMM/YMM/ZMM). if (instInfo.isVex() && !instInfo.isEvexCompatible()) { if (instInfo.isEvexKRegOnly()) { // EVEX encodable only if the first operand is K register (compare instructions). @@ -166,7 +156,7 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& } } else if (instInfo.isEvexTransformable()) { - ib.addAggregatedFlags(RAInst::kFlagIsTransformable); + ib.addAggregatedFlags(RATiedFlags::kInst_IsTransformable); } else { // Not EVEX, restrict everything to [0-15] registers. @@ -182,26 +172,24 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& // ---------------- const Reg& reg = op.as<Reg>(); - uint32_t flags = raRegRwFlags(opRwInfo.opFlags()); - uint32_t allowedRegs = instructionAllowedRegs; + RATiedFlags flags = raRegRwFlags(opRwInfo.opFlags()); + RegMask allowedRegs = instructionAllowedRegs; - // X86-specific constraints related to LO|HI general purpose registers. - // This is only required when the register is part of the encoding. If - // the register is fixed we won't restrict anything as it doesn't restrict - // encoding of other registers. - if (reg.isGpb() && !(opRwInfo.opFlags() & OpRWInfo::kRegPhysId)) { - flags |= RATiedReg::kX86Gpb; + // X86-specific constraints related to LO|HI general purpose registers. This is only required when the + // register is part of the encoding. If the register is fixed we won't restrict anything as it doesn't + // restrict encoding of other registers. + if (reg.isGpb() && !opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) { + flags |= RATiedFlags::kX86_Gpb; if (!_is64Bit) { - // Restrict to first four - AL|AH|BL|BH|CL|CH|DL|DH. In 32-bit mode - // it's not possible to access SIL|DIL, etc, so this is just enough. + // Restrict to first four - AL|AH|BL|BH|CL|CH|DL|DH. In 32-bit mode it's not possible to access + // SIL|DIL, etc, so this is just enough. allowedRegs = 0x0Fu; } else { - // If we encountered GPB-HI register the situation is much more - // complicated than in 32-bit mode. We need to patch all registers - // to not use ID higher than 7 and all GPB-LO registers to not use - // index higher than 3. Instead of doing the patching here we just - // set a flag and will do it later, to not complicate this loop. + // If we encountered GPB-HI register the situation is much more complicated than in 32-bit mode. + // We need to patch all registers to not use ID higher than 7 and all GPB-LO registers to not use + // index higher than 3. Instead of doing the patching here we just set a flag and will do it later, + // to not complicate this loop. if (reg.isGpbHi()) { hasGpbHiConstraint = true; allowedRegs = 0x0Fu; @@ -214,25 +202,24 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& RAWorkReg* workReg; ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); - // Use RW instead of Write in case that not the whole register is - // overwritten. This is important for liveness as we cannot kill a - // register that will be used. For example `mov al, 0xFF` is not a - // write-only operation if user allocated the whole `rax` register. - if ((flags & RATiedReg::kRW) == RATiedReg::kWrite) { + // Use RW instead of Write in case that not the whole register is overwritten. This is important + // for liveness as we cannot kill a register that will be used. For example `mov al, 0xFF` is not + // a write-only operation if user allocated the whole `rax` register. + if ((flags & RATiedFlags::kRW) == RATiedFlags::kWrite) { if (workReg->regByteMask() & ~(opRwInfo.writeByteMask() | opRwInfo.extendByteMask())) { // Not write-only operation. - flags = (flags & ~RATiedReg::kOut) | (RATiedReg::kRead | RATiedReg::kUse); + flags = (flags & ~RATiedFlags::kOut) | (RATiedFlags::kRead | RATiedFlags::kUse); } } - // Do not use RegMem flag if changing Reg to Mem requires additional - // CPU feature that may not be enabled. - if (rwInfo.rmFeature() && (flags & (RATiedReg::kUseRM | RATiedReg::kOutRM))) { - flags &= ~(RATiedReg::kUseRM | RATiedReg::kOutRM); + // Do not use RegMem flag if changing Reg to Mem requires additional CPU feature that may not be enabled. + if (rwInfo.rmFeature() && Support::test(flags, RATiedFlags::kUseRM | RATiedFlags::kOutRM)) { + flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM); } - uint32_t group = workReg->group(); - uint32_t allocable = _pass->_availableRegs[group] & allowedRegs; + RegGroup group = workReg->group(); + RegMask useRegs = _pass->_availableRegs[group] & allowedRegs; + RegMask outRegs = useRegs; uint32_t useId = BaseReg::kIdBad; uint32_t outId = BaseReg::kIdBad; @@ -240,31 +227,75 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& uint32_t useRewriteMask = 0; uint32_t outRewriteMask = 0; - if (flags & RATiedReg::kUse) { + if (opRwInfo.consecutiveLeadCount()) { + // There must be a single consecutive register lead, otherwise the RW data is invalid. + if (consecutiveLeadId != Globals::kInvalidId) + return DebugUtils::errored(kErrorInvalidState); + + // A consecutive lead register cannot be used as a consecutive +1/+2/+3 register, the registers must be distinct. + if (RATiedReg::consecutiveDataFromFlags(flags) != 0) + return DebugUtils::errored(kErrorNotConsecutiveRegs); + + flags |= RATiedFlags::kLeadConsecutive | RATiedReg::consecutiveDataToFlags(opRwInfo.consecutiveLeadCount() - 1); + consecutiveLeadId = workReg->workId(); + + RegMask filter = raConsecutiveLeadCountToRegMaskFilter[opRwInfo.consecutiveLeadCount()]; + if (Support::test(flags, RATiedFlags::kUse)) { + flags |= RATiedFlags::kUseConsecutive; + useRegs &= filter; + } + else { + flags |= RATiedFlags::kOutConsecutive; + outRegs &= filter; + } + } + + if (Support::test(flags, RATiedFlags::kUse)) { useRewriteMask = Support::bitMask(inst->getRewriteIndex(®._baseId)); - if (opRwInfo.opFlags() & OpRWInfo::kRegPhysId) { + if (opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) { useId = opRwInfo.physId(); - flags |= RATiedReg::kUseFixed; + flags |= RATiedFlags::kUseFixed; + } + else if (opRwInfo.hasOpFlag(OpRWFlags::kConsecutive)) { + if (consecutiveLeadId == Globals::kInvalidId) + return DebugUtils::errored(kErrorInvalidState); + + if (consecutiveLeadId == workReg->workId()) + return DebugUtils::errored(kErrorOverlappedRegs); + + flags |= RATiedFlags::kUseConsecutive | RATiedReg::consecutiveDataToFlags(++consecutiveOffset); } } else { outRewriteMask = Support::bitMask(inst->getRewriteIndex(®._baseId)); - if (opRwInfo.opFlags() & OpRWInfo::kRegPhysId) { + if (opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) { outId = opRwInfo.physId(); - flags |= RATiedReg::kOutFixed; + flags |= RATiedFlags::kOutFixed; + } + else if (opRwInfo.hasOpFlag(OpRWFlags::kConsecutive)) { + if (consecutiveLeadId == Globals::kInvalidId) + return DebugUtils::errored(kErrorInvalidState); + + if (consecutiveLeadId == workReg->workId()) + return DebugUtils::errored(kErrorOverlappedRegs); + + flags |= RATiedFlags::kOutConsecutive | RATiedReg::consecutiveDataToFlags(++consecutiveOffset); } } - ASMJIT_PROPAGATE(ib.add(workReg, flags, allocable, useId, useRewriteMask, outId, outRewriteMask, opRwInfo.rmSize())); + ASMJIT_PROPAGATE(ib.add(workReg, flags, useRegs, useId, useRewriteMask, outRegs, outId, outRewriteMask, opRwInfo.rmSize(), consecutiveParent)); if (singleRegOps == i) singleRegOps++; + + if (Support::test(flags, RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive)) + consecutiveParent = workReg->workId(); } } else if (op.isMem()) { // Memory Operand // -------------- const Mem& mem = op.as<Mem>(); - ib.addForbiddenFlags(RATiedReg::kUseRM | RATiedReg::kOutRM); + ib.addForbiddenFlags(RATiedFlags::kUseRM | RATiedFlags::kOutRM); if (mem.isRegHome()) { RAWorkReg* workReg; @@ -277,9 +308,9 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& RAWorkReg* workReg; ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); - uint32_t flags = raMemBaseRwFlags(opRwInfo.opFlags()); - uint32_t group = workReg->group(); - uint32_t allocable = _pass->_availableRegs[group]; + RATiedFlags flags = raMemBaseRwFlags(opRwInfo.opFlags()); + RegGroup group = workReg->group(); + RegMask inOutRegs = _pass->_availableRegs[group]; uint32_t useId = BaseReg::kIdBad; uint32_t outId = BaseReg::kIdBad; @@ -287,22 +318,22 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& uint32_t useRewriteMask = 0; uint32_t outRewriteMask = 0; - if (flags & RATiedReg::kUse) { + if (Support::test(flags, RATiedFlags::kUse)) { useRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._baseId)); - if (opRwInfo.opFlags() & OpRWInfo::kMemPhysId) { + if (opRwInfo.hasOpFlag(OpRWFlags::kMemPhysId)) { useId = opRwInfo.physId(); - flags |= RATiedReg::kUseFixed; + flags |= RATiedFlags::kUseFixed; } } else { outRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._baseId)); - if (opRwInfo.opFlags() & OpRWInfo::kMemPhysId) { + if (opRwInfo.hasOpFlag(OpRWFlags::kMemPhysId)) { outId = opRwInfo.physId(); - flags |= RATiedReg::kOutFixed; + flags |= RATiedFlags::kOutFixed; } } - ASMJIT_PROPAGATE(ib.add(workReg, flags, allocable, useId, useRewriteMask, outId, outRewriteMask)); + ASMJIT_PROPAGATE(ib.add(workReg, flags, inOutRegs, useId, useRewriteMask, inOutRegs, outId, outRewriteMask)); } } @@ -312,9 +343,9 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& RAWorkReg* workReg; ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); - uint32_t flags = raMemIndexRwFlags(opRwInfo.opFlags()); - uint32_t group = workReg->group(); - uint32_t allocable = _pass->_availableRegs[group] & instructionAllowedRegs; + RATiedFlags flags = raMemIndexRwFlags(opRwInfo.opFlags()); + RegGroup group = workReg->group(); + RegMask inOutRegs = _pass->_availableRegs[group] & instructionAllowedRegs; // Index registers have never fixed id on X86/x64. const uint32_t useId = BaseReg::kIdBad; @@ -323,12 +354,12 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& uint32_t useRewriteMask = 0; uint32_t outRewriteMask = 0; - if (flags & RATiedReg::kUse) + if (Support::test(flags, RATiedFlags::kUse)) useRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._data[Operand::kDataMemIndexId])); else outRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._data[Operand::kDataMemIndexId])); - ASMJIT_PROPAGATE(ib.add(workReg, RATiedReg::kUse | RATiedReg::kRead, allocable, useId, useRewriteMask, outId, outRewriteMask)); + ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, inOutRegs, useId, useRewriteMask, inOutRegs, outId, outRewriteMask)); } } } @@ -342,23 +373,23 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& RAWorkReg* workReg; ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); + RegMask inOutRegs = _pass->_availableRegs[group]; uint32_t rewriteMask = Support::bitMask(inst->getRewriteIndex(&inst->extraReg()._id)); - if (group == Gp::kGroupKReg) { + if (group == RegGroup::kX86_K) { // AVX-512 mask selector {k} register - read-only, allocable to any register except {k0}. - uint32_t allocableRegs = _pass->_availableRegs[group]; - ASMJIT_PROPAGATE(ib.add(workReg, RATiedReg::kUse | RATiedReg::kRead, allocableRegs, BaseReg::kIdBad, rewriteMask, BaseReg::kIdBad, 0)); + ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, inOutRegs, BaseReg::kIdBad, rewriteMask, inOutRegs, BaseReg::kIdBad, 0)); singleRegOps = 0; } else { // REP {cx|ecx|rcx} register - read & write, allocable to {cx|ecx|rcx} only. - ASMJIT_PROPAGATE(ib.add(workReg, RATiedReg::kUse | RATiedReg::kRW, 0, Gp::kIdCx, rewriteMask, Gp::kIdBad, 0)); + ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRW, inOutRegs, Gp::kIdCx, rewriteMask, inOutRegs, Gp::kIdBad, 0)); } } else { - uint32_t group = inst->extraReg().group(); - if (group == Gp::kGroupKReg && inst->extraReg().id() != 0) + RegGroup group = inst->extraReg().group(); + if (group == RegGroup::kX86_K && inst->extraReg().id() != 0) singleRegOps = 0; } } @@ -366,16 +397,18 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& // Handle X86 constraints. if (hasGpbHiConstraint) { for (RATiedReg& tiedReg : ib) { - tiedReg._allocableRegs &= tiedReg.hasFlag(RATiedReg::kX86Gpb) ? 0x0Fu : 0xFFu; + RegMask filter = tiedReg.hasFlag(RATiedFlags::kX86_Gpb) ? 0x0Fu : 0xFFu; + tiedReg._useRegMask &= filter; + tiedReg._outRegMask &= filter; } } if (ib.tiedRegCount() == 1) { // Handle special cases of some instructions where all operands share the same // register. In such case the single operand becomes read-only or write-only. - uint32_t singleRegCase = InstDB::kSingleRegNone; + InstSameRegHint sameRegHint = InstSameRegHint::kNone; if (singleRegOps == opCount) { - singleRegCase = instInfo.singleRegCase(); + sameRegHint = instInfo.sameRegHint(); } else if (opCount == 2 && inst->op(1).isImm()) { // Handle some tricks used by X86 asm. @@ -383,14 +416,14 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& const Imm& imm = inst->op(1).as<Imm>(); const RAWorkReg* workReg = _pass->workRegById(ib[0]->workId()); - uint32_t workRegSize = workReg->info().size(); + uint32_t workRegSize = workReg->signature().size(); switch (inst->id()) { case Inst::kIdOr: { // Sets the value of the destination register to -1, previous content unused. if (reg.size() >= 4 || reg.size() >= workRegSize) { if (imm.value() == -1 || imm.valueAs<uint64_t>() == raImmMaskFromSize(reg.size())) - singleRegCase = InstDB::kSingleRegWO; + sameRegHint = InstSameRegHint::kWO; } ASMJIT_FALLTHROUGH; } @@ -407,41 +440,40 @@ Error RACFGBuilder::onInst(InstNode* inst, uint32_t& controlType, RAInstBuilder& // Updates [E|R]FLAGS without changing the content. if (reg.size() != 4 || reg.size() >= workRegSize) { if (imm.value() == 0) - singleRegCase = InstDB::kSingleRegRO; + sameRegHint = InstSameRegHint::kRO; } break; } } } - switch (singleRegCase) { - case InstDB::kSingleRegNone: + switch (sameRegHint) { + case InstSameRegHint::kNone: break; - case InstDB::kSingleRegRO: + case InstSameRegHint::kRO: ib[0]->makeReadOnly(); break; - case InstDB::kSingleRegWO: + case InstSameRegHint::kWO: ib[0]->makeWriteOnly(); break; } } - controlType = instInfo.controlType(); + cf = instInfo.controlFlow(); } return kErrorOk; } -// ============================================================================ -// [asmjit::x86::RACFGBuilder - OnInvoke] -// ============================================================================ +// x86::RACFGBuilder - OnInvoke +// ============================ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { const FuncDetail& fd = invokeNode->detail(); uint32_t argCount = invokeNode->argCount(); cc()->_setCursor(invokeNode->prev()); - uint32_t nativeRegType = cc()->_gpRegInfo.type(); + RegType nativeRegType = cc()->_gpSignature.regType(); for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { const FuncValuePack& argPack = fd.argPack(argIndex); @@ -461,8 +493,8 @@ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); if (arg.isReg()) { - uint32_t regGroup = workReg->group(); - uint32_t argGroup = Reg::groupOf(arg.regType()); + RegGroup regGroup = workReg->group(); + RegGroup argGroup = Reg::groupOf(arg.regType()); if (arg.isIndirect()) { if (reg.isGp()) { @@ -516,7 +548,7 @@ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { } cc()->_setCursor(invokeNode); - if (fd.hasFlag(CallConv::kFlagCalleePopsStack) && fd.argStackSize() != 0) + if (fd.hasFlag(CallConvFlags::kCalleePopsStack) && fd.argStackSize() != 0) ASMJIT_PROPAGATE(cc()->sub(cc()->zsp(), fd.argStackSize())); if (fd.hasRet()) { @@ -532,26 +564,26 @@ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); if (ret.isReg()) { - if (ret.regType() == Reg::kTypeSt) { - if (workReg->group() != Reg::kGroupVec) + if (ret.regType() == RegType::kX86_St) { + if (workReg->group() != RegGroup::kVec) return DebugUtils::errored(kErrorInvalidAssignment); - Reg dst = Reg::fromSignatureAndId(workReg->signature(), workReg->virtId()); + Reg dst(workReg->signature(), workReg->virtId()); Mem mem; - uint32_t typeId = Type::baseOf(workReg->typeId()); + TypeId typeId = TypeUtils::scalarOf(workReg->typeId()); if (ret.hasTypeId()) typeId = ret.typeId(); switch (typeId) { - case Type::kIdF32: + case TypeId::kFloat32: ASMJIT_PROPAGATE(_pass->useTemporaryMem(mem, 4, 4)); mem.setSize(4); ASMJIT_PROPAGATE(cc()->fstp(mem)); ASMJIT_PROPAGATE(cc()->emit(choose(Inst::kIdMovss, Inst::kIdVmovss), dst.as<Xmm>(), mem)); break; - case Type::kIdF64: + case TypeId::kFloat64: ASMJIT_PROPAGATE(_pass->useTemporaryMem(mem, 8, 4)); mem.setSize(8); ASMJIT_PROPAGATE(cc()->fstp(mem)); @@ -563,8 +595,8 @@ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { } } else { - uint32_t regGroup = workReg->group(); - uint32_t retGroup = Reg::groupOf(ret.regType()); + RegGroup regGroup = workReg->group(); + RegGroup retGroup = Reg::groupOf(ret.regType()); if (regGroup != retGroup) { // TODO: Conversion is not supported. @@ -577,8 +609,8 @@ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { } // This block has function call(s). - _curBlock->addFlags(RABlock::kFlagHasFuncCalls); - _pass->func()->frame().addAttributes(FuncFrame::kAttrHasFuncCalls); + _curBlock->addFlags(RABlockFlags::kHasFuncCalls); + _pass->func()->frame().addAttributes(FuncAttributes::kHasFuncCalls); _pass->func()->frame().updateCallStackSize(fd.argStackSize()); return kErrorOk; @@ -606,14 +638,14 @@ Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); if (arg.isIndirect()) { - uint32_t regGroup = workReg->group(); - if (regGroup != BaseReg::kGroupGp) + RegGroup regGroup = workReg->group(); + if (regGroup != RegGroup::kGp) return DebugUtils::errored(kErrorInvalidState); ASMJIT_PROPAGATE(ib.addCallArg(workReg, arg.regId())); } else if (arg.isReg()) { - uint32_t regGroup = workReg->group(); - uint32_t argGroup = Reg::groupOf(arg.regType()); + RegGroup regGroup = workReg->group(); + RegGroup argGroup = Reg::groupOf(arg.regType()); if (regGroup == argGroup) { ASMJIT_PROPAGATE(ib.addCallArg(workReg, arg.regId())); @@ -630,7 +662,7 @@ Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept // Not handled here... const Operand& op = invokeNode->ret(retIndex); - if (ret.regType() == Reg::kTypeSt) + if (ret.regType() == RegType::kX86_St) continue; if (op.isReg()) { @@ -639,8 +671,8 @@ Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); if (ret.isReg()) { - uint32_t regGroup = workReg->group(); - uint32_t retGroup = Reg::groupOf(ret.regType()); + RegGroup regGroup = workReg->group(); + RegGroup retGroup = Reg::groupOf(ret.regType()); if (regGroup == retGroup) { ASMJIT_PROPAGATE(ib.addCallRet(workReg, ret.regId())); @@ -653,32 +685,25 @@ Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept } // Setup clobbered registers. - ib._clobbered[0] = Support::lsbMask<uint32_t>(_pass->_physRegCount[0]) & ~fd.preservedRegs(0); - ib._clobbered[1] = Support::lsbMask<uint32_t>(_pass->_physRegCount[1]) & ~fd.preservedRegs(1); - ib._clobbered[2] = Support::lsbMask<uint32_t>(_pass->_physRegCount[2]) & ~fd.preservedRegs(2); - ib._clobbered[3] = Support::lsbMask<uint32_t>(_pass->_physRegCount[3]) & ~fd.preservedRegs(3); + for (RegGroup group : RegGroupVirtValues{}) + ib._clobbered[group] = Support::lsbMask<RegMask>(_pass->_physRegCount[group]) & ~fd.preservedRegs(group); return kErrorOk; } -// ============================================================================ -// [asmjit::x86::RACFGBuilder - MoveVecToPtr] -// ============================================================================ - -static uint32_t x86VecRegSignatureBySize(uint32_t size) noexcept { - if (size >= 64) - return Zmm::kSignature; - else if (size >= 32) - return Ymm::kSignature; - else - return Xmm::kSignature; +// x86::RACFGBuilder - MoveVecToPtr +// ================================ + +static inline OperandSignature x86VecRegSignatureBySize(uint32_t size) noexcept { + return OperandSignature(size >= 64 ? uint32_t(Zmm::kSignature) : + size >= 32 ? uint32_t(Ymm::kSignature) : uint32_t(Xmm::kSignature)); } Error RACFGBuilder::moveVecToPtr(InvokeNode* invokeNode, const FuncValue& arg, const Vec& src, BaseReg* out) noexcept { DebugUtils::unused(invokeNode); ASMJIT_ASSERT(arg.isReg()); - uint32_t argSize = Type::sizeOf(arg.typeId()); + uint32_t argSize = TypeUtils::sizeOf(arg.typeId()); if (argSize == 0) return DebugUtils::errored(kErrorInvalidState); @@ -689,14 +714,14 @@ Error RACFGBuilder::moveVecToPtr(InvokeNode* invokeNode, const FuncValue& arg, c _funcNode->frame().updateCallStackAlignment(argSize); invokeNode->detail()._argStackSize = argStackOffset + argSize; - Vec vecReg = Vec::fromSignatureAndId(x86VecRegSignatureBySize(argSize), src.id()); + Vec vecReg(x86VecRegSignatureBySize(argSize), src.id()); Mem vecPtr = ptr(_pass->_sp.as<Gp>(), int32_t(argStackOffset)); uint32_t vMovInstId = choose(Inst::kIdMovaps, Inst::kIdVmovaps); if (argSize > 16) vMovInstId = Inst::kIdVmovaps; - ASMJIT_PROPAGATE(cc()->_newReg(out, cc()->_gpRegInfo.type(), nullptr)); + ASMJIT_PROPAGATE(cc()->_newReg(out, ArchTraits::byArch(cc()->arch()).regTypeToTypeId(cc()->_gpSignature.regType()), nullptr)); VirtReg* vReg = cc()->virtRegById(out->id()); vReg->setWeight(BaseRAPass::kCallArgWeight); @@ -712,38 +737,37 @@ Error RACFGBuilder::moveVecToPtr(InvokeNode* invokeNode, const FuncValue& arg, c return kErrorOk; } -// ============================================================================ -// [asmjit::x86::RACFGBuilder - MoveImmToRegArg] -// ============================================================================ +// x86::RACFGBuilder - MoveImmToRegArg +// =================================== Error RACFGBuilder::moveImmToRegArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_, BaseReg* out) noexcept { DebugUtils::unused(invokeNode); ASMJIT_ASSERT(arg.isReg()); Imm imm(imm_); - uint32_t rTypeId = Type::kIdU32; + TypeId rTypeId = TypeId::kUInt32; switch (arg.typeId()) { - case Type::kIdI8: imm.signExtend8Bits(); goto MovU32; - case Type::kIdU8: imm.zeroExtend8Bits(); goto MovU32; - case Type::kIdI16: imm.signExtend16Bits(); goto MovU32; - case Type::kIdU16: imm.zeroExtend16Bits(); goto MovU32; + case TypeId::kInt8: imm.signExtend8Bits(); goto MovU32; + case TypeId::kUInt8: imm.zeroExtend8Bits(); goto MovU32; + case TypeId::kInt16: imm.signExtend16Bits(); goto MovU32; + case TypeId::kUInt16: imm.zeroExtend16Bits(); goto MovU32; - case Type::kIdI32: - case Type::kIdU32: + case TypeId::kInt32: + case TypeId::kUInt32: MovU32: imm.zeroExtend32Bits(); break; - case Type::kIdI64: - case Type::kIdU64: + case TypeId::kInt64: + case TypeId::kUInt64: // Moving to GPD automatically zero extends in 64-bit mode. if (imm.isUInt32()) { imm.zeroExtend32Bits(); break; } - rTypeId = Type::kIdU64; + rTypeId = TypeId::kUInt64; break; default: @@ -756,9 +780,8 @@ MovU32: return cc()->mov(out->as<x86::Gp>(), imm); } -// ============================================================================ -// [asmjit::x86::RACFGBuilder - MoveImmToStackArg] -// ============================================================================ +// x86::RACFGBuilder - MoveImmToStackArg +// ===================================== Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_) noexcept { DebugUtils::unused(invokeNode); @@ -771,30 +794,28 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a imm[0] = imm_; uint32_t nMovs = 0; - // One stack entry has the same size as the native register size. That means - // that if we want to move a 32-bit integer on the stack in 64-bit mode, we - // need to extend it to a 64-bit integer first. In 32-bit mode, pushing a - // 64-bit on stack is done in two steps by pushing low and high parts - // separately. + // One stack entry has the same size as the native register size. That means that if we want to move a 32-bit + // integer on the stack in 64-bit mode, we need to extend it to a 64-bit integer first. In 32-bit mode, pushing + // a 64-bit on stack is done in two steps by pushing low and high parts separately. switch (arg.typeId()) { - case Type::kIdI8: imm[0].signExtend8Bits(); goto MovU32; - case Type::kIdU8: imm[0].zeroExtend8Bits(); goto MovU32; - case Type::kIdI16: imm[0].signExtend16Bits(); goto MovU32; - case Type::kIdU16: imm[0].zeroExtend16Bits(); goto MovU32; - - case Type::kIdI32: - case Type::kIdU32: - case Type::kIdF32: + case TypeId::kInt8: imm[0].signExtend8Bits(); goto MovU32; + case TypeId::kUInt8: imm[0].zeroExtend8Bits(); goto MovU32; + case TypeId::kInt16: imm[0].signExtend16Bits(); goto MovU32; + case TypeId::kUInt16: imm[0].zeroExtend16Bits(); goto MovU32; + + case TypeId::kInt32: + case TypeId::kUInt32: + case TypeId::kFloat32: MovU32: imm[0].zeroExtend32Bits(); nMovs = 1; break; - case Type::kIdI64: - case Type::kIdU64: - case Type::kIdF64: - case Type::kIdMmx32: - case Type::kIdMmx64: + case TypeId::kInt64: + case TypeId::kUInt64: + case TypeId::kFloat64: + case TypeId::kMmx32: + case TypeId::kMmx64: if (_is64Bit && imm[0].isInt32()) { stackPtr.setSize(8); nMovs = 1; @@ -818,9 +839,8 @@ MovU32: return kErrorOk; } -// ============================================================================ -// [asmjit::x86::RACFGBuilder - MoveRegToStackArg] -// ============================================================================ +// x86::RACFGBuilder - MoveRegToStackArg +// ===================================== Error RACFGBuilder::moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const BaseReg& reg) noexcept { DebugUtils::unused(invokeNode); @@ -831,124 +851,124 @@ Error RACFGBuilder::moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& a VirtReg* vr = cc()->virtRegById(reg.id()); uint32_t registerSize = cc()->registerSize(); - uint32_t instId = 0; + InstId instId = 0; - uint32_t dstTypeId = arg.typeId(); - uint32_t srcTypeId = vr->typeId(); + TypeId dstTypeId = arg.typeId(); + TypeId srcTypeId = vr->typeId(); switch (dstTypeId) { - case Type::kIdI64: - case Type::kIdU64: + case TypeId::kInt64: + case TypeId::kUInt64: // Extend BYTE->QWORD (GP). - if (Type::isGp8(srcTypeId)) { - r1.setRegT<Reg::kTypeGpbLo>(reg.id()); + if (TypeUtils::isGp8(srcTypeId)) { + r1.setRegT<RegType::kX86_GpbLo>(reg.id()); - instId = (dstTypeId == Type::kIdI64 && srcTypeId == Type::kIdI8) ? Inst::kIdMovsx : Inst::kIdMovzx; + instId = (dstTypeId == TypeId::kInt64 && srcTypeId == TypeId::kInt8) ? Inst::kIdMovsx : Inst::kIdMovzx; goto ExtendMovGpXQ; } // Extend WORD->QWORD (GP). - if (Type::isGp16(srcTypeId)) { - r1.setRegT<Reg::kTypeGpw>(reg.id()); + if (TypeUtils::isGp16(srcTypeId)) { + r1.setRegT<RegType::kX86_Gpw>(reg.id()); - instId = (dstTypeId == Type::kIdI64 && srcTypeId == Type::kIdI16) ? Inst::kIdMovsx : Inst::kIdMovzx; + instId = (dstTypeId == TypeId::kInt64 && srcTypeId == TypeId::kInt16) ? Inst::kIdMovsx : Inst::kIdMovzx; goto ExtendMovGpXQ; } // Extend DWORD->QWORD (GP). - if (Type::isGp32(srcTypeId)) { - r1.setRegT<Reg::kTypeGpd>(reg.id()); + if (TypeUtils::isGp32(srcTypeId)) { + r1.setRegT<RegType::kX86_Gpd>(reg.id()); instId = Inst::kIdMovsxd; - if (dstTypeId == Type::kIdI64 && srcTypeId == Type::kIdI32) + if (dstTypeId == TypeId::kInt64 && srcTypeId == TypeId::kInt32) goto ExtendMovGpXQ; else goto ZeroExtendGpDQ; } // Move QWORD (GP). - if (Type::isGp64(srcTypeId)) goto MovGpQ; - if (Type::isMmx(srcTypeId)) goto MovMmQ; - if (Type::isVec(srcTypeId)) goto MovXmmQ; + if (TypeUtils::isGp64(srcTypeId)) goto MovGpQ; + if (TypeUtils::isMmx(srcTypeId)) goto MovMmQ; + if (TypeUtils::isVec(srcTypeId)) goto MovXmmQ; break; - case Type::kIdI32: - case Type::kIdU32: - case Type::kIdI16: - case Type::kIdU16: + case TypeId::kInt32: + case TypeId::kUInt32: + case TypeId::kInt16: + case TypeId::kUInt16: // DWORD <- WORD (Zero|Sign Extend). - if (Type::isGp16(srcTypeId)) { - bool isDstSigned = dstTypeId == Type::kIdI16 || dstTypeId == Type::kIdI32; - bool isSrcSigned = srcTypeId == Type::kIdI8 || srcTypeId == Type::kIdI16; + if (TypeUtils::isGp16(srcTypeId)) { + bool isDstSigned = dstTypeId == TypeId::kInt16 || dstTypeId == TypeId::kInt32; + bool isSrcSigned = srcTypeId == TypeId::kInt8 || srcTypeId == TypeId::kInt16; - r1.setRegT<Reg::kTypeGpw>(reg.id()); + r1.setRegT<RegType::kX86_Gpw>(reg.id()); instId = isDstSigned && isSrcSigned ? Inst::kIdMovsx : Inst::kIdMovzx; goto ExtendMovGpD; } // DWORD <- BYTE (Zero|Sign Extend). - if (Type::isGp8(srcTypeId)) { - bool isDstSigned = dstTypeId == Type::kIdI16 || dstTypeId == Type::kIdI32; - bool isSrcSigned = srcTypeId == Type::kIdI8 || srcTypeId == Type::kIdI16; + if (TypeUtils::isGp8(srcTypeId)) { + bool isDstSigned = dstTypeId == TypeId::kInt16 || dstTypeId == TypeId::kInt32; + bool isSrcSigned = srcTypeId == TypeId::kInt8 || srcTypeId == TypeId::kInt16; - r1.setRegT<Reg::kTypeGpbLo>(reg.id()); + r1.setRegT<RegType::kX86_GpbLo>(reg.id()); instId = isDstSigned && isSrcSigned ? Inst::kIdMovsx : Inst::kIdMovzx; goto ExtendMovGpD; } ASMJIT_FALLTHROUGH; - case Type::kIdI8: - case Type::kIdU8: - if (Type::isInt(srcTypeId)) goto MovGpD; - if (Type::isMmx(srcTypeId)) goto MovMmD; - if (Type::isVec(srcTypeId)) goto MovXmmD; + case TypeId::kInt8: + case TypeId::kUInt8: + if (TypeUtils::isInt(srcTypeId)) goto MovGpD; + if (TypeUtils::isMmx(srcTypeId)) goto MovMmD; + if (TypeUtils::isVec(srcTypeId)) goto MovXmmD; break; - case Type::kIdMmx32: - case Type::kIdMmx64: + case TypeId::kMmx32: + case TypeId::kMmx64: // Extend BYTE->QWORD (GP). - if (Type::isGp8(srcTypeId)) { - r1.setRegT<Reg::kTypeGpbLo>(reg.id()); + if (TypeUtils::isGp8(srcTypeId)) { + r1.setRegT<RegType::kX86_GpbLo>(reg.id()); instId = Inst::kIdMovzx; goto ExtendMovGpXQ; } // Extend WORD->QWORD (GP). - if (Type::isGp16(srcTypeId)) { - r1.setRegT<Reg::kTypeGpw>(reg.id()); + if (TypeUtils::isGp16(srcTypeId)) { + r1.setRegT<RegType::kX86_Gpw>(reg.id()); instId = Inst::kIdMovzx; goto ExtendMovGpXQ; } - if (Type::isGp32(srcTypeId)) goto ExtendMovGpDQ; - if (Type::isGp64(srcTypeId)) goto MovGpQ; - if (Type::isMmx(srcTypeId)) goto MovMmQ; - if (Type::isVec(srcTypeId)) goto MovXmmQ; + if (TypeUtils::isGp32(srcTypeId)) goto ExtendMovGpDQ; + if (TypeUtils::isGp64(srcTypeId)) goto MovGpQ; + if (TypeUtils::isMmx(srcTypeId)) goto MovMmQ; + if (TypeUtils::isVec(srcTypeId)) goto MovXmmQ; break; - case Type::kIdF32: - case Type::kIdF32x1: - if (Type::isVec(srcTypeId)) goto MovXmmD; + case TypeId::kFloat32: + case TypeId::kFloat32x1: + if (TypeUtils::isVec(srcTypeId)) goto MovXmmD; break; - case Type::kIdF64: - case Type::kIdF64x1: - if (Type::isVec(srcTypeId)) goto MovXmmQ; + case TypeId::kFloat64: + case TypeId::kFloat64x1: + if (TypeUtils::isVec(srcTypeId)) goto MovXmmQ; break; default: - if (Type::isVec(dstTypeId) && reg.as<Reg>().isVec()) { - stackPtr.setSize(Type::sizeOf(dstTypeId)); + if (TypeUtils::isVec(dstTypeId) && reg.as<Reg>().isVec()) { + stackPtr.setSize(TypeUtils::sizeOf(dstTypeId)); uint32_t vMovInstId = choose(Inst::kIdMovaps, Inst::kIdVmovaps); - if (Type::isVec128(dstTypeId)) - r0.setRegT<Reg::kTypeXmm>(reg.id()); - else if (Type::isVec256(dstTypeId)) - r0.setRegT<Reg::kTypeYmm>(reg.id()); - else if (Type::isVec512(dstTypeId)) - r0.setRegT<Reg::kTypeZmm>(reg.id()); + if (TypeUtils::isVec128(dstTypeId)) + r0.setRegT<RegType::kX86_Xmm>(reg.id()); + else if (TypeUtils::isVec256(dstTypeId)) + r0.setRegT<RegType::kX86_Ymm>(reg.id()); + else if (TypeUtils::isVec512(dstTypeId)) + r0.setRegT<RegType::kX86_Zmm>(reg.id()); else break; @@ -961,7 +981,7 @@ Error RACFGBuilder::moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& a // Extend+Move Gp. ExtendMovGpD: stackPtr.setSize(4); - r0.setRegT<Reg::kTypeGpd>(reg.id()); + r0.setRegT<RegType::kX86_Gpd>(reg.id()); ASMJIT_PROPAGATE(cc()->emit(instId, r0, r1)); ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, stackPtr, r0)); @@ -970,14 +990,14 @@ ExtendMovGpD: ExtendMovGpXQ: if (registerSize == 8) { stackPtr.setSize(8); - r0.setRegT<Reg::kTypeGpq>(reg.id()); + r0.setRegT<RegType::kX86_Gpq>(reg.id()); ASMJIT_PROPAGATE(cc()->emit(instId, r0, r1)); ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, stackPtr, r0)); } else { stackPtr.setSize(4); - r0.setRegT<Reg::kTypeGpd>(reg.id()); + r0.setRegT<RegType::kX86_Gpd>(reg.id()); ASMJIT_PROPAGATE(cc()->emit(instId, r0, r1)); @@ -990,43 +1010,42 @@ ExtendMovGpDQ: ZeroExtendGpDQ: stackPtr.setSize(4); - r0.setRegT<Reg::kTypeGpd>(reg.id()); + r0.setRegT<RegType::kX86_Gpd>(reg.id()); goto ExtendMovGpDQ; MovGpD: stackPtr.setSize(4); - r0.setRegT<Reg::kTypeGpd>(reg.id()); + r0.setRegT<RegType::kX86_Gpd>(reg.id()); return cc()->emit(Inst::kIdMov, stackPtr, r0); MovGpQ: stackPtr.setSize(8); - r0.setRegT<Reg::kTypeGpq>(reg.id()); + r0.setRegT<RegType::kX86_Gpq>(reg.id()); return cc()->emit(Inst::kIdMov, stackPtr, r0); MovMmD: stackPtr.setSize(4); - r0.setRegT<Reg::kTypeMm>(reg.id()); + r0.setRegT<RegType::kX86_Mm>(reg.id()); return cc()->emit(choose(Inst::kIdMovd, Inst::kIdVmovd), stackPtr, r0); MovMmQ: stackPtr.setSize(8); - r0.setRegT<Reg::kTypeMm>(reg.id()); + r0.setRegT<RegType::kX86_Mm>(reg.id()); return cc()->emit(choose(Inst::kIdMovq, Inst::kIdVmovq), stackPtr, r0); MovXmmD: stackPtr.setSize(4); - r0.setRegT<Reg::kTypeXmm>(reg.id()); + r0.setRegT<RegType::kX86_Xmm>(reg.id()); return cc()->emit(choose(Inst::kIdMovss, Inst::kIdVmovss), stackPtr, r0); MovXmmQ: stackPtr.setSize(8); - r0.setRegT<Reg::kTypeXmm>(reg.id()); + r0.setRegT<RegType::kX86_Xmm>(reg.id()); return cc()->emit(choose(Inst::kIdMovlps, Inst::kIdVmovlps), stackPtr, r0); } -// ============================================================================ -// [asmjit::x86::RACFGBuilder - OnReg] -// ============================================================================ +// x86::RACFGBuilder - OnReg +// ========================= Error RACFGBuilder::onBeforeRet(FuncRetNode* funcRet) noexcept { const FuncDetail& funcDetail = _pass->func()->detail(); @@ -1042,7 +1061,7 @@ Error RACFGBuilder::onBeforeRet(FuncRetNode* funcRet) noexcept { if (!op.isReg()) continue; - if (ret.regType() == Reg::kTypeSt) { + if (ret.regType() == RegType::kX86_St) { const Reg& reg = op.as<Reg>(); uint32_t vIndex = Operand::virtIdToIndex(reg.id()); @@ -1050,25 +1069,25 @@ Error RACFGBuilder::onBeforeRet(FuncRetNode* funcRet) noexcept { RAWorkReg* workReg; ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); - if (workReg->group() != Reg::kGroupVec) + if (workReg->group() != RegGroup::kVec) return DebugUtils::errored(kErrorInvalidAssignment); - Reg src = Reg::fromSignatureAndId(workReg->signature(), workReg->virtId()); + Reg src(workReg->signature(), workReg->virtId()); Mem mem; - uint32_t typeId = Type::baseOf(workReg->typeId()); + TypeId typeId = TypeUtils::scalarOf(workReg->typeId()); if (ret.hasTypeId()) typeId = ret.typeId(); switch (typeId) { - case Type::kIdF32: + case TypeId::kFloat32: ASMJIT_PROPAGATE(_pass->useTemporaryMem(mem, 4, 4)); mem.setSize(4); ASMJIT_PROPAGATE(cc()->emit(choose(Inst::kIdMovss, Inst::kIdVmovss), mem, src.as<Xmm>())); ASMJIT_PROPAGATE(cc()->fld(mem)); break; - case Type::kIdF64: + case TypeId::kFloat64: ASMJIT_PROPAGATE(_pass->useTemporaryMem(mem, 8, 4)); mem.setSize(8); ASMJIT_PROPAGATE(cc()->emit(choose(Inst::kIdMovsd, Inst::kIdVmovsd), mem, src.as<Xmm>())); @@ -1099,7 +1118,7 @@ Error RACFGBuilder::onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept { return DebugUtils::errored(kErrorInvalidAssignment); // Not handled here... - if (ret.regType() == Reg::kTypeSt) + if (ret.regType() == RegType::kX86_St) continue; if (op.isReg()) { @@ -1111,9 +1130,9 @@ Error RACFGBuilder::onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept { RAWorkReg* workReg; ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); - uint32_t group = workReg->group(); - uint32_t allocable = _pass->_availableRegs[group]; - ASMJIT_PROPAGATE(ib.add(workReg, RATiedReg::kUse | RATiedReg::kRead, allocable, ret.regId(), 0, BaseReg::kIdBad, 0)); + RegGroup group = workReg->group(); + RegMask inOutRegs = _pass->_availableRegs[group]; + ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, inOutRegs, ret.regId(), 0, inOutRegs, BaseReg::kIdBad, 0)); } } else { @@ -1124,20 +1143,18 @@ Error RACFGBuilder::onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept { return kErrorOk; } -// ============================================================================ -// [asmjit::x86::X86RAPass - Construction / Destruction] -// ============================================================================ +// x86::X86RAPass - Construction & Destruction +// =========================================== X86RAPass::X86RAPass() noexcept : BaseRAPass() { _iEmitHelper = &_emitHelper; } X86RAPass::~X86RAPass() noexcept {} -// ============================================================================ -// [asmjit::x86::X86RAPass - OnInit / OnDone] -// ============================================================================ +// x86::X86RAPass - OnInit & OnDone +// ================================ void X86RAPass::onInit() noexcept { - uint32_t arch = cc()->arch(); + Arch arch = cc()->arch(); uint32_t baseRegCount = Environment::is32Bit(arch) ? 8u : 16u; uint32_t simdRegCount = baseRegCount; @@ -1152,17 +1169,17 @@ void X86RAPass::onInit() noexcept { _emitHelper._avx512Enabled = avx512Enabled; _archTraits = &ArchTraits::byArch(arch); - _physRegCount.set(Reg::kGroupGp , baseRegCount); - _physRegCount.set(Reg::kGroupVec , simdRegCount); - _physRegCount.set(Reg::kGroupMm , 8); - _physRegCount.set(Reg::kGroupKReg, 8); + _physRegCount.set(RegGroup::kGp, baseRegCount); + _physRegCount.set(RegGroup::kVec, simdRegCount); + _physRegCount.set(RegGroup::kX86_K, 8); + _physRegCount.set(RegGroup::kX86_MM, 8); _buildPhysIndex(); _availableRegCount = _physRegCount; - _availableRegs[Reg::kGroupGp ] = Support::lsbMask<uint32_t>(_physRegCount.get(Reg::kGroupGp )); - _availableRegs[Reg::kGroupVec ] = Support::lsbMask<uint32_t>(_physRegCount.get(Reg::kGroupVec )); - _availableRegs[Reg::kGroupMm ] = Support::lsbMask<uint32_t>(_physRegCount.get(Reg::kGroupMm )); - _availableRegs[Reg::kGroupKReg] = Support::lsbMask<uint32_t>(_physRegCount.get(Reg::kGroupKReg)) ^ 1u; + _availableRegs[RegGroup::kGp] = Support::lsbMask<RegMask>(_physRegCount.get(RegGroup::kGp)); + _availableRegs[RegGroup::kVec] = Support::lsbMask<RegMask>(_physRegCount.get(RegGroup::kVec)); + _availableRegs[RegGroup::kX86_K] = Support::lsbMask<RegMask>(_physRegCount.get(RegGroup::kX86_K)) ^ 1u; + _availableRegs[RegGroup::kX86_MM] = Support::lsbMask<RegMask>(_physRegCount.get(RegGroup::kX86_MM)); _scratchRegIndexes[0] = uint8_t(Gp::kIdCx); _scratchRegIndexes[1] = uint8_t(baseRegCount - 1); @@ -1171,8 +1188,8 @@ void X86RAPass::onInit() noexcept { // make unavailable all registers that are special and cannot be used in general. bool hasFP = _func->frame().hasPreservedFP(); - makeUnavailable(Reg::kGroupGp, Gp::kIdSp); // ESP|RSP used as a stack-pointer (SP). - if (hasFP) makeUnavailable(Reg::kGroupGp, Gp::kIdBp); // EBP|RBP used as a frame-pointer (FP). + makeUnavailable(RegGroup::kGp, Gp::kIdSp); // ESP|RSP used as a stack-pointer (SP). + if (hasFP) makeUnavailable(RegGroup::kGp, Gp::kIdBp); // EBP|RBP used as a frame-pointer (FP). _sp = cc()->zsp(); _fp = cc()->zbp(); @@ -1180,19 +1197,17 @@ void X86RAPass::onInit() noexcept { void X86RAPass::onDone() noexcept {} -// ============================================================================ -// [asmjit::x86::X86RAPass - BuildCFG] -// ============================================================================ +// x86::X86RAPass - BuildCFG +// ========================= Error X86RAPass::buildCFG() noexcept { return RACFGBuilder(this).run(); } -// ============================================================================ -// [asmjit::x86::X86RAPass - Rewrite] -// ============================================================================ +// x86::X86RAPass - Rewrite +// ======================== -static uint32_t transformVexToEvex(uint32_t instId) { +static InstId transformVexToEvex(InstId instId) { switch (instId) { case Inst::kIdVbroadcastf128: return Inst::kIdVbroadcastf32x4; case Inst::kIdVbroadcasti128: return Inst::kIdVbroadcasti32x4; @@ -1206,6 +1221,10 @@ static uint32_t transformVexToEvex(uint32_t instId) { case Inst::kIdVpandn: return Inst::kIdVpandnd; case Inst::kIdVpor: return Inst::kIdVpord; case Inst::kIdVpxor: return Inst::kIdVpxord; + case Inst::kIdVroundpd: return Inst::kIdVrndscalepd; + case Inst::kIdVroundps: return Inst::kIdVrndscaleps; + case Inst::kIdVroundsd: return Inst::kIdVrndscalesd; + case Inst::kIdVroundss: return Inst::kIdVrndscaless; default: // This should never happen as only transformable instructions should go this path. @@ -1232,8 +1251,8 @@ ASMJIT_FAVOR_SPEED Error X86RAPass::_rewrite(BaseNode* first, BaseNode* stop) no // Rewrite virtual registers into physical registers. if (raInst) { - // If the instruction contains pass data (raInst) then it was a subject - // for register allocation and must be rewritten to use physical regs. + // If the instruction contains pass data (raInst) then it was a subject for register allocation and must be + // rewritten to use physical regs. RATiedReg* tiedRegs = raInst->tiedRegs(); uint32_t tiedCount = raInst->tiedCount(); @@ -1262,17 +1281,14 @@ ASMJIT_FAVOR_SPEED Error X86RAPass::_rewrite(BaseNode* first, BaseNode* stop) no } } - // This data is allocated by Zone passed to `runOnFunction()`, which - // will be reset after the RA pass finishes. So reset this data to - // prevent having a dead pointer after the RA pass is complete. + // This data is allocated by Zone passed to `runOnFunction()`, which will be reset after the RA pass finishes. + // So reset this data to prevent having a dead pointer after the RA pass is complete. node->resetPassData(); - if (ASMJIT_UNLIKELY(node->type() != BaseNode::kNodeInst)) { - // FuncRet terminates the flow, it must either be removed if the exit - // label is next to it (optimization) or patched to an architecture - // dependent jump instruction that jumps to the function's exit before - // the epilog. - if (node->type() == BaseNode::kNodeFuncRet) { + if (ASMJIT_UNLIKELY(node->type() != NodeType::kInst)) { + // FuncRet terminates the flow, it must either be removed if the exit label is next to it (optimization) or + // patched to an architecture dependent jump instruction that jumps to the function's exit before the epilog. + if (node->type() == NodeType::kFuncRet) { RABlock* block = raInst->block(); if (!isNextTo(node, _func->exitNode())) { cc()->_setCursor(node->prev()); @@ -1317,19 +1333,18 @@ ASMJIT_FAVOR_SPEED Error X86RAPass::_rewrite(BaseNode* first, BaseNode* stop) no return kErrorOk; } -// ============================================================================ -// [asmjit::x86::X86RAPass - OnEmit] -// ============================================================================ +// x86::X86RAPass - OnEmit +// ======================= Error X86RAPass::emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { RAWorkReg* wReg = workRegById(workId); - BaseReg dst = BaseReg::fromSignatureAndId(wReg->info().signature(), dstPhysId); - BaseReg src = BaseReg::fromSignatureAndId(wReg->info().signature(), srcPhysId); + BaseReg dst(wReg->signature(), dstPhysId); + BaseReg src(wReg->signature(), srcPhysId); const char* comment = nullptr; #ifndef ASMJIT_NO_LOGGING - if (_loggerFlags & FormatOptions::kFlagAnnotations) { + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { _tmpString.assignFormat("<MOVE> %s", workRegById(workId)->name()); comment = _tmpString.data(); } @@ -1342,31 +1357,29 @@ Error X86RAPass::emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, RAWorkReg* waReg = workRegById(aWorkId); RAWorkReg* wbReg = workRegById(bWorkId); - bool is64Bit = Support::max(waReg->typeId(), wbReg->typeId()) >= Type::kIdI64; - uint32_t sign = is64Bit ? uint32_t(RegTraits<Reg::kTypeGpq>::kSignature) - : uint32_t(RegTraits<Reg::kTypeGpd>::kSignature); + bool is64Bit = Support::max(waReg->typeId(), wbReg->typeId()) >= TypeId::kInt64; + OperandSignature sign = is64Bit ? OperandSignature(RegTraits<RegType::kX86_Gpq>::kSignature) + : OperandSignature(RegTraits<RegType::kX86_Gpd>::kSignature); #ifndef ASMJIT_NO_LOGGING - if (_loggerFlags & FormatOptions::kFlagAnnotations) { + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { _tmpString.assignFormat("<SWAP> %s, %s", waReg->name(), wbReg->name()); cc()->setInlineComment(_tmpString.data()); } #endif - return cc()->emit(Inst::kIdXchg, - Reg::fromSignatureAndId(sign, aPhysId), - Reg::fromSignatureAndId(sign, bPhysId)); + return cc()->emit(Inst::kIdXchg, Reg(sign, aPhysId), Reg(sign, bPhysId)); } Error X86RAPass::emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept { RAWorkReg* wReg = workRegById(workId); - BaseReg dstReg = BaseReg::fromSignatureAndId(wReg->info().signature(), dstPhysId); - BaseMem srcMem = BaseMem(workRegAsMem(wReg)); + BaseReg dstReg(wReg->signature(), dstPhysId); + BaseMem srcMem(workRegAsMem(wReg)); const char* comment = nullptr; #ifndef ASMJIT_NO_LOGGING - if (_loggerFlags & FormatOptions::kFlagAnnotations) { + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { _tmpString.assignFormat("<LOAD> %s", workRegById(workId)->name()); comment = _tmpString.data(); } @@ -1377,13 +1390,13 @@ Error X86RAPass::emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept { Error X86RAPass::emitSave(uint32_t workId, uint32_t srcPhysId) noexcept { RAWorkReg* wReg = workRegById(workId); - BaseMem dstMem = BaseMem(workRegAsMem(wReg)); - BaseReg srcReg = BaseReg::fromSignatureAndId(wReg->info().signature(), srcPhysId); + BaseMem dstMem(workRegAsMem(wReg)); + BaseReg srcReg(wReg->signature(), srcPhysId); const char* comment = nullptr; #ifndef ASMJIT_NO_LOGGING - if (_loggerFlags & FormatOptions::kFlagAnnotations) { + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { _tmpString.assignFormat("<SAVE> %s", workRegById(workId)->name()); comment = _tmpString.data(); } @@ -1402,7 +1415,7 @@ Error X86RAPass::emitPreCall(InvokeNode* invokeNode) noexcept { uint32_t argCount = invokeNode->argCount(); switch (invokeNode->detail().callConv().id()) { - case CallConv::kIdX64SystemV: { + case CallConvId::kX64SystemV: { // AL register contains the number of arguments passed in XMM register(s). uint32_t n = 0; for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { @@ -1412,7 +1425,7 @@ Error X86RAPass::emitPreCall(InvokeNode* invokeNode) noexcept { if (!arg) break; - if (arg.isReg() && Reg::groupOf(arg.regType()) == Reg::kGroupVec) + if (arg.isReg() && Reg::groupOf(arg.regType()) == RegGroup::kVec) n++; } } @@ -1424,7 +1437,7 @@ Error X86RAPass::emitPreCall(InvokeNode* invokeNode) noexcept { break; } - case CallConv::kIdX64Windows: { + case CallConvId::kX64Windows: { // Each double-precision argument passed in XMM must be also passed in GP. for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { const FuncValuePack& argPack = fd.argPack(argIndex); @@ -1433,8 +1446,8 @@ Error X86RAPass::emitPreCall(InvokeNode* invokeNode) noexcept { if (!arg) break; - if (arg.isReg() && Reg::groupOf(arg.regType()) == Reg::kGroupVec) { - Gp dst = gpq(fd.callConv().passedOrder(Reg::kGroupGp)[argIndex]); + if (arg.isReg() && Reg::groupOf(arg.regType()) == RegGroup::kVec) { + Gp dst = gpq(fd.callConv().passedOrder(RegGroup::kGp)[argIndex]); Xmm src = xmm(arg.regId()); ASMJIT_PROPAGATE(cc()->emit(choose(Inst::kIdMovq, Inst::kIdVmovq), dst, src)); } diff --git a/src/asmjit/x86/x86rapass_p.h b/src/asmjit/x86/x86rapass_p.h index 5faa04f..b9603c2 100644 --- a/src/asmjit/x86/x86rapass_p.h +++ b/src/asmjit/x86/x86rapass_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_X86_X86RAPASS_P_H_INCLUDED #define ASMJIT_X86_X86RAPASS_P_H_INCLUDED @@ -40,14 +22,9 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) //! \addtogroup asmjit_x86 //! \{ -// ============================================================================ -// [asmjit::X86RAPass] -// ============================================================================ - //! X86 register allocation pass. //! -//! Takes care of generating function prologs and epilogs, and also performs -//! register allocation. +//! Takes care of generating function prologs and epilogs, and also performs register allocation. class X86RAPass : public BaseRAPass { public: ASMJIT_NONCOPYABLE(X86RAPass) @@ -55,16 +32,16 @@ public: EmitHelper _emitHelper; - // -------------------------------------------------------------------------- - // [Construction / Destruction] - // -------------------------------------------------------------------------- + //! \name Construction & Destruction + //! \{ X86RAPass() noexcept; virtual ~X86RAPass() noexcept; - // -------------------------------------------------------------------------- - // [Accessors] - // -------------------------------------------------------------------------- + //! \} + + //! \name Accessors + //! \{ //! Returns the compiler casted to `x86::Compiler`. inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); } @@ -72,40 +49,30 @@ public: //! Returns emit helper. inline EmitHelper* emitHelper() noexcept { return &_emitHelper; } - // -------------------------------------------------------------------------- - // [Utilities] - // -------------------------------------------------------------------------- - inline bool avxEnabled() const noexcept { return _emitHelper._avxEnabled; } inline bool avx512Enabled() const noexcept { return _emitHelper._avx512Enabled; } + //! \} + + //! \name Utilities + //! \{ + inline uint32_t choose(uint32_t sseInstId, uint32_t avxInstId) noexcept { return avxEnabled() ? avxInstId : sseInstId; } - // -------------------------------------------------------------------------- - // [OnInit / OnDone] - // -------------------------------------------------------------------------- + //! \} + + //! \name Interface + //! \{ void onInit() noexcept override; void onDone() noexcept override; - // -------------------------------------------------------------------------- - // [CFG] - // -------------------------------------------------------------------------- - Error buildCFG() noexcept override; - // -------------------------------------------------------------------------- - // [Rewrite] - // -------------------------------------------------------------------------- - Error _rewrite(BaseNode* first, BaseNode* stop) noexcept override; - // -------------------------------------------------------------------------- - // [Emit] - // -------------------------------------------------------------------------- - Error emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept override; Error emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept override; @@ -114,6 +81,8 @@ public: Error emitJump(const Label& label) noexcept override; Error emitPreCall(InvokeNode* invokeNode) noexcept override; + + //! \} }; //! \} diff --git a/test/asmjit_test_assembler.cpp b/test/asmjit_test_assembler.cpp index 5ae19ab..bcb16ad 100644 --- a/test/asmjit_test_assembler.cpp +++ b/test/asmjit_test_assembler.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> #include <stdio.h> @@ -41,6 +23,7 @@ int main(int argc, char* argv[]) { TestSettings settings {}; settings.quiet = cmdLine.hasArg("--quiet"); + settings.validate = cmdLine.hasArg("--validate"); printf("AsmJit Assembler Test-Suite v%u.%u.%u:\n\n", unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), @@ -51,6 +34,7 @@ int main(int argc, char* argv[]) { printf(" --help Show usage only\n"); printf(" --arch=<ARCH> Select architecture to run ('all' by default)\n"); printf(" --quiet Show only assembling errors [%s]\n", settings.quiet ? "x" : " "); + printf(" --validate Use instruction validation [%s]\n", settings.validate ? "x" : " "); printf("\n"); if (cmdLine.hasArg("--help")) diff --git a/test/asmjit_test_assembler.h b/test/asmjit_test_assembler.h index c14a300..0e98c26 100644 --- a/test/asmjit_test_assembler.h +++ b/test/asmjit_test_assembler.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_TEST_ASSEMBLER_H_INCLUDED #define ASMJIT_TEST_ASSEMBLER_H_INCLUDED @@ -29,6 +11,7 @@ struct TestSettings { bool quiet; + bool validate; }; template<typename AssemblerType> @@ -42,7 +25,7 @@ public: size_t passed {}; size_t count {}; - AssemblerTester(uint32_t arch, const TestSettings& settings) noexcept + AssemblerTester(asmjit::Arch arch, const TestSettings& settings) noexcept : env(arch), settings(settings) { prepare(); @@ -62,6 +45,9 @@ public: code.reset(); code.init(env, 0); code.attach(&assembler); + + if (settings.validate) + assembler.addDiagnosticOptions(asmjit::DiagnosticOptions::kValidateAssembler); } ASMJIT_NOINLINE bool testInstruction(const char* expectedOpcode, const char* s, uint32_t err) noexcept { diff --git a/test/asmjit_test_assembler_x64.cpp b/test/asmjit_test_assembler_x64.cpp index ab7b780..bedf796 100644 --- a/test/asmjit_test_assembler_x64.cpp +++ b/test/asmjit_test_assembler_x64.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> #if !defined(ASMJIT_NO_X86) @@ -1074,9 +1056,9 @@ static void ASMJIT_NOINLINE testX64AssemblerBase(AssemblerTester<x86::Assembler> TEST_INSTRUCTION("480FBFCA" , movsx(rcx, dx)); TEST_INSTRUCTION("480FBE8C1A80000000" , movsx(rcx, byte_ptr(rdx, rbx, 0, 128))); TEST_INSTRUCTION("480FBF8C1A80000000" , movsx(rcx, word_ptr(rdx, rbx, 0, 128))); - TEST_INSTRUCTION("6663CA" , movsxd(cx, edx)); + TEST_INSTRUCTION("6663CA" , movsxd(cx, dx)); TEST_INSTRUCTION("66638C1A80000000" , movsxd(cx, ptr(rdx, rbx, 0, 128))); - TEST_INSTRUCTION("66638C1A80000000" , movsxd(cx, dword_ptr(rdx, rbx, 0, 128))); + TEST_INSTRUCTION("66638C1A80000000" , movsxd(cx, word_ptr(rdx, rbx, 0, 128))); TEST_INSTRUCTION("63CA" , movsxd(ecx, edx)); TEST_INSTRUCTION("638C1A80000000" , movsxd(ecx, ptr(rdx, rbx, 0, 128))); TEST_INSTRUCTION("638C1A80000000" , movsxd(ecx, dword_ptr(rdx, rbx, 0, 128))); @@ -8033,6 +8015,9625 @@ static void ASMJIT_NOINLINE testX64AssemblerAVX(AssemblerTester<x86::Assembler>& TEST_INSTRUCTION("C5F877" , vzeroupper()); } +static void ASMJIT_NOINLINE testX64AssemblerAVX512_FP16(AssemblerTester<x86::Assembler>& tester) noexcept { + using namespace x86; + + TEST_INSTRUCTION("62F5560810F4" , vmovsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F57E0F10B4F400000010" , k(k7).vmovsh(xmm6, word_ptr(rsp, rsi, 3, 268435456))); + TEST_INSTRUCTION("62F57E081031" , vmovsh(xmm6, word_ptr(rcx))); + TEST_INSTRUCTION("62F57E0810717F" , vmovsh(xmm6, word_ptr(rcx, 254))); + TEST_INSTRUCTION("62F57E8F107280" , k(k7).z().vmovsh(xmm6, word_ptr(rdx, -256))); + TEST_INSTRUCTION("62F57E0F11B4F400000010" , k(k7).vmovsh(word_ptr(rsp, rsi, 3, 268435456), xmm6)); + TEST_INSTRUCTION("62F57E081131" , vmovsh(word_ptr(rcx), xmm6)); + TEST_INSTRUCTION("62F57E0811717F" , vmovsh(word_ptr(rcx, 254), xmm6)); + TEST_INSTRUCTION("62F57E0F117280" , k(k7).vmovsh(word_ptr(rdx, -256), xmm6)); + TEST_INSTRUCTION("62F57D086EF2" , vmovw(xmm6, edx)); + TEST_INSTRUCTION("62F57D087EF2" , vmovw(edx, xmm6)); + TEST_INSTRUCTION("62F57D086EB4F400000010" , vmovw(xmm6, word_ptr(rsp, rsi, 3, 268435456))); + TEST_INSTRUCTION("62F57D086E31" , vmovw(xmm6, word_ptr(rcx))); + TEST_INSTRUCTION("62F57D086E717F" , vmovw(xmm6, word_ptr(rcx, 254))); + TEST_INSTRUCTION("62F57D086E717F" , vmovw(xmm6, word_ptr(rcx, 254))); + TEST_INSTRUCTION("62F57D086E7280" , vmovw(xmm6, word_ptr(rdx, -256))); + TEST_INSTRUCTION("62F57D087EB4F400000010" , vmovw(word_ptr(rsp, esi, 3, 268435456), xmm6)); + TEST_INSTRUCTION("62F57D087E31" , vmovw(word_ptr(rcx), xmm6)); + TEST_INSTRUCTION("62F57D087E717F" , vmovw(word_ptr(rcx, 254), xmm6)); + TEST_INSTRUCTION("62F57D087E7280" , vmovw(word_ptr(rdx, -256), xmm6)); +} + +// Tests generated from 'llvm/test/MC/X86/intel-syntax-avx512.s' file. +static void ASMJIT_NOINLINE testX64AssemblerAVX512_LLVM(AssemblerTester<x86::Assembler>& tester) noexcept { + using namespace x86; + + TEST_INSTRUCTION("62F174485808" , vaddps(zmm1, zmm1, zmmword_ptr(rax))); + TEST_INSTRUCTION("62F1F54858CA" , vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F54D58CA" , k(k5).vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F5CD58CA" , k(k5).z().vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F5CD58CA" , k(k5).z().vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F51858CA" , rn_sae().vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F55858CA" , ru_sae().vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F53858CA" , rd_sae().vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62F1F57858CA" , rz_sae().vaddpd(zmm1, zmm1, zmm2)); + TEST_INSTRUCTION("62919D48C2D2AB" , vcmppd(k2, zmm12, zmm26, 171)); + TEST_INSTRUCTION("62919D4BC2D2AB" , k(k3).vcmppd(k2, zmm12, zmm26, 171)); + TEST_INSTRUCTION("62919D18C2D2AB" , sae().vcmppd(k2, zmm12, zmm26, 171)); + TEST_INSTRUCTION("62919D48C2D27B" , vcmppd(k2, zmm12, zmm26, 123)); + TEST_INSTRUCTION("62919D18C2D27B" , sae().vcmppd(k2, zmm12, zmm26, 123)); + TEST_INSTRUCTION("62F19D48C2117B" , vcmppd(k2, zmm12, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B19D48C294F0230100007B" , vcmppd(k2, zmm12, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F19D58C2117B" , vcmppd(k2, zmm12, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F19D48C2527F7B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F19D48C292002000007B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F19D48C252807B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F19D48C292C0DFFFFF7B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F19D58C2527F7B" , vcmppd(k2, zmm12, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F19D58C292000400007B" , vcmppd(k2, zmm12, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F19D58C252807B" , vcmppd(k2, zmm12, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F19D58C292F8FBFFFF7B" , vcmppd(k2, zmm12, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62B17440C2D6AB" , vcmpps(k2, zmm17, zmm22, 171)); + TEST_INSTRUCTION("62B17443C2D6AB" , k(k3).vcmpps(k2, zmm17, zmm22, 171)); + TEST_INSTRUCTION("62B17410C2D6AB" , sae().vcmpps(k2, zmm17, zmm22, 171)); + TEST_INSTRUCTION("62B17440C2D67B" , vcmpps(k2, zmm17, zmm22, 123)); + TEST_INSTRUCTION("62B17410C2D67B" , sae().vcmpps(k2, zmm17, zmm22, 123)); + TEST_INSTRUCTION("62F17440C2117B" , vcmpps(k2, zmm17, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B17440C294F0230100007B" , vcmpps(k2, zmm17, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F17450C2117B" , vcmpps(k2, zmm17, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F17440C2527F7B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F17440C292002000007B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F17440C252807B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F17440C292C0DFFFFF7B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F17450C2527F7B" , vcmpps(k2, zmm17, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F17450C292000200007B" , vcmpps(k2, zmm17, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F17450C252807B" , vcmpps(k2, zmm17, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F17450C292FCFDFFFF7B" , vcmpps(k2, zmm17, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62136D0055FCAB" , vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D0555FCAB" , k(k5).vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D8555FCAB" , k(k5).z().vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D1055FCAB" , sae().vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D0055FC7B" , vfixupimmss(xmm15, xmm18, xmm28, 123)); + TEST_INSTRUCTION("62136D1055FC7B" , sae().vfixupimmss(xmm15, xmm18, xmm28, 123)); + TEST_INSTRUCTION("62736D0055397B" , vfixupimmss(xmm15, xmm18, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62336D0055BCF0230100007B" , vfixupimmss(xmm15, xmm18, dword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62736D00557A7F7B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62736D0055BA000200007B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62736D00557A807B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62736D0055BAFCFDFFFF7B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("6273AD0055EDAB" , vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD0655EDAB" , k(k6).vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD8655EDAB" , k(k6).z().vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD1055EDAB" , sae().vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD0055ED7B" , vfixupimmsd(xmm13, xmm26, xmm5, 123)); + TEST_INSTRUCTION("6273AD1055ED7B" , sae().vfixupimmsd(xmm13, xmm26, xmm5, 123)); + TEST_INSTRUCTION("6273AD0055297B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233AD0055ACF0230100007B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6273AD00556A7F7B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("6273AD0055AA000400007B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("6273AD00556A807B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("6273AD0055AAF8FBFFFF7B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62E1FD082F39" , vcomisd(xmm23, qword_ptr(rcx))); + TEST_INSTRUCTION("62E17C082F01" , vcomiss(xmm16, dword_ptr(rcx))); + TEST_INSTRUCTION("62717E0A1129" , k(k2).vmovss(dword_ptr(rcx), xmm13)); + TEST_INSTRUCTION("C4217A11ACF034120000" , vmovss(dword_ptr(rax, r14, 3, 4660), xmm13)); + TEST_INSTRUCTION("C57A11AAFC010000" , vmovss(dword_ptr(rdx, 508), xmm13)); + TEST_INSTRUCTION("C57A11AA00020000" , vmovss(dword_ptr(rdx, 512), xmm13)); + TEST_INSTRUCTION("C57A11AA00FEFFFF" , vmovss(dword_ptr(rdx, -512), xmm13)); + TEST_INSTRUCTION("C57A11AAFCFDFFFF" , vmovss(dword_ptr(rdx, -516), xmm13)); + TEST_INSTRUCTION("C5FA11AAFC010000" , vmovss(dword_ptr(rdx, 508), xmm5)); + TEST_INSTRUCTION("C5FA11AA00020000" , vmovss(dword_ptr(rdx, 512), xmm5)); + TEST_INSTRUCTION("C5FA11AA00FEFFFF" , vmovss(dword_ptr(rdx, -512), xmm5)); + TEST_INSTRUCTION("C5FA11AAFCFDFFFF" , vmovss(dword_ptr(rdx, -516), xmm5)); + TEST_INSTRUCTION("C57A1129" , vmovss(dword_ptr(rcx), xmm13)); + TEST_INSTRUCTION("C5FA1011" , vmovss(xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62F17E0C1011" , k(k4).vmovss(xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62F17E8C1011" , k(k4).z().vmovss(xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("6261FF081009" , vmovsd(xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6261FF0B1009" , k(k3).vmovsd(xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6261FF8B1009" , k(k3).z().vmovsd(xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6221FF08108CF023010000" , vmovsd(xmm25, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261FF08104A7F" , vmovsd(xmm25, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261FF08108A00040000" , vmovsd(xmm25, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6261FF08104A80" , vmovsd(xmm25, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261FF08108AF8FBFFFF" , vmovsd(xmm25, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6271A54058C6" , vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A54758C6" , k(k7).vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A5C758C6" , k(k7).z().vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A51058C6" , rn_sae().vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A55058C6" , ru_sae().vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A53058C6" , rd_sae().vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A57058C6" , rz_sae().vaddpd(zmm8, zmm27, zmm6)); + TEST_INSTRUCTION("6271A5405801" , vaddpd(zmm8, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231A5405884F023010000" , vaddpd(zmm8, zmm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271A5505801" , vaddpd(zmm8, zmm27, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271A54058427F" , vaddpd(zmm8, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271A540588200200000" , vaddpd(zmm8, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271A540584280" , vaddpd(zmm8, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271A5405882C0DFFFFF" , vaddpd(zmm8, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271A55058427F" , vaddpd(zmm8, zmm27, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271A550588200040000" , vaddpd(zmm8, zmm27, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271A550584280" , vaddpd(zmm8, zmm27, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271A5505882F8FBFFFF" , vaddpd(zmm8, zmm27, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E1144858D2" , vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E1144C58D2" , k(k4).vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E114CC58D2" , k(k4).z().vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E1141858D2" , rn_sae().vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E1145858D2" , ru_sae().vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E1143858D2" , rd_sae().vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E1147858D2" , rz_sae().vaddps(zmm18, zmm13, zmm2)); + TEST_INSTRUCTION("62E114485811" , vaddps(zmm18, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A114485894F023010000" , vaddps(zmm18, zmm13, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E114585811" , vaddps(zmm18, zmm13, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E1144858527F" , vaddps(zmm18, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E11448589200200000" , vaddps(zmm18, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E11448585280" , vaddps(zmm18, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E114485892C0DFFFFF" , vaddps(zmm18, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1145858527F" , vaddps(zmm18, zmm13, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E11458589200020000" , vaddps(zmm18, zmm13, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E11458585280" , vaddps(zmm18, zmm13, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E114585892FCFDFFFF" , vaddps(zmm18, zmm13, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D1F70058D8" , vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62D1F70358D8" , k(k3).vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62D1F78358D8" , k(k3).z().vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62D1F71058D8" , rn_sae().vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62D1F75058D8" , ru_sae().vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62D1F73058D8" , rd_sae().vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62D1F77058D8" , rz_sae().vaddsd(xmm3, xmm17, xmm8)); + TEST_INSTRUCTION("62F1F7005819" , vaddsd(xmm3, xmm17, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1F700589CF023010000" , vaddsd(xmm3, xmm17, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1F700585A7F" , vaddsd(xmm3, xmm17, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1F700589A00040000" , vaddsd(xmm3, xmm17, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1F700585A80" , vaddsd(xmm3, xmm17, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1F700589AF8FBFFFF" , vaddsd(xmm3, xmm17, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B1560858FB" , vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("62B1560A58FB" , k(k2).vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("62B1568A58FB" , k(k2).z().vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("62B1561858FB" , rn_sae().vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("62B1565858FB" , ru_sae().vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("62B1563858FB" , rd_sae().vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("62B1567858FB" , rz_sae().vaddss(xmm7, xmm5, xmm19)); + TEST_INSTRUCTION("C5D25839" , vaddss(xmm7, xmm5, dword_ptr(rcx))); + TEST_INSTRUCTION("C4A15258BCF023010000" , vaddss(xmm7, xmm5, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5D258BAFC010000" , vaddss(xmm7, xmm5, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5D258BA00020000" , vaddss(xmm7, xmm5, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5D258BA00FEFFFF" , vaddss(xmm7, xmm5, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5D258BAFCFDFFFF" , vaddss(xmm7, xmm5, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62136D4003CAAB" , valignd(zmm9, zmm18, zmm26, 171)); + TEST_INSTRUCTION("62136D4403CAAB" , k(k4).valignd(zmm9, zmm18, zmm26, 171)); + TEST_INSTRUCTION("62136DC403CAAB" , k(k4).z().valignd(zmm9, zmm18, zmm26, 171)); + TEST_INSTRUCTION("62136D4003CA7B" , valignd(zmm9, zmm18, zmm26, 123)); + TEST_INSTRUCTION("62736D4003097B" , valignd(zmm9, zmm18, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62336D40038CF0230100007B" , valignd(zmm9, zmm18, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62736D5003097B" , valignd(zmm9, zmm18, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62736D40034A7F7B" , valignd(zmm9, zmm18, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62736D40038A002000007B" , valignd(zmm9, zmm18, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62736D40034A807B" , valignd(zmm9, zmm18, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62736D40038AC0DFFFFF7B" , valignd(zmm9, zmm18, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62736D50034A7F7B" , valignd(zmm9, zmm18, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62736D50038A000200007B" , valignd(zmm9, zmm18, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62736D50034A807B" , valignd(zmm9, zmm18, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62736D50038AFCFDFFFF7B" , valignd(zmm9, zmm18, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62529D4065C4" , vblendmpd(zmm8, zmm28, zmm12)); + TEST_INSTRUCTION("62529D4165C4" , k(k1).vblendmpd(zmm8, zmm28, zmm12)); + TEST_INSTRUCTION("62529DC165C4" , k(k1).z().vblendmpd(zmm8, zmm28, zmm12)); + TEST_INSTRUCTION("62729D406501" , vblendmpd(zmm8, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62329D406584F023010000" , vblendmpd(zmm8, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62729D506501" , vblendmpd(zmm8, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62729D4065427F" , vblendmpd(zmm8, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62729D40658200200000" , vblendmpd(zmm8, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62729D40654280" , vblendmpd(zmm8, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62729D406582C0DFFFFF" , vblendmpd(zmm8, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62729D5065427F" , vblendmpd(zmm8, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62729D50658200040000" , vblendmpd(zmm8, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62729D50654280" , vblendmpd(zmm8, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62729D506582F8FBFFFF" , vblendmpd(zmm8, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62721D4065FC" , vblendmps(zmm15, zmm28, zmm4)); + TEST_INSTRUCTION("62721D4365FC" , k(k3).vblendmps(zmm15, zmm28, zmm4)); + TEST_INSTRUCTION("62721DC365FC" , k(k3).z().vblendmps(zmm15, zmm28, zmm4)); + TEST_INSTRUCTION("62721D406539" , vblendmps(zmm15, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62321D4065BCF023010000" , vblendmps(zmm15, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62721D506539" , vblendmps(zmm15, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62721D40657A7F" , vblendmps(zmm15, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62721D4065BA00200000" , vblendmps(zmm15, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62721D40657A80" , vblendmps(zmm15, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62721D4065BAC0DFFFFF" , vblendmps(zmm15, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62721D50657A7F" , vblendmps(zmm15, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62721D5065BA00020000" , vblendmps(zmm15, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62721D50657A80" , vblendmps(zmm15, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62721D5065BAFCFDFFFF" , vblendmps(zmm15, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F27D481A19" , vbroadcastf32x4(zmm3, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27D4F1A19" , k(k7).vbroadcastf32x4(zmm3, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27DCF1A19" , k(k7).z().vbroadcastf32x4(zmm3, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D481A9CF023010000" , vbroadcastf32x4(zmm3, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D481A5A7F" , vbroadcastf32x4(zmm3, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62F27D481A9A00080000" , vbroadcastf32x4(zmm3, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62F27D481A5A80" , vbroadcastf32x4(zmm3, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62F27D481A9AF0F7FFFF" , vbroadcastf32x4(zmm3, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6262FD481B09" , vbroadcastf64x4(zmm25, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6262FD4E1B09" , k(k6).vbroadcastf64x4(zmm25, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6262FDCE1B09" , k(k6).z().vbroadcastf64x4(zmm25, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6222FD481B8CF023010000" , vbroadcastf64x4(zmm25, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262FD481B4A7F" , vbroadcastf64x4(zmm25, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("6262FD481B8A00100000" , vbroadcastf64x4(zmm25, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("6262FD481B4A80" , vbroadcastf64x4(zmm25, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("6262FD481B8AE0EFFFFF" , vbroadcastf64x4(zmm25, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62627D485A31" , vbroadcasti32x4(zmm30, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62627D4B5A31" , k(k3).vbroadcasti32x4(zmm30, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62627DCB5A31" , k(k3).z().vbroadcasti32x4(zmm30, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62227D485AB4F023010000" , vbroadcasti32x4(zmm30, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62627D485A727F" , vbroadcasti32x4(zmm30, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62627D485AB200080000" , vbroadcasti32x4(zmm30, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62627D485A7280" , vbroadcasti32x4(zmm30, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62627D485AB2F0F7FFFF" , vbroadcasti32x4(zmm30, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6272FD485B29" , vbroadcasti64x4(zmm13, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6272FD4C5B29" , k(k4).vbroadcasti64x4(zmm13, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6272FDCC5B29" , k(k4).z().vbroadcasti64x4(zmm13, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6232FD485BACF023010000" , vbroadcasti64x4(zmm13, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272FD485B6A7F" , vbroadcasti64x4(zmm13, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("6272FD485BAA00100000" , vbroadcasti64x4(zmm13, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("6272FD485B6A80" , vbroadcasti64x4(zmm13, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("6272FD485BAAE0EFFFFF" , vbroadcasti64x4(zmm13, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("6262FD481931" , vbroadcastsd(zmm30, qword_ptr(rcx))); + TEST_INSTRUCTION("6262FD4C1931" , k(k4).vbroadcastsd(zmm30, qword_ptr(rcx))); + TEST_INSTRUCTION("6262FDCC1931" , k(k4).z().vbroadcastsd(zmm30, qword_ptr(rcx))); + TEST_INSTRUCTION("6222FD4819B4F023010000" , vbroadcastsd(zmm30, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262FD4819727F" , vbroadcastsd(zmm30, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262FD4819B200040000" , vbroadcastsd(zmm30, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262FD48197280" , vbroadcastsd(zmm30, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262FD4819B2F8FBFFFF" , vbroadcastsd(zmm30, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62A2FD4819EE" , vbroadcastsd(zmm21, xmm22)); + TEST_INSTRUCTION("62A2FD4F19EE" , k(k7).vbroadcastsd(zmm21, xmm22)); + TEST_INSTRUCTION("62A2FDCF19EE" , k(k7).z().vbroadcastsd(zmm21, xmm22)); + TEST_INSTRUCTION("62F27D481819" , vbroadcastss(zmm3, dword_ptr(rcx))); + TEST_INSTRUCTION("62F27D4C1819" , k(k4).vbroadcastss(zmm3, dword_ptr(rcx))); + TEST_INSTRUCTION("62F27DCC1819" , k(k4).z().vbroadcastss(zmm3, dword_ptr(rcx))); + TEST_INSTRUCTION("62B27D48189CF023010000" , vbroadcastss(zmm3, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D48185A7F" , vbroadcastss(zmm3, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F27D48189A00020000" , vbroadcastss(zmm3, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F27D48185A80" , vbroadcastss(zmm3, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F27D48189AFCFDFFFF" , vbroadcastss(zmm3, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62A27D4818D2" , vbroadcastss(zmm18, xmm18)); + TEST_INSTRUCTION("62A27D4A18D2" , k(k2).vbroadcastss(zmm18, xmm18)); + TEST_INSTRUCTION("62A27DCA18D2" , k(k2).z().vbroadcastss(zmm18, xmm18)); + TEST_INSTRUCTION("62919D48C2D2AB" , vcmppd(k2, zmm12, zmm26, 171)); + TEST_INSTRUCTION("62919D4BC2D2AB" , k(k3).vcmppd(k2, zmm12, zmm26, 171)); + TEST_INSTRUCTION("62919D18C2D2AB" , sae().vcmppd(k2, zmm12, zmm26, 171)); + TEST_INSTRUCTION("62919D48C2D27B" , vcmppd(k2, zmm12, zmm26, 123)); + TEST_INSTRUCTION("62919D18C2D27B" , sae().vcmppd(k2, zmm12, zmm26, 123)); + TEST_INSTRUCTION("62F19D48C2117B" , vcmppd(k2, zmm12, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B19D48C294F0230100007B" , vcmppd(k2, zmm12, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F19D58C2117B" , vcmppd(k2, zmm12, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F19D48C2527F7B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F19D48C292002000007B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F19D48C252807B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F19D48C292C0DFFFFF7B" , vcmppd(k2, zmm12, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F19D58C2527F7B" , vcmppd(k2, zmm12, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F19D58C292000400007B" , vcmppd(k2, zmm12, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F19D58C252807B" , vcmppd(k2, zmm12, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F19D58C292F8FBFFFF7B" , vcmppd(k2, zmm12, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62B17440C2D6AB" , vcmpps(k2, zmm17, zmm22, 171)); + TEST_INSTRUCTION("62B17443C2D6AB" , k(k3).vcmpps(k2, zmm17, zmm22, 171)); + TEST_INSTRUCTION("62B17410C2D6AB" , sae().vcmpps(k2, zmm17, zmm22, 171)); + TEST_INSTRUCTION("62B17440C2D67B" , vcmpps(k2, zmm17, zmm22, 123)); + TEST_INSTRUCTION("62B17410C2D67B" , sae().vcmpps(k2, zmm17, zmm22, 123)); + TEST_INSTRUCTION("62F17440C2117B" , vcmpps(k2, zmm17, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B17440C294F0230100007B" , vcmpps(k2, zmm17, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F17450C2117B" , vcmpps(k2, zmm17, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F17440C2527F7B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F17440C292002000007B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F17440C252807B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F17440C292C0DFFFFF7B" , vcmpps(k2, zmm17, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F17450C2527F7B" , vcmpps(k2, zmm17, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F17450C292000200007B" , vcmpps(k2, zmm17, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F17450C252807B" , vcmpps(k2, zmm17, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F17450C292FCFDFFFF7B" , vcmpps(k2, zmm17, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62F1E700C2ECAB" , vcmpsd(k5, xmm19, xmm4, 171)); + TEST_INSTRUCTION("62F1E701C2ECAB" , k(k1).vcmpsd(k5, xmm19, xmm4, 171)); + TEST_INSTRUCTION("62F1E710C2ECAB" , sae().vcmpsd(k5, xmm19, xmm4, 171)); + TEST_INSTRUCTION("62F1E700C2EC7B" , vcmpsd(k5, xmm19, xmm4, 123)); + TEST_INSTRUCTION("62F1E710C2EC7B" , sae().vcmpsd(k5, xmm19, xmm4, 123)); + TEST_INSTRUCTION("62F1E700C2297B" , vcmpsd(k5, xmm19, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1E700C2ACF0230100007B" , vcmpsd(k5, xmm19, qword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1E700C26A7F7B" , vcmpsd(k5, xmm19, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("62F1E700C2AA000400007B" , vcmpsd(k5, xmm19, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("62F1E700C26A807B" , vcmpsd(k5, xmm19, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("62F1E700C2AAF8FBFFFF7B" , vcmpsd(k5, xmm19, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62D10608C2E4AB" , vcmpss(k4, xmm15, xmm12, 171)); + TEST_INSTRUCTION("62D1060DC2E4AB" , k(k5).vcmpss(k4, xmm15, xmm12, 171)); + TEST_INSTRUCTION("62D10618C2E4AB" , sae().vcmpss(k4, xmm15, xmm12, 171)); + TEST_INSTRUCTION("62D10608C2E47B" , vcmpss(k4, xmm15, xmm12, 123)); + TEST_INSTRUCTION("62D10618C2E47B" , sae().vcmpss(k4, xmm15, xmm12, 123)); + TEST_INSTRUCTION("62F10608C2217B" , vcmpss(k4, xmm15, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B10608C2A4F0230100007B" , vcmpss(k4, xmm15, dword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F10608C2627F7B" , vcmpss(k4, xmm15, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62F10608C2A2000200007B" , vcmpss(k4, xmm15, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62F10608C262807B" , vcmpss(k4, xmm15, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62F10608C2A2FCFDFFFF7B" , vcmpss(k4, xmm15, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62A1FD082FFD" , vcomisd(xmm23, xmm21)); + TEST_INSTRUCTION("62A1FD182FFD" , sae().vcomisd(xmm23, xmm21)); + TEST_INSTRUCTION("62E1FD082F39" , vcomisd(xmm23, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD082FBCF023010000" , vcomisd(xmm23, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1FD082F7A7F" , vcomisd(xmm23, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1FD082FBA00040000" , vcomisd(xmm23, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1FD082F7A80" , vcomisd(xmm23, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1FD082FBAF8FBFFFF" , vcomisd(xmm23, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62117C082FF4" , vcomiss(xmm14, xmm28)); + TEST_INSTRUCTION("62117C182FF4" , sae().vcomiss(xmm14, xmm28)); + TEST_INSTRUCTION("C5782F31" , vcomiss(xmm14, dword_ptr(rcx))); + TEST_INSTRUCTION("C421782FB4F023010000" , vcomiss(xmm14, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5782FB2FC010000" , vcomiss(xmm14, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5782FB200020000" , vcomiss(xmm14, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5782FB200FEFFFF" , vcomiss(xmm14, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5782FB2FCFDFFFF" , vcomiss(xmm14, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6272FD488A09" , vcompresspd(zmmword_ptr(rcx), zmm9)); + TEST_INSTRUCTION("6272FD4C8A09" , k(k4).vcompresspd(zmmword_ptr(rcx), zmm9)); + TEST_INSTRUCTION("6232FD488A8CF023010000" , vcompresspd(zmmword_ptr(rax, r14, 3, 291), zmm9)); + TEST_INSTRUCTION("6272FD488A4A7F" , vcompresspd(zmmword_ptr(rdx, 1016), zmm9)); + TEST_INSTRUCTION("6272FD488A8A00040000" , vcompresspd(zmmword_ptr(rdx, 1024), zmm9)); + TEST_INSTRUCTION("6272FD488A4A80" , vcompresspd(zmmword_ptr(rdx, -1024), zmm9)); + TEST_INSTRUCTION("6272FD488A8AF8FBFFFF" , vcompresspd(zmmword_ptr(rdx, -1032), zmm9)); + TEST_INSTRUCTION("62D2FD488AE0" , vcompresspd(zmm8, zmm4)); + TEST_INSTRUCTION("62D2FD4E8AE0" , k(k6).vcompresspd(zmm8, zmm4)); + TEST_INSTRUCTION("62D2FDCE8AE0" , k(k6).z().vcompresspd(zmm8, zmm4)); + TEST_INSTRUCTION("62727D488A11" , vcompressps(zmmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("62727D4F8A11" , k(k7).vcompressps(zmmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("62327D488A94F023010000" , vcompressps(zmmword_ptr(rax, r14, 3, 291), zmm10)); + TEST_INSTRUCTION("62727D488A527F" , vcompressps(zmmword_ptr(rdx, 508), zmm10)); + TEST_INSTRUCTION("62727D488A9200020000" , vcompressps(zmmword_ptr(rdx, 512), zmm10)); + TEST_INSTRUCTION("62727D488A5280" , vcompressps(zmmword_ptr(rdx, -512), zmm10)); + TEST_INSTRUCTION("62727D488A92FCFDFFFF" , vcompressps(zmmword_ptr(rdx, -516), zmm10)); + TEST_INSTRUCTION("62727D488AF4" , vcompressps(zmm4, zmm14)); + TEST_INSTRUCTION("62727D4A8AF4" , k(k2).vcompressps(zmm4, zmm14)); + TEST_INSTRUCTION("62727DCA8AF4" , k(k2).z().vcompressps(zmm4, zmm14)); + TEST_INSTRUCTION("62817E48E6F0" , vcvtdq2pd(zmm22, ymm24)); + TEST_INSTRUCTION("62817E4CE6F0" , k(k4).vcvtdq2pd(zmm22, ymm24)); + TEST_INSTRUCTION("62817ECCE6F0" , k(k4).z().vcvtdq2pd(zmm22, ymm24)); + TEST_INSTRUCTION("62E17E48E631" , vcvtdq2pd(zmm22, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62A17E48E6B4F023010000" , vcvtdq2pd(zmm22, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17E58E631" , vcvtdq2pd(zmm22, dword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E17E48E6727F" , vcvtdq2pd(zmm22, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62E17E48E6B200100000" , vcvtdq2pd(zmm22, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62E17E48E67280" , vcvtdq2pd(zmm22, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62E17E48E6B2E0EFFFFF" , vcvtdq2pd(zmm22, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62E17E58E6727F" , vcvtdq2pd(zmm22, dword_ptr(rdx, 508)._1to8())); + TEST_INSTRUCTION("62E17E58E6B200020000" , vcvtdq2pd(zmm22, dword_ptr(rdx, 512)._1to8())); + TEST_INSTRUCTION("62E17E58E67280" , vcvtdq2pd(zmm22, dword_ptr(rdx, -512)._1to8())); + TEST_INSTRUCTION("62E17E58E6B2FCFDFFFF" , vcvtdq2pd(zmm22, dword_ptr(rdx, -516)._1to8())); + TEST_INSTRUCTION("62917C485BF9" , vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62917C4D5BF9" , k(k5).vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62917CCD5BF9" , k(k5).z().vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62917C185BF9" , rn_sae().vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62917C585BF9" , ru_sae().vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62917C385BF9" , rd_sae().vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62917C785BF9" , rz_sae().vcvtdq2ps(zmm7, zmm25)); + TEST_INSTRUCTION("62F17C485B39" , vcvtdq2ps(zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17C485BBCF023010000" , vcvtdq2ps(zmm7, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17C585B39" , vcvtdq2ps(zmm7, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F17C485B7A7F" , vcvtdq2ps(zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17C485BBA00200000" , vcvtdq2ps(zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17C485B7A80" , vcvtdq2ps(zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17C485BBAC0DFFFFF" , vcvtdq2ps(zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F17C585B7A7F" , vcvtdq2ps(zmm7, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F17C585BBA00020000" , vcvtdq2ps(zmm7, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F17C585B7A80" , vcvtdq2ps(zmm7, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F17C585BBAFCFDFFFF" , vcvtdq2ps(zmm7, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6241FF48E6C7" , vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6241FF4BE6C7" , k(k3).vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6241FFCBE6C7" , k(k3).z().vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6241FF18E6C7" , rn_sae().vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6241FF58E6C7" , ru_sae().vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6241FF38E6C7" , rd_sae().vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6241FF78E6C7" , rz_sae().vcvtpd2dq(ymm24, zmm15)); + TEST_INSTRUCTION("6261FF48E601" , vcvtpd2dq(ymm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221FF48E684F023010000" , vcvtpd2dq(ymm24, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261FF58E601" , vcvtpd2dq(ymm24, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261FF48E6427F" , vcvtpd2dq(ymm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261FF48E68200200000" , vcvtpd2dq(ymm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261FF48E64280" , vcvtpd2dq(ymm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261FF48E682C0DFFFFF" , vcvtpd2dq(ymm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261FF58E6427F" , vcvtpd2dq(ymm24, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261FF58E68200040000" , vcvtpd2dq(ymm24, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261FF58E64280" , vcvtpd2dq(ymm24, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261FF58E682F8FBFFFF" , vcvtpd2dq(ymm24, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B1FD485AEF" , vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62B1FD4D5AEF" , k(k5).vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62B1FDCD5AEF" , k(k5).z().vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62B1FD185AEF" , rn_sae().vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62B1FD585AEF" , ru_sae().vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62B1FD385AEF" , rd_sae().vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62B1FD785AEF" , rz_sae().vcvtpd2ps(ymm5, zmm23)); + TEST_INSTRUCTION("62F1FD485A29" , vcvtpd2ps(ymm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FD485AACF023010000" , vcvtpd2ps(ymm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FD585A29" , vcvtpd2ps(ymm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1FD485A6A7F" , vcvtpd2ps(ymm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FD485AAA00200000" , vcvtpd2ps(ymm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FD485A6A80" , vcvtpd2ps(ymm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FD485AAAC0DFFFFF" , vcvtpd2ps(ymm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1FD585A6A7F" , vcvtpd2ps(ymm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1FD585AAA00040000" , vcvtpd2ps(ymm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1FD585A6A80" , vcvtpd2ps(ymm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1FD585AAAF8FBFFFF" , vcvtpd2ps(ymm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6231FC4879FB" , vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6231FC4F79FB" , k(k7).vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6231FCCF79FB" , k(k7).z().vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6231FC1879FB" , rn_sae().vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6231FC5879FB" , ru_sae().vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6231FC3879FB" , rd_sae().vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6231FC7879FB" , rz_sae().vcvtpd2udq(ymm15, zmm19)); + TEST_INSTRUCTION("6271FC487939" , vcvtpd2udq(ymm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231FC4879BCF023010000" , vcvtpd2udq(ymm15, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271FC587939" , vcvtpd2udq(ymm15, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271FC48797A7F" , vcvtpd2udq(ymm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271FC4879BA00200000" , vcvtpd2udq(ymm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271FC48797A80" , vcvtpd2udq(ymm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271FC4879BAC0DFFFFF" , vcvtpd2udq(ymm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271FC58797A7F" , vcvtpd2udq(ymm15, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271FC5879BA00040000" , vcvtpd2udq(ymm15, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271FC58797A80" , vcvtpd2udq(ymm15, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271FC5879BAF8FBFFFF" , vcvtpd2udq(ymm15, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62127D4813EB" , vcvtph2ps(zmm13, ymm27)); + TEST_INSTRUCTION("62127D4B13EB" , k(k3).vcvtph2ps(zmm13, ymm27)); + TEST_INSTRUCTION("62127DCB13EB" , k(k3).z().vcvtph2ps(zmm13, ymm27)); + TEST_INSTRUCTION("62127D1813EB" , sae().vcvtph2ps(zmm13, ymm27)); + TEST_INSTRUCTION("62727D481329" , vcvtph2ps(zmm13, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62327D4813ACF023010000" , vcvtph2ps(zmm13, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62727D48136A7F" , vcvtph2ps(zmm13, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62727D4813AA00100000" , vcvtph2ps(zmm13, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62727D48136A80" , vcvtph2ps(zmm13, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62727D4813AAE0EFFFFF" , vcvtph2ps(zmm13, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62117D485BE0" , vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62117D4C5BE0" , k(k4).vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62117DCC5BE0" , k(k4).z().vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62117D185BE0" , rn_sae().vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62117D585BE0" , ru_sae().vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62117D385BE0" , rd_sae().vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62117D785BE0" , rz_sae().vcvtps2dq(zmm12, zmm24)); + TEST_INSTRUCTION("62717D485B21" , vcvtps2dq(zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62317D485BA4F023010000" , vcvtps2dq(zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717D585B21" , vcvtps2dq(zmm12, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62717D485B627F" , vcvtps2dq(zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62717D485BA200200000" , vcvtps2dq(zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62717D485B6280" , vcvtps2dq(zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62717D485BA2C0DFFFFF" , vcvtps2dq(zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62717D585B627F" , vcvtps2dq(zmm12, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62717D585BA200020000" , vcvtps2dq(zmm12, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62717D585B6280" , vcvtps2dq(zmm12, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62717D585BA2FCFDFFFF" , vcvtps2dq(zmm12, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62717C485AEE" , vcvtps2pd(zmm13, ymm6)); + TEST_INSTRUCTION("62717C4B5AEE" , k(k3).vcvtps2pd(zmm13, ymm6)); + TEST_INSTRUCTION("62717CCB5AEE" , k(k3).z().vcvtps2pd(zmm13, ymm6)); + TEST_INSTRUCTION("62717C185AEE" , sae().vcvtps2pd(zmm13, ymm6)); + TEST_INSTRUCTION("62717C485A29" , vcvtps2pd(zmm13, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62317C485AACF023010000" , vcvtps2pd(zmm13, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717C585A29" , vcvtps2pd(zmm13, dword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62717C485A6A7F" , vcvtps2pd(zmm13, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62717C485AAA00100000" , vcvtps2pd(zmm13, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62717C485A6A80" , vcvtps2pd(zmm13, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62717C485AAAE0EFFFFF" , vcvtps2pd(zmm13, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62717C585A6A7F" , vcvtps2pd(zmm13, dword_ptr(rdx, 508)._1to8())); + TEST_INSTRUCTION("62717C585AAA00020000" , vcvtps2pd(zmm13, dword_ptr(rdx, 512)._1to8())); + TEST_INSTRUCTION("62717C585A6A80" , vcvtps2pd(zmm13, dword_ptr(rdx, -512)._1to8())); + TEST_INSTRUCTION("62717C585AAAFCFDFFFF" , vcvtps2pd(zmm13, dword_ptr(rdx, -516)._1to8())); + TEST_INSTRUCTION("62537D481DF3AB" , vcvtps2ph(ymm11, zmm14, 171)); + TEST_INSTRUCTION("62537D4E1DF3AB" , k(k6).vcvtps2ph(ymm11, zmm14, 171)); + TEST_INSTRUCTION("62537DCE1DF3AB" , k(k6).z().vcvtps2ph(ymm11, zmm14, 171)); + TEST_INSTRUCTION("62537D181DF3AB" , sae().vcvtps2ph(ymm11, zmm14, 171)); + TEST_INSTRUCTION("62537D481DF37B" , vcvtps2ph(ymm11, zmm14, 123)); + TEST_INSTRUCTION("62537D181DF37B" , sae().vcvtps2ph(ymm11, zmm14, 123)); + TEST_INSTRUCTION("62117C4879E2" , vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62117C4C79E2" , k(k4).vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62117CCC79E2" , k(k4).z().vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62117C1879E2" , rn_sae().vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62117C5879E2" , ru_sae().vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62117C3879E2" , rd_sae().vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62117C7879E2" , rz_sae().vcvtps2udq(zmm12, zmm26)); + TEST_INSTRUCTION("62717C487921" , vcvtps2udq(zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62317C4879A4F023010000" , vcvtps2udq(zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717C587921" , vcvtps2udq(zmm12, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62717C4879627F" , vcvtps2udq(zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62717C4879A200200000" , vcvtps2udq(zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62717C48796280" , vcvtps2udq(zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62717C4879A2C0DFFFFF" , vcvtps2udq(zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62717C5879627F" , vcvtps2udq(zmm12, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62717C5879A200020000" , vcvtps2udq(zmm12, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62717C58796280" , vcvtps2udq(zmm12, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62717C5879A2FCFDFFFF" , vcvtps2udq(zmm12, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F17F182DC7" , rn_sae().vcvtsd2si(eax, xmm7)); + TEST_INSTRUCTION("62F17F582DC7" , ru_sae().vcvtsd2si(eax, xmm7)); + TEST_INSTRUCTION("62F17F382DC7" , rd_sae().vcvtsd2si(eax, xmm7)); + TEST_INSTRUCTION("62F17F782DC7" , rz_sae().vcvtsd2si(eax, xmm7)); + TEST_INSTRUCTION("62F17F182DEF" , rn_sae().vcvtsd2si(ebp, xmm7)); + TEST_INSTRUCTION("62F17F582DEF" , ru_sae().vcvtsd2si(ebp, xmm7)); + TEST_INSTRUCTION("62F17F382DEF" , rd_sae().vcvtsd2si(ebp, xmm7)); + TEST_INSTRUCTION("62F17F782DEF" , rz_sae().vcvtsd2si(ebp, xmm7)); + TEST_INSTRUCTION("62717F182DEF" , rn_sae().vcvtsd2si(r13d, xmm7)); + TEST_INSTRUCTION("62717F582DEF" , ru_sae().vcvtsd2si(r13d, xmm7)); + TEST_INSTRUCTION("62717F382DEF" , rd_sae().vcvtsd2si(r13d, xmm7)); + TEST_INSTRUCTION("62717F782DEF" , rz_sae().vcvtsd2si(r13d, xmm7)); + TEST_INSTRUCTION("62D1FF182DC2" , rn_sae().vcvtsd2si(rax, xmm10)); + TEST_INSTRUCTION("62D1FF582DC2" , ru_sae().vcvtsd2si(rax, xmm10)); + TEST_INSTRUCTION("62D1FF382DC2" , rd_sae().vcvtsd2si(rax, xmm10)); + TEST_INSTRUCTION("62D1FF782DC2" , rz_sae().vcvtsd2si(rax, xmm10)); + TEST_INSTRUCTION("6251FF182DC2" , rn_sae().vcvtsd2si(r8, xmm10)); + TEST_INSTRUCTION("6251FF582DC2" , ru_sae().vcvtsd2si(r8, xmm10)); + TEST_INSTRUCTION("6251FF382DC2" , rd_sae().vcvtsd2si(r8, xmm10)); + TEST_INSTRUCTION("6251FF782DC2" , rz_sae().vcvtsd2si(r8, xmm10)); + TEST_INSTRUCTION("62C1B7085ACC" , vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62C1B70E5ACC" , k(k6).vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62C1B78E5ACC" , k(k6).z().vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62C1B7185ACC" , rn_sae().vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62C1B7585ACC" , ru_sae().vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62C1B7385ACC" , rd_sae().vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62C1B7785ACC" , rz_sae().vcvtsd2ss(xmm17, xmm9, xmm12)); + TEST_INSTRUCTION("62E1B7085A09" , vcvtsd2ss(xmm17, xmm9, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1B7085A8CF023010000" , vcvtsd2ss(xmm17, xmm9, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1B7085A4A7F" , vcvtsd2ss(xmm17, xmm9, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1B7085A8A00040000" , vcvtsd2ss(xmm17, xmm9, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1B7085A4A80" , vcvtsd2ss(xmm17, xmm9, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1B7085A8AF8FBFFFF" , vcvtsd2ss(xmm17, xmm9, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C5AB2AF8" , vcvtsi2sd(xmm7, xmm10, eax)); + TEST_INSTRUCTION("C5AB2AFD" , vcvtsi2sd(xmm7, xmm10, ebp)); + TEST_INSTRUCTION("C4C12B2AFD" , vcvtsi2sd(xmm7, xmm10, r13d)); + TEST_INSTRUCTION("C5AB2A39" , vcvtsi2sd(xmm7, xmm10, dword_ptr(rcx))); + TEST_INSTRUCTION("C4A12B2ABCF023010000" , vcvtsi2sd(xmm7, xmm10, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5AB2ABAFC010000" , vcvtsi2sd(xmm7, xmm10, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5AB2ABA00020000" , vcvtsi2sd(xmm7, xmm10, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5AB2ABA00FEFFFF" , vcvtsi2sd(xmm7, xmm10, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5AB2ABAFCFDFFFF" , vcvtsi2sd(xmm7, xmm10, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62619F082AE8" , vcvtsi2sd(xmm29, xmm12, rax)); + TEST_INSTRUCTION("62619F182AE8" , rn_sae().vcvtsi2sd(xmm29, xmm12, rax)); + TEST_INSTRUCTION("62619F582AE8" , ru_sae().vcvtsi2sd(xmm29, xmm12, rax)); + TEST_INSTRUCTION("62619F382AE8" , rd_sae().vcvtsi2sd(xmm29, xmm12, rax)); + TEST_INSTRUCTION("62619F782AE8" , rz_sae().vcvtsi2sd(xmm29, xmm12, rax)); + TEST_INSTRUCTION("62419F082AE8" , vcvtsi2sd(xmm29, xmm12, r8)); + TEST_INSTRUCTION("62419F182AE8" , rn_sae().vcvtsi2sd(xmm29, xmm12, r8)); + TEST_INSTRUCTION("62419F582AE8" , ru_sae().vcvtsi2sd(xmm29, xmm12, r8)); + TEST_INSTRUCTION("62419F382AE8" , rd_sae().vcvtsi2sd(xmm29, xmm12, r8)); + TEST_INSTRUCTION("62419F782AE8" , rz_sae().vcvtsi2sd(xmm29, xmm12, r8)); + TEST_INSTRUCTION("62619F082A29" , vcvtsi2sd(xmm29, xmm12, qword_ptr(rcx))); + TEST_INSTRUCTION("62219F082AACF023010000" , vcvtsi2sd(xmm29, xmm12, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62619F082A6A7F" , vcvtsi2sd(xmm29, xmm12, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62619F082AAA00040000" , vcvtsi2sd(xmm29, xmm12, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62619F082A6A80" , vcvtsi2sd(xmm29, xmm12, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62619F082AAAF8FBFFFF" , vcvtsi2sd(xmm29, xmm12, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C52A2AF8" , vcvtsi2ss(xmm15, xmm10, eax)); + TEST_INSTRUCTION("62712E182AF8" , rn_sae().vcvtsi2ss(xmm15, xmm10, eax)); + TEST_INSTRUCTION("62712E582AF8" , ru_sae().vcvtsi2ss(xmm15, xmm10, eax)); + TEST_INSTRUCTION("62712E382AF8" , rd_sae().vcvtsi2ss(xmm15, xmm10, eax)); + TEST_INSTRUCTION("62712E782AF8" , rz_sae().vcvtsi2ss(xmm15, xmm10, eax)); + TEST_INSTRUCTION("C52A2AFD" , vcvtsi2ss(xmm15, xmm10, ebp)); + TEST_INSTRUCTION("62712E182AFD" , rn_sae().vcvtsi2ss(xmm15, xmm10, ebp)); + TEST_INSTRUCTION("62712E582AFD" , ru_sae().vcvtsi2ss(xmm15, xmm10, ebp)); + TEST_INSTRUCTION("62712E382AFD" , rd_sae().vcvtsi2ss(xmm15, xmm10, ebp)); + TEST_INSTRUCTION("62712E782AFD" , rz_sae().vcvtsi2ss(xmm15, xmm10, ebp)); + TEST_INSTRUCTION("C4412A2AFD" , vcvtsi2ss(xmm15, xmm10, r13d)); + TEST_INSTRUCTION("62512E182AFD" , rn_sae().vcvtsi2ss(xmm15, xmm10, r13d)); + TEST_INSTRUCTION("62512E582AFD" , ru_sae().vcvtsi2ss(xmm15, xmm10, r13d)); + TEST_INSTRUCTION("62512E382AFD" , rd_sae().vcvtsi2ss(xmm15, xmm10, r13d)); + TEST_INSTRUCTION("62512E782AFD" , rz_sae().vcvtsi2ss(xmm15, xmm10, r13d)); + TEST_INSTRUCTION("C52A2A39" , vcvtsi2ss(xmm15, xmm10, dword_ptr(rcx))); + TEST_INSTRUCTION("C4212A2ABCF023010000" , vcvtsi2ss(xmm15, xmm10, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C52A2ABAFC010000" , vcvtsi2ss(xmm15, xmm10, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C52A2ABA00020000" , vcvtsi2ss(xmm15, xmm10, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C52A2ABA00FEFFFF" , vcvtsi2ss(xmm15, xmm10, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C52A2ABAFCFDFFFF" , vcvtsi2ss(xmm15, xmm10, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62E1AE082AC0" , vcvtsi2ss(xmm16, xmm10, rax)); + TEST_INSTRUCTION("62E1AE182AC0" , rn_sae().vcvtsi2ss(xmm16, xmm10, rax)); + TEST_INSTRUCTION("62E1AE582AC0" , ru_sae().vcvtsi2ss(xmm16, xmm10, rax)); + TEST_INSTRUCTION("62E1AE382AC0" , rd_sae().vcvtsi2ss(xmm16, xmm10, rax)); + TEST_INSTRUCTION("62E1AE782AC0" , rz_sae().vcvtsi2ss(xmm16, xmm10, rax)); + TEST_INSTRUCTION("62C1AE082AC0" , vcvtsi2ss(xmm16, xmm10, r8)); + TEST_INSTRUCTION("62C1AE182AC0" , rn_sae().vcvtsi2ss(xmm16, xmm10, r8)); + TEST_INSTRUCTION("62C1AE582AC0" , ru_sae().vcvtsi2ss(xmm16, xmm10, r8)); + TEST_INSTRUCTION("62C1AE382AC0" , rd_sae().vcvtsi2ss(xmm16, xmm10, r8)); + TEST_INSTRUCTION("62C1AE782AC0" , rz_sae().vcvtsi2ss(xmm16, xmm10, r8)); + TEST_INSTRUCTION("62E1AE082A01" , vcvtsi2ss(xmm16, xmm10, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1AE082A84F023010000" , vcvtsi2ss(xmm16, xmm10, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1AE082A427F" , vcvtsi2ss(xmm16, xmm10, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1AE082A8200040000" , vcvtsi2ss(xmm16, xmm10, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1AE082A4280" , vcvtsi2ss(xmm16, xmm10, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1AE082A82F8FBFFFF" , vcvtsi2ss(xmm16, xmm10, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62614E085AE6" , vcvtss2sd(xmm28, xmm6, xmm6)); + TEST_INSTRUCTION("62614E0B5AE6" , k(k3).vcvtss2sd(xmm28, xmm6, xmm6)); + TEST_INSTRUCTION("62614E8B5AE6" , k(k3).z().vcvtss2sd(xmm28, xmm6, xmm6)); + TEST_INSTRUCTION("62614E185AE6" , sae().vcvtss2sd(xmm28, xmm6, xmm6)); + TEST_INSTRUCTION("62614E085A21" , vcvtss2sd(xmm28, xmm6, dword_ptr(rcx))); + TEST_INSTRUCTION("62214E085AA4F023010000" , vcvtss2sd(xmm28, xmm6, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62614E085A627F" , vcvtss2sd(xmm28, xmm6, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62614E085AA200020000" , vcvtss2sd(xmm28, xmm6, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62614E085A6280" , vcvtss2sd(xmm28, xmm6, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62614E085AA2FCFDFFFF" , vcvtss2sd(xmm28, xmm6, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B17E182DC6" , rn_sae().vcvtss2si(eax, xmm22)); + TEST_INSTRUCTION("62B17E582DC6" , ru_sae().vcvtss2si(eax, xmm22)); + TEST_INSTRUCTION("62B17E382DC6" , rd_sae().vcvtss2si(eax, xmm22)); + TEST_INSTRUCTION("62B17E782DC6" , rz_sae().vcvtss2si(eax, xmm22)); + TEST_INSTRUCTION("62B17E182DEE" , rn_sae().vcvtss2si(ebp, xmm22)); + TEST_INSTRUCTION("62B17E582DEE" , ru_sae().vcvtss2si(ebp, xmm22)); + TEST_INSTRUCTION("62B17E382DEE" , rd_sae().vcvtss2si(ebp, xmm22)); + TEST_INSTRUCTION("62B17E782DEE" , rz_sae().vcvtss2si(ebp, xmm22)); + TEST_INSTRUCTION("62317E182DEE" , rn_sae().vcvtss2si(r13d, xmm22)); + TEST_INSTRUCTION("62317E582DEE" , ru_sae().vcvtss2si(r13d, xmm22)); + TEST_INSTRUCTION("62317E382DEE" , rd_sae().vcvtss2si(r13d, xmm22)); + TEST_INSTRUCTION("62317E782DEE" , rz_sae().vcvtss2si(r13d, xmm22)); + TEST_INSTRUCTION("6291FE182DC5" , rn_sae().vcvtss2si(rax, xmm29)); + TEST_INSTRUCTION("6291FE582DC5" , ru_sae().vcvtss2si(rax, xmm29)); + TEST_INSTRUCTION("6291FE382DC5" , rd_sae().vcvtss2si(rax, xmm29)); + TEST_INSTRUCTION("6291FE782DC5" , rz_sae().vcvtss2si(rax, xmm29)); + TEST_INSTRUCTION("6211FE182DC5" , rn_sae().vcvtss2si(r8, xmm29)); + TEST_INSTRUCTION("6211FE582DC5" , ru_sae().vcvtss2si(r8, xmm29)); + TEST_INSTRUCTION("6211FE382DC5" , rd_sae().vcvtss2si(r8, xmm29)); + TEST_INSTRUCTION("6211FE782DC5" , rz_sae().vcvtss2si(r8, xmm29)); + TEST_INSTRUCTION("6241FD48E6D9" , vcvttpd2dq(ymm27, zmm9)); + TEST_INSTRUCTION("6241FD4DE6D9" , k(k5).vcvttpd2dq(ymm27, zmm9)); + TEST_INSTRUCTION("6241FDCDE6D9" , k(k5).z().vcvttpd2dq(ymm27, zmm9)); + TEST_INSTRUCTION("6241FD18E6D9" , sae().vcvttpd2dq(ymm27, zmm9)); + TEST_INSTRUCTION("6261FD48E619" , vcvttpd2dq(ymm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221FD48E69CF023010000" , vcvttpd2dq(ymm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261FD58E619" , vcvttpd2dq(ymm27, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261FD48E65A7F" , vcvttpd2dq(ymm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261FD48E69A00200000" , vcvttpd2dq(ymm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261FD48E65A80" , vcvttpd2dq(ymm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261FD48E69AC0DFFFFF" , vcvttpd2dq(ymm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261FD58E65A7F" , vcvttpd2dq(ymm27, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261FD58E69A00040000" , vcvttpd2dq(ymm27, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261FD58E65A80" , vcvttpd2dq(ymm27, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261FD58E69AF8FBFFFF" , vcvttpd2dq(ymm27, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62117E485BF1" , vcvttps2dq(zmm14, zmm25)); + TEST_INSTRUCTION("62117E4B5BF1" , k(k3).vcvttps2dq(zmm14, zmm25)); + TEST_INSTRUCTION("62117ECB5BF1" , k(k3).z().vcvttps2dq(zmm14, zmm25)); + TEST_INSTRUCTION("62117E185BF1" , sae().vcvttps2dq(zmm14, zmm25)); + TEST_INSTRUCTION("62717E485B31" , vcvttps2dq(zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62317E485BB4F023010000" , vcvttps2dq(zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717E585B31" , vcvttps2dq(zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62717E485B727F" , vcvttps2dq(zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62717E485BB200200000" , vcvttps2dq(zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62717E485B7280" , vcvttps2dq(zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62717E485BB2C0DFFFFF" , vcvttps2dq(zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62717E585B727F" , vcvttps2dq(zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62717E585BB200020000" , vcvttps2dq(zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62717E585B7280" , vcvttps2dq(zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62717E585BB2FCFDFFFF" , vcvttps2dq(zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F17F182CC3" , sae().vcvttsd2si(eax, xmm3)); + TEST_INSTRUCTION("62F17F182CEB" , sae().vcvttsd2si(ebp, xmm3)); + TEST_INSTRUCTION("62717F182CEB" , sae().vcvttsd2si(r13d, xmm3)); + TEST_INSTRUCTION("62F1FF182CC1" , sae().vcvttsd2si(rax, xmm1)); + TEST_INSTRUCTION("6271FF182CC1" , sae().vcvttsd2si(r8, xmm1)); + TEST_INSTRUCTION("62D17E182CC6" , sae().vcvttss2si(eax, xmm14)); + TEST_INSTRUCTION("62D17E182CEE" , sae().vcvttss2si(ebp, xmm14)); + TEST_INSTRUCTION("62517E182CEE" , sae().vcvttss2si(r13d, xmm14)); + TEST_INSTRUCTION("62B1FE182CC5" , sae().vcvttss2si(rax, xmm21)); + TEST_INSTRUCTION("6231FE182CC5" , sae().vcvttss2si(r8, xmm21)); + TEST_INSTRUCTION("62C17E487AD6" , vcvtudq2pd(zmm18, ymm14)); + TEST_INSTRUCTION("62C17E4B7AD6" , k(k3).vcvtudq2pd(zmm18, ymm14)); + TEST_INSTRUCTION("62C17ECB7AD6" , k(k3).z().vcvtudq2pd(zmm18, ymm14)); + TEST_INSTRUCTION("62E17E487A11" , vcvtudq2pd(zmm18, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62A17E487A94F023010000" , vcvtudq2pd(zmm18, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17E587A11" , vcvtudq2pd(zmm18, dword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E17E487A527F" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62E17E487A9200100000" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62E17E487A5280" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62E17E487A92E0EFFFFF" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62E17E587A527F" , vcvtudq2pd(zmm18, dword_ptr(rdx, 508)._1to8())); + TEST_INSTRUCTION("62E17E587A9200020000" , vcvtudq2pd(zmm18, dword_ptr(rdx, 512)._1to8())); + TEST_INSTRUCTION("62E17E587A5280" , vcvtudq2pd(zmm18, dword_ptr(rdx, -512)._1to8())); + TEST_INSTRUCTION("62E17E587A92FCFDFFFF" , vcvtudq2pd(zmm18, dword_ptr(rdx, -516)._1to8())); + TEST_INSTRUCTION("62E17F487AD7" , vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17F4A7AD7" , k(k2).vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17FCA7AD7" , k(k2).z().vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17F187AD7" , rn_sae().vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17F587AD7" , ru_sae().vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17F387AD7" , rd_sae().vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17F787AD7" , rz_sae().vcvtudq2ps(zmm18, zmm7)); + TEST_INSTRUCTION("62E17F487A11" , vcvtudq2ps(zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17F487A94F023010000" , vcvtudq2ps(zmm18, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17F587A11" , vcvtudq2ps(zmm18, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E17F487A527F" , vcvtudq2ps(zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17F487A9200200000" , vcvtudq2ps(zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17F487A5280" , vcvtudq2ps(zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17F487A92C0DFFFFF" , vcvtudq2ps(zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E17F587A527F" , vcvtudq2ps(zmm18, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E17F587A9200020000" , vcvtudq2ps(zmm18, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E17F587A5280" , vcvtudq2ps(zmm18, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E17F587A92FCFDFFFF" , vcvtudq2ps(zmm18, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C1CD485ED3" , vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62C1CD4C5ED3" , k(k4).vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62C1CDCC5ED3" , k(k4).z().vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62C1CD185ED3" , rn_sae().vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62C1CD585ED3" , ru_sae().vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62C1CD385ED3" , rd_sae().vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62C1CD785ED3" , rz_sae().vdivpd(zmm18, zmm6, zmm11)); + TEST_INSTRUCTION("62E1CD485E11" , vdivpd(zmm18, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1CD485E94F023010000" , vdivpd(zmm18, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1CD585E11" , vdivpd(zmm18, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1CD485E527F" , vdivpd(zmm18, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1CD485E9200200000" , vdivpd(zmm18, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1CD485E5280" , vdivpd(zmm18, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1CD485E92C0DFFFFF" , vdivpd(zmm18, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1CD585E527F" , vdivpd(zmm18, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1CD585E9200040000" , vdivpd(zmm18, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1CD585E5280" , vdivpd(zmm18, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1CD585E92F8FBFFFF" , vdivpd(zmm18, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("628144405EFC" , vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("628144425EFC" , k(k2).vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("628144C25EFC" , k(k2).z().vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("628144105EFC" , rn_sae().vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("628144505EFC" , ru_sae().vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("628144305EFC" , rd_sae().vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("628144705EFC" , rz_sae().vdivps(zmm23, zmm23, zmm28)); + TEST_INSTRUCTION("62E144405E39" , vdivps(zmm23, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A144405EBCF023010000" , vdivps(zmm23, zmm23, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E144505E39" , vdivps(zmm23, zmm23, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E144405E7A7F" , vdivps(zmm23, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E144405EBA00200000" , vdivps(zmm23, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E144405E7A80" , vdivps(zmm23, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E144405EBAC0DFFFFF" , vdivps(zmm23, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E144505E7A7F" , vdivps(zmm23, zmm23, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E144505EBA00020000" , vdivps(zmm23, zmm23, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E144505E7A80" , vdivps(zmm23, zmm23, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E144505EBAFCFDFFFF" , vdivps(zmm23, zmm23, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("622197085EEE" , vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("6221970B5EEE" , k(k3).vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("6221978B5EEE" , k(k3).z().vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("622197185EEE" , rn_sae().vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("622197585EEE" , ru_sae().vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("622197385EEE" , rd_sae().vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("622197785EEE" , rz_sae().vdivsd(xmm29, xmm13, xmm22)); + TEST_INSTRUCTION("626197085E29" , vdivsd(xmm29, xmm13, qword_ptr(rcx))); + TEST_INSTRUCTION("622197085EACF023010000" , vdivsd(xmm29, xmm13, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626197085E6A7F" , vdivsd(xmm29, xmm13, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("626197085EAA00040000" , vdivsd(xmm29, xmm13, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("626197085E6A80" , vdivsd(xmm29, xmm13, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("626197085EAAF8FBFFFF" , vdivsd(xmm29, xmm13, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62A14E085EE9" , vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62A14E0D5EE9" , k(k5).vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62A14E8D5EE9" , k(k5).z().vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62A14E185EE9" , rn_sae().vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62A14E585EE9" , ru_sae().vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62A14E385EE9" , rd_sae().vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62A14E785EE9" , rz_sae().vdivss(xmm21, xmm6, xmm17)); + TEST_INSTRUCTION("62E14E085E29" , vdivss(xmm21, xmm6, dword_ptr(rcx))); + TEST_INSTRUCTION("62A14E085EACF023010000" , vdivss(xmm21, xmm6, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E14E085E6A7F" , vdivss(xmm21, xmm6, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E14E085EAA00020000" , vdivss(xmm21, xmm6, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E14E085E6A80" , vdivss(xmm21, xmm6, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E14E085EAAFCFDFFFF" , vdivss(xmm21, xmm6, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6262FD488801" , vexpandpd(zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6262FD4C8801" , k(k4).vexpandpd(zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6262FDCC8801" , k(k4).z().vexpandpd(zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222FD488884F023010000" , vexpandpd(zmm24, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262FD4888427F" , vexpandpd(zmm24, zmmword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262FD48888200040000" , vexpandpd(zmm24, zmmword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262FD48884280" , vexpandpd(zmm24, zmmword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262FD488882F8FBFFFF" , vexpandpd(zmm24, zmmword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62C2FD4888FF" , vexpandpd(zmm23, zmm15)); + TEST_INSTRUCTION("62C2FD4D88FF" , k(k5).vexpandpd(zmm23, zmm15)); + TEST_INSTRUCTION("62C2FDCD88FF" , k(k5).z().vexpandpd(zmm23, zmm15)); + TEST_INSTRUCTION("62F27D488821" , vexpandps(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27D4E8821" , k(k6).vexpandps(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27DCE8821" , k(k6).z().vexpandps(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D4888A4F023010000" , vexpandps(zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D4888627F" , vexpandps(zmm4, zmmword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F27D4888A200020000" , vexpandps(zmm4, zmmword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F27D48886280" , vexpandps(zmm4, zmmword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F27D4888A2FCFDFFFF" , vexpandps(zmm4, zmmword_ptr(rdx, -516))); + TEST_INSTRUCTION("62527D4888F1" , vexpandps(zmm14, zmm9)); + TEST_INSTRUCTION("62527D4A88F1" , k(k2).vexpandps(zmm14, zmm9)); + TEST_INSTRUCTION("62527DCA88F1" , k(k2).z().vexpandps(zmm14, zmm9)); + TEST_INSTRUCTION("62C37D4819EFAB" , vextractf32x4(xmm15, zmm21, 171)); + TEST_INSTRUCTION("62C37D4919EFAB" , k(k1).vextractf32x4(xmm15, zmm21, 171)); + TEST_INSTRUCTION("62C37DC919EFAB" , k(k1).z().vextractf32x4(xmm15, zmm21, 171)); + TEST_INSTRUCTION("62C37D4819EF7B" , vextractf32x4(xmm15, zmm21, 123)); + TEST_INSTRUCTION("6243FD481BC3AB" , vextractf64x4(ymm11, zmm24, 171)); + TEST_INSTRUCTION("6243FD4D1BC3AB" , k(k5).vextractf64x4(ymm11, zmm24, 171)); + TEST_INSTRUCTION("6243FDCD1BC3AB" , k(k5).z().vextractf64x4(ymm11, zmm24, 171)); + TEST_INSTRUCTION("6243FD481BC37B" , vextractf64x4(ymm11, zmm24, 123)); + TEST_INSTRUCTION("62C37D4839C5AB" , vextracti32x4(xmm13, zmm16, 171)); + TEST_INSTRUCTION("62C37D4D39C5AB" , k(k5).vextracti32x4(xmm13, zmm16, 171)); + TEST_INSTRUCTION("62C37DCD39C5AB" , k(k5).z().vextracti32x4(xmm13, zmm16, 171)); + TEST_INSTRUCTION("62C37D4839C57B" , vextracti32x4(xmm13, zmm16, 123)); + TEST_INSTRUCTION("62C3FD483BC5AB" , vextracti64x4(ymm13, zmm16, 171)); + TEST_INSTRUCTION("62C3FD4B3BC5AB" , k(k3).vextracti64x4(ymm13, zmm16, 171)); + TEST_INSTRUCTION("62C3FDCB3BC5AB" , k(k3).z().vextracti64x4(ymm13, zmm16, 171)); + TEST_INSTRUCTION("62C3FD483BC57B" , vextracti64x4(ymm13, zmm16, 123)); + TEST_INSTRUCTION("62637D0817C0AB" , vextractps(eax, xmm24, 171)); + TEST_INSTRUCTION("62637D0817C07B" , vextractps(eax, xmm24, 123)); + TEST_INSTRUCTION("62437D0817C07B" , vextractps(r8d, xmm24, 123)); + TEST_INSTRUCTION("62637D0817017B" , vextractps(dword_ptr(rcx), xmm24, 123)); + TEST_INSTRUCTION("62237D081784F0230100007B" , vextractps(dword_ptr(rax, r14, 3, 291), xmm24, 123)); + TEST_INSTRUCTION("62637D0817427F7B" , vextractps(dword_ptr(rdx, 508), xmm24, 123)); + TEST_INSTRUCTION("62637D081782000200007B" , vextractps(dword_ptr(rdx, 512), xmm24, 123)); + TEST_INSTRUCTION("62637D081742807B" , vextractps(dword_ptr(rdx, -512), xmm24, 123)); + TEST_INSTRUCTION("62637D081782FCFDFFFF7B" , vextractps(dword_ptr(rdx, -516), xmm24, 123)); + TEST_INSTRUCTION("6222FD4098D5" , vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6222FD4598D5" , k(k5).vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6222FDC598D5" , k(k5).z().vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6222FD1098D5" , rn_sae().vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6222FD5098D5" , ru_sae().vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6222FD3098D5" , rd_sae().vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6222FD7098D5" , rz_sae().vfmadd132pd(zmm26, zmm16, zmm21)); + TEST_INSTRUCTION("6262FD409811" , vfmadd132pd(zmm26, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222FD409894F023010000" , vfmadd132pd(zmm26, zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262FD509811" , vfmadd132pd(zmm26, zmm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262FD4098527F" , vfmadd132pd(zmm26, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262FD40989200200000" , vfmadd132pd(zmm26, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262FD40985280" , vfmadd132pd(zmm26, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262FD409892C0DFFFFF" , vfmadd132pd(zmm26, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262FD5098527F" , vfmadd132pd(zmm26, zmm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262FD50989200040000" , vfmadd132pd(zmm26, zmm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262FD50985280" , vfmadd132pd(zmm26, zmm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262FD509892F8FBFFFF" , vfmadd132pd(zmm26, zmm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62925D4098C9" , vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62925D4198C9" , k(k1).vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62925DC198C9" , k(k1).z().vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62925D1098C9" , rn_sae().vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62925D5098C9" , ru_sae().vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62925D3098C9" , rd_sae().vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62925D7098C9" , rz_sae().vfmadd132ps(zmm1, zmm20, zmm25)); + TEST_INSTRUCTION("62F25D409809" , vfmadd132ps(zmm1, zmm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B25D40988CF023010000" , vfmadd132ps(zmm1, zmm20, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F25D509809" , vfmadd132ps(zmm1, zmm20, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F25D40984A7F" , vfmadd132ps(zmm1, zmm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F25D40988A00200000" , vfmadd132ps(zmm1, zmm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F25D40984A80" , vfmadd132ps(zmm1, zmm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F25D40988AC0DFFFFF" , vfmadd132ps(zmm1, zmm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F25D50984A7F" , vfmadd132ps(zmm1, zmm20, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F25D50988A00020000" , vfmadd132ps(zmm1, zmm20, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F25D50984A80" , vfmadd132ps(zmm1, zmm20, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F25D50988AFCFDFFFF" , vfmadd132ps(zmm1, zmm20, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6262F50099E3" , vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F50299E3" , k(k2).vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F58299E3" , k(k2).z().vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F51099E3" , rn_sae().vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F55099E3" , ru_sae().vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F53099E3" , rd_sae().vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F57099E3" , rz_sae().vfmadd132sd(xmm28, xmm17, xmm3)); + TEST_INSTRUCTION("6262F5009921" , vfmadd132sd(xmm28, xmm17, qword_ptr(rcx))); + TEST_INSTRUCTION("6222F50099A4F023010000" , vfmadd132sd(xmm28, xmm17, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262F50099627F" , vfmadd132sd(xmm28, xmm17, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262F50099A200040000" , vfmadd132sd(xmm28, xmm17, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262F500996280" , vfmadd132sd(xmm28, xmm17, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262F50099A2F8FBFFFF" , vfmadd132sd(xmm28, xmm17, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6222750099F6" , vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("6222750399F6" , k(k3).vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("6222758399F6" , k(k3).z().vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("6222751099F6" , rn_sae().vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("6222755099F6" , ru_sae().vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("6222753099F6" , rd_sae().vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("6222757099F6" , rz_sae().vfmadd132ss(xmm30, xmm17, xmm22)); + TEST_INSTRUCTION("626275009931" , vfmadd132ss(xmm30, xmm17, dword_ptr(rcx))); + TEST_INSTRUCTION("6222750099B4F023010000" , vfmadd132ss(xmm30, xmm17, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262750099727F" , vfmadd132ss(xmm30, xmm17, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("6262750099B200020000" , vfmadd132ss(xmm30, xmm17, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62627500997280" , vfmadd132ss(xmm30, xmm17, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("6262750099B2FCFDFFFF" , vfmadd132ss(xmm30, xmm17, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6282FD40A8D1" , vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("6282FD43A8D1" , k(k3).vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("6282FDC3A8D1" , k(k3).z().vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("6282FD10A8D1" , rn_sae().vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("6282FD50A8D1" , ru_sae().vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("6282FD30A8D1" , rd_sae().vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("6282FD70A8D1" , rz_sae().vfmadd213pd(zmm18, zmm16, zmm25)); + TEST_INSTRUCTION("62E2FD40A811" , vfmadd213pd(zmm18, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2FD40A894F023010000" , vfmadd213pd(zmm18, zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2FD50A811" , vfmadd213pd(zmm18, zmm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2FD40A8527F" , vfmadd213pd(zmm18, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2FD40A89200200000" , vfmadd213pd(zmm18, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2FD40A85280" , vfmadd213pd(zmm18, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2FD40A892C0DFFFFF" , vfmadd213pd(zmm18, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2FD50A8527F" , vfmadd213pd(zmm18, zmm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2FD50A89200040000" , vfmadd213pd(zmm18, zmm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2FD50A85280" , vfmadd213pd(zmm18, zmm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2FD50A892F8FBFFFF" , vfmadd213pd(zmm18, zmm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C26540A8E6" , vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62C26544A8E6" , k(k4).vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62C265C4A8E6" , k(k4).z().vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62C26510A8E6" , rn_sae().vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62C26550A8E6" , ru_sae().vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62C26530A8E6" , rd_sae().vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62C26570A8E6" , rz_sae().vfmadd213ps(zmm20, zmm19, zmm14)); + TEST_INSTRUCTION("62E26540A821" , vfmadd213ps(zmm20, zmm19, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A26540A8A4F023010000" , vfmadd213ps(zmm20, zmm19, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E26550A821" , vfmadd213ps(zmm20, zmm19, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E26540A8627F" , vfmadd213ps(zmm20, zmm19, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E26540A8A200200000" , vfmadd213ps(zmm20, zmm19, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E26540A86280" , vfmadd213ps(zmm20, zmm19, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E26540A8A2C0DFFFFF" , vfmadd213ps(zmm20, zmm19, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E26550A8627F" , vfmadd213ps(zmm20, zmm19, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E26550A8A200020000" , vfmadd213ps(zmm20, zmm19, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E26550A86280" , vfmadd213ps(zmm20, zmm19, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E26550A8A2FCFDFFFF" , vfmadd213ps(zmm20, zmm19, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6242AD00A9C5" , vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6242AD03A9C5" , k(k3).vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6242AD83A9C5" , k(k3).z().vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6242AD10A9C5" , rn_sae().vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6242AD50A9C5" , ru_sae().vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6242AD30A9C5" , rd_sae().vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6242AD70A9C5" , rz_sae().vfmadd213sd(xmm24, xmm26, xmm13)); + TEST_INSTRUCTION("6262AD00A901" , vfmadd213sd(xmm24, xmm26, qword_ptr(rcx))); + TEST_INSTRUCTION("6222AD00A984F023010000" , vfmadd213sd(xmm24, xmm26, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262AD00A9427F" , vfmadd213sd(xmm24, xmm26, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262AD00A98200040000" , vfmadd213sd(xmm24, xmm26, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262AD00A94280" , vfmadd213sd(xmm24, xmm26, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262AD00A982F8FBFFFF" , vfmadd213sd(xmm24, xmm26, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62224D00A9F0" , vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62224D01A9F0" , k(k1).vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62224D81A9F0" , k(k1).z().vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62224D10A9F0" , rn_sae().vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62224D50A9F0" , ru_sae().vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62224D30A9F0" , rd_sae().vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62224D70A9F0" , rz_sae().vfmadd213ss(xmm30, xmm22, xmm16)); + TEST_INSTRUCTION("62624D00A931" , vfmadd213ss(xmm30, xmm22, dword_ptr(rcx))); + TEST_INSTRUCTION("62224D00A9B4F023010000" , vfmadd213ss(xmm30, xmm22, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62624D00A9727F" , vfmadd213ss(xmm30, xmm22, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62624D00A9B200020000" , vfmadd213ss(xmm30, xmm22, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62624D00A97280" , vfmadd213ss(xmm30, xmm22, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62624D00A9B2FCFDFFFF" , vfmadd213ss(xmm30, xmm22, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6242CD48B8F1" , vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6242CD4CB8F1" , k(k4).vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6242CDCCB8F1" , k(k4).z().vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6242CD18B8F1" , rn_sae().vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6242CD58B8F1" , ru_sae().vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6242CD38B8F1" , rd_sae().vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6242CD78B8F1" , rz_sae().vfmadd231pd(zmm30, zmm6, zmm9)); + TEST_INSTRUCTION("6262CD48B831" , vfmadd231pd(zmm30, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222CD48B8B4F023010000" , vfmadd231pd(zmm30, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262CD58B831" , vfmadd231pd(zmm30, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262CD48B8727F" , vfmadd231pd(zmm30, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262CD48B8B200200000" , vfmadd231pd(zmm30, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262CD48B87280" , vfmadd231pd(zmm30, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262CD48B8B2C0DFFFFF" , vfmadd231pd(zmm30, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262CD58B8727F" , vfmadd231pd(zmm30, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262CD58B8B200040000" , vfmadd231pd(zmm30, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262CD58B87280" , vfmadd231pd(zmm30, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262CD58B8B2F8FBFFFF" , vfmadd231pd(zmm30, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62021D40B8D9" , vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62021D43B8D9" , k(k3).vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62021DC3B8D9" , k(k3).z().vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62021D10B8D9" , rn_sae().vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62021D50B8D9" , ru_sae().vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62021D30B8D9" , rd_sae().vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62021D70B8D9" , rz_sae().vfmadd231ps(zmm27, zmm28, zmm25)); + TEST_INSTRUCTION("62621D40B819" , vfmadd231ps(zmm27, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62221D40B89CF023010000" , vfmadd231ps(zmm27, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62621D50B819" , vfmadd231ps(zmm27, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62621D40B85A7F" , vfmadd231ps(zmm27, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62621D40B89A00200000" , vfmadd231ps(zmm27, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62621D40B85A80" , vfmadd231ps(zmm27, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62621D40B89AC0DFFFFF" , vfmadd231ps(zmm27, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62621D50B85A7F" , vfmadd231ps(zmm27, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62621D50B89A00020000" , vfmadd231ps(zmm27, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62621D50B85A80" , vfmadd231ps(zmm27, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62621D50B89AFCFDFFFF" , vfmadd231ps(zmm27, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C4C2F1B9E6" , vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("62D2F509B9E6" , k(k1).vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("62D2F589B9E6" , k(k1).z().vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("62D2F518B9E6" , rn_sae().vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("62D2F558B9E6" , ru_sae().vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("62D2F538B9E6" , rd_sae().vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("62D2F578B9E6" , rz_sae().vfmadd231sd(xmm4, xmm1, xmm14)); + TEST_INSTRUCTION("C4E2F1B921" , vfmadd231sd(xmm4, xmm1, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A2F1B9A4F023010000" , vfmadd231sd(xmm4, xmm1, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C4E2F1B9A2F8030000" , vfmadd231sd(xmm4, xmm1, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E2F1B9A200040000" , vfmadd231sd(xmm4, xmm1, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E2F1B9A200FCFFFF" , vfmadd231sd(xmm4, xmm1, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E2F1B9A2F8FBFFFF" , vfmadd231sd(xmm4, xmm1, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62420508B9EA" , vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("6242050CB9EA" , k(k4).vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("6242058CB9EA" , k(k4).z().vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("62420518B9EA" , rn_sae().vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("62420558B9EA" , ru_sae().vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("62420538B9EA" , rd_sae().vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("62420578B9EA" , rz_sae().vfmadd231ss(xmm29, xmm15, xmm10)); + TEST_INSTRUCTION("62620508B929" , vfmadd231ss(xmm29, xmm15, dword_ptr(rcx))); + TEST_INSTRUCTION("62220508B9ACF023010000" , vfmadd231ss(xmm29, xmm15, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62620508B96A7F" , vfmadd231ss(xmm29, xmm15, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62620508B9AA00020000" , vfmadd231ss(xmm29, xmm15, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62620508B96A80" , vfmadd231ss(xmm29, xmm15, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62620508B9AAFCFDFFFF" , vfmadd231ss(xmm29, xmm15, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62A2B54096E5" , vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62A2B54296E5" , k(k2).vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62A2B5C296E5" , k(k2).z().vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62A2B51096E5" , rn_sae().vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62A2B55096E5" , ru_sae().vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62A2B53096E5" , rd_sae().vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62A2B57096E5" , rz_sae().vfmaddsub132pd(zmm20, zmm25, zmm21)); + TEST_INSTRUCTION("62E2B5409621" , vfmaddsub132pd(zmm20, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2B54096A4F023010000" , vfmaddsub132pd(zmm20, zmm25, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2B5509621" , vfmaddsub132pd(zmm20, zmm25, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2B54096627F" , vfmaddsub132pd(zmm20, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2B54096A200200000" , vfmaddsub132pd(zmm20, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2B540966280" , vfmaddsub132pd(zmm20, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2B54096A2C0DFFFFF" , vfmaddsub132pd(zmm20, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2B55096627F" , vfmaddsub132pd(zmm20, zmm25, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2B55096A200040000" , vfmaddsub132pd(zmm20, zmm25, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2B550966280" , vfmaddsub132pd(zmm20, zmm25, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2B55096A2F8FBFFFF" , vfmaddsub132pd(zmm20, zmm25, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6232354896D4" , vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("6232354B96D4" , k(k3).vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("623235CB96D4" , k(k3).z().vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("6232351896D4" , rn_sae().vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("6232355896D4" , ru_sae().vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("6232353896D4" , rd_sae().vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("6232357896D4" , rz_sae().vfmaddsub132ps(zmm10, zmm9, zmm20)); + TEST_INSTRUCTION("627235489611" , vfmaddsub132ps(zmm10, zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("623235489694F023010000" , vfmaddsub132ps(zmm10, zmm9, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("627235589611" , vfmaddsub132ps(zmm10, zmm9, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("6272354896527F" , vfmaddsub132ps(zmm10, zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62723548969200200000" , vfmaddsub132ps(zmm10, zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62723548965280" , vfmaddsub132ps(zmm10, zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("627235489692C0DFFFFF" , vfmaddsub132ps(zmm10, zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272355896527F" , vfmaddsub132ps(zmm10, zmm9, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62723558969200020000" , vfmaddsub132ps(zmm10, zmm9, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62723558965280" , vfmaddsub132ps(zmm10, zmm9, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("627235589692FCFDFFFF" , vfmaddsub132ps(zmm10, zmm9, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6242CD48A6D2" , vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6242CD4EA6D2" , k(k6).vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6242CDCEA6D2" , k(k6).z().vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6242CD18A6D2" , rn_sae().vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6242CD58A6D2" , ru_sae().vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6242CD38A6D2" , rd_sae().vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6242CD78A6D2" , rz_sae().vfmaddsub213pd(zmm26, zmm6, zmm10)); + TEST_INSTRUCTION("6262CD48A611" , vfmaddsub213pd(zmm26, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222CD48A694F023010000" , vfmaddsub213pd(zmm26, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262CD58A611" , vfmaddsub213pd(zmm26, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262CD48A6527F" , vfmaddsub213pd(zmm26, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262CD48A69200200000" , vfmaddsub213pd(zmm26, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262CD48A65280" , vfmaddsub213pd(zmm26, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262CD48A692C0DFFFFF" , vfmaddsub213pd(zmm26, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262CD58A6527F" , vfmaddsub213pd(zmm26, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262CD58A69200040000" , vfmaddsub213pd(zmm26, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262CD58A65280" , vfmaddsub213pd(zmm26, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262CD58A692F8FBFFFF" , vfmaddsub213pd(zmm26, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62823D40A6CC" , vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62823D46A6CC" , k(k6).vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62823DC6A6CC" , k(k6).z().vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62823D10A6CC" , rn_sae().vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62823D50A6CC" , ru_sae().vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62823D30A6CC" , rd_sae().vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62823D70A6CC" , rz_sae().vfmaddsub213ps(zmm17, zmm24, zmm28)); + TEST_INSTRUCTION("62E23D40A609" , vfmaddsub213ps(zmm17, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A23D40A68CF023010000" , vfmaddsub213ps(zmm17, zmm24, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E23D50A609" , vfmaddsub213ps(zmm17, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E23D40A64A7F" , vfmaddsub213ps(zmm17, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E23D40A68A00200000" , vfmaddsub213ps(zmm17, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E23D40A64A80" , vfmaddsub213ps(zmm17, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E23D40A68AC0DFFFFF" , vfmaddsub213ps(zmm17, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E23D50A64A7F" , vfmaddsub213ps(zmm17, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E23D50A68A00020000" , vfmaddsub213ps(zmm17, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E23D50A64A80" , vfmaddsub213ps(zmm17, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E23D50A68AFCFDFFFF" , vfmaddsub213ps(zmm17, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6212A540B6C8" , vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6212A547B6C8" , k(k7).vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6212A5C7B6C8" , k(k7).z().vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6212A510B6C8" , rn_sae().vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6212A550B6C8" , ru_sae().vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6212A530B6C8" , rd_sae().vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6212A570B6C8" , rz_sae().vfmaddsub231pd(zmm9, zmm27, zmm24)); + TEST_INSTRUCTION("6272A540B609" , vfmaddsub231pd(zmm9, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232A540B68CF023010000" , vfmaddsub231pd(zmm9, zmm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272A550B609" , vfmaddsub231pd(zmm9, zmm27, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272A540B64A7F" , vfmaddsub231pd(zmm9, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272A540B68A00200000" , vfmaddsub231pd(zmm9, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272A540B64A80" , vfmaddsub231pd(zmm9, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272A540B68AC0DFFFFF" , vfmaddsub231pd(zmm9, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272A550B64A7F" , vfmaddsub231pd(zmm9, zmm27, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272A550B68A00040000" , vfmaddsub231pd(zmm9, zmm27, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272A550B64A80" , vfmaddsub231pd(zmm9, zmm27, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272A550B68AF8FBFFFF" , vfmaddsub231pd(zmm9, zmm27, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62325540B6FB" , vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("62325546B6FB" , k(k6).vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("623255C6B6FB" , k(k6).z().vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("62325510B6FB" , rn_sae().vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("62325550B6FB" , ru_sae().vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("62325530B6FB" , rd_sae().vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("62325570B6FB" , rz_sae().vfmaddsub231ps(zmm15, zmm21, zmm19)); + TEST_INSTRUCTION("62725540B639" , vfmaddsub231ps(zmm15, zmm21, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62325540B6BCF023010000" , vfmaddsub231ps(zmm15, zmm21, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62725550B639" , vfmaddsub231ps(zmm15, zmm21, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62725540B67A7F" , vfmaddsub231ps(zmm15, zmm21, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62725540B6BA00200000" , vfmaddsub231ps(zmm15, zmm21, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62725540B67A80" , vfmaddsub231ps(zmm15, zmm21, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62725540B6BAC0DFFFFF" , vfmaddsub231ps(zmm15, zmm21, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62725550B67A7F" , vfmaddsub231ps(zmm15, zmm21, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62725550B6BA00020000" , vfmaddsub231ps(zmm15, zmm21, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62725550B67A80" , vfmaddsub231ps(zmm15, zmm21, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62725550B6BAFCFDFFFF" , vfmaddsub231ps(zmm15, zmm21, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62829D489AF3" , vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62829D4A9AF3" , k(k2).vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62829DCA9AF3" , k(k2).z().vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62829D189AF3" , rn_sae().vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62829D589AF3" , ru_sae().vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62829D389AF3" , rd_sae().vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62829D789AF3" , rz_sae().vfmsub132pd(zmm22, zmm12, zmm27)); + TEST_INSTRUCTION("62E29D489A31" , vfmsub132pd(zmm22, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A29D489AB4F023010000" , vfmsub132pd(zmm22, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E29D589A31" , vfmsub132pd(zmm22, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E29D489A727F" , vfmsub132pd(zmm22, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E29D489AB200200000" , vfmsub132pd(zmm22, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E29D489A7280" , vfmsub132pd(zmm22, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E29D489AB2C0DFFFFF" , vfmsub132pd(zmm22, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E29D589A727F" , vfmsub132pd(zmm22, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E29D589AB200040000" , vfmsub132pd(zmm22, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E29D589A7280" , vfmsub132pd(zmm22, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E29D589AB2F8FBFFFF" , vfmsub132pd(zmm22, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B215489AC8" , vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62B2154C9AC8" , k(k4).vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62B215CC9AC8" , k(k4).z().vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62B215189AC8" , rn_sae().vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62B215589AC8" , ru_sae().vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62B215389AC8" , rd_sae().vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62B215789AC8" , rz_sae().vfmsub132ps(zmm1, zmm13, zmm16)); + TEST_INSTRUCTION("62F215489A09" , vfmsub132ps(zmm1, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B215489A8CF023010000" , vfmsub132ps(zmm1, zmm13, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F215589A09" , vfmsub132ps(zmm1, zmm13, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F215489A4A7F" , vfmsub132ps(zmm1, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F215489A8A00200000" , vfmsub132ps(zmm1, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F215489A4A80" , vfmsub132ps(zmm1, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F215489A8AC0DFFFFF" , vfmsub132ps(zmm1, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F215589A4A7F" , vfmsub132ps(zmm1, zmm13, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F215589A8A00020000" , vfmsub132ps(zmm1, zmm13, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F215589A4A80" , vfmsub132ps(zmm1, zmm13, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F215589A8AFCFDFFFF" , vfmsub132ps(zmm1, zmm13, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6212BD089BE3" , vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("6212BD0B9BE3" , k(k3).vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("6212BD8B9BE3" , k(k3).z().vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("6212BD189BE3" , rn_sae().vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("6212BD589BE3" , ru_sae().vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("6212BD389BE3" , rd_sae().vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("6212BD789BE3" , rz_sae().vfmsub132sd(xmm12, xmm8, xmm27)); + TEST_INSTRUCTION("C462B99B21" , vfmsub132sd(xmm12, xmm8, qword_ptr(rcx))); + TEST_INSTRUCTION("C422B99BA4F023010000" , vfmsub132sd(xmm12, xmm8, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C462B99BA2F8030000" , vfmsub132sd(xmm12, xmm8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C462B99BA200040000" , vfmsub132sd(xmm12, xmm8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C462B99BA200FCFFFF" , vfmsub132sd(xmm12, xmm8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C462B99BA2F8FBFFFF" , vfmsub132sd(xmm12, xmm8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62024D009BF3" , vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62024D039BF3" , k(k3).vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62024D839BF3" , k(k3).z().vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62024D109BF3" , rn_sae().vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62024D509BF3" , ru_sae().vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62024D309BF3" , rd_sae().vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62024D709BF3" , rz_sae().vfmsub132ss(xmm30, xmm22, xmm27)); + TEST_INSTRUCTION("62624D009B31" , vfmsub132ss(xmm30, xmm22, dword_ptr(rcx))); + TEST_INSTRUCTION("62224D009BB4F023010000" , vfmsub132ss(xmm30, xmm22, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62624D009B727F" , vfmsub132ss(xmm30, xmm22, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62624D009BB200020000" , vfmsub132ss(xmm30, xmm22, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62624D009B7280" , vfmsub132ss(xmm30, xmm22, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62624D009BB2FCFDFFFF" , vfmsub132ss(xmm30, xmm22, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F2AD48AAEC" , vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2AD49AAEC" , k(k1).vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2ADC9AAEC" , k(k1).z().vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2AD18AAEC" , rn_sae().vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2AD58AAEC" , ru_sae().vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2AD38AAEC" , rd_sae().vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2AD78AAEC" , rz_sae().vfmsub213pd(zmm5, zmm10, zmm4)); + TEST_INSTRUCTION("62F2AD48AA29" , vfmsub213pd(zmm5, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2AD48AAACF023010000" , vfmsub213pd(zmm5, zmm10, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2AD58AA29" , vfmsub213pd(zmm5, zmm10, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2AD48AA6A7F" , vfmsub213pd(zmm5, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2AD48AAAA00200000" , vfmsub213pd(zmm5, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2AD48AA6A80" , vfmsub213pd(zmm5, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2AD48AAAAC0DFFFFF" , vfmsub213pd(zmm5, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2AD58AA6A7F" , vfmsub213pd(zmm5, zmm10, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2AD58AAAA00040000" , vfmsub213pd(zmm5, zmm10, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2AD58AA6A80" , vfmsub213pd(zmm5, zmm10, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2AD58AAAAF8FBFFFF" , vfmsub213pd(zmm5, zmm10, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C24D40AAF2" , vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62C24D46AAF2" , k(k6).vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62C24DC6AAF2" , k(k6).z().vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62C24D10AAF2" , rn_sae().vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62C24D50AAF2" , ru_sae().vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62C24D30AAF2" , rd_sae().vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62C24D70AAF2" , rz_sae().vfmsub213ps(zmm22, zmm22, zmm10)); + TEST_INSTRUCTION("62E24D40AA31" , vfmsub213ps(zmm22, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A24D40AAB4F023010000" , vfmsub213ps(zmm22, zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E24D50AA31" , vfmsub213ps(zmm22, zmm22, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E24D40AA727F" , vfmsub213ps(zmm22, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E24D40AAB200200000" , vfmsub213ps(zmm22, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E24D40AA7280" , vfmsub213ps(zmm22, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E24D40AAB2C0DFFFFF" , vfmsub213ps(zmm22, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E24D50AA727F" , vfmsub213ps(zmm22, zmm22, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E24D50AAB200020000" , vfmsub213ps(zmm22, zmm22, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E24D50AA7280" , vfmsub213ps(zmm22, zmm22, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E24D50AAB2FCFDFFFF" , vfmsub213ps(zmm22, zmm22, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C4C2B9ABF4" , vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("62D2BD09ABF4" , k(k1).vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("62D2BD89ABF4" , k(k1).z().vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("62D2BD18ABF4" , rn_sae().vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("62D2BD58ABF4" , ru_sae().vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("62D2BD38ABF4" , rd_sae().vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("62D2BD78ABF4" , rz_sae().vfmsub213sd(xmm6, xmm8, xmm12)); + TEST_INSTRUCTION("C4E2B9AB31" , vfmsub213sd(xmm6, xmm8, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A2B9ABB4F023010000" , vfmsub213sd(xmm6, xmm8, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C4E2B9ABB2F8030000" , vfmsub213sd(xmm6, xmm8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E2B9ABB200040000" , vfmsub213sd(xmm6, xmm8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E2B9ABB200FCFFFF" , vfmsub213sd(xmm6, xmm8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E2B9ABB2F8FBFFFF" , vfmsub213sd(xmm6, xmm8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62021508ABF2" , vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62021509ABF2" , k(k1).vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62021589ABF2" , k(k1).z().vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62021518ABF2" , rn_sae().vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62021558ABF2" , ru_sae().vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62021538ABF2" , rd_sae().vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62021578ABF2" , rz_sae().vfmsub213ss(xmm30, xmm13, xmm26)); + TEST_INSTRUCTION("62621508AB31" , vfmsub213ss(xmm30, xmm13, dword_ptr(rcx))); + TEST_INSTRUCTION("62221508ABB4F023010000" , vfmsub213ss(xmm30, xmm13, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62621508AB727F" , vfmsub213ss(xmm30, xmm13, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62621508ABB200020000" , vfmsub213ss(xmm30, xmm13, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62621508AB7280" , vfmsub213ss(xmm30, xmm13, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62621508ABB2FCFDFFFF" , vfmsub213ss(xmm30, xmm13, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62D29D48BAEB" , vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62D29D4ABAEB" , k(k2).vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62D29DCABAEB" , k(k2).z().vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62D29D18BAEB" , rn_sae().vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62D29D58BAEB" , ru_sae().vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62D29D38BAEB" , rd_sae().vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62D29D78BAEB" , rz_sae().vfmsub231pd(zmm5, zmm12, zmm11)); + TEST_INSTRUCTION("62F29D48BA29" , vfmsub231pd(zmm5, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B29D48BAACF023010000" , vfmsub231pd(zmm5, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F29D58BA29" , vfmsub231pd(zmm5, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F29D48BA6A7F" , vfmsub231pd(zmm5, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F29D48BAAA00200000" , vfmsub231pd(zmm5, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F29D48BA6A80" , vfmsub231pd(zmm5, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F29D48BAAAC0DFFFFF" , vfmsub231pd(zmm5, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F29D58BA6A7F" , vfmsub231pd(zmm5, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F29D58BAAA00040000" , vfmsub231pd(zmm5, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F29D58BA6A80" , vfmsub231pd(zmm5, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F29D58BAAAF8FBFFFF" , vfmsub231pd(zmm5, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62925540BAF3" , vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("62925543BAF3" , k(k3).vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("629255C3BAF3" , k(k3).z().vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("62925510BAF3" , rn_sae().vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("62925550BAF3" , ru_sae().vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("62925530BAF3" , rd_sae().vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("62925570BAF3" , rz_sae().vfmsub231ps(zmm6, zmm21, zmm27)); + TEST_INSTRUCTION("62F25540BA31" , vfmsub231ps(zmm6, zmm21, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B25540BAB4F023010000" , vfmsub231ps(zmm6, zmm21, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F25550BA31" , vfmsub231ps(zmm6, zmm21, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F25540BA727F" , vfmsub231ps(zmm6, zmm21, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F25540BAB200200000" , vfmsub231ps(zmm6, zmm21, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F25540BA7280" , vfmsub231ps(zmm6, zmm21, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F25540BAB2C0DFFFFF" , vfmsub231ps(zmm6, zmm21, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F25550BA727F" , vfmsub231ps(zmm6, zmm21, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F25550BAB200020000" , vfmsub231ps(zmm6, zmm21, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F25550BA7280" , vfmsub231ps(zmm6, zmm21, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F25550BAB2FCFDFFFF" , vfmsub231ps(zmm6, zmm21, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C4E2A1BBDE" , vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("62F2A50FBBDE" , k(k7).vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("62F2A58FBBDE" , k(k7).z().vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("62F2A518BBDE" , rn_sae().vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("62F2A558BBDE" , ru_sae().vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("62F2A538BBDE" , rd_sae().vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("62F2A578BBDE" , rz_sae().vfmsub231sd(xmm3, xmm11, xmm6)); + TEST_INSTRUCTION("C4E2A1BB19" , vfmsub231sd(xmm3, xmm11, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A2A1BB9CF023010000" , vfmsub231sd(xmm3, xmm11, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C4E2A1BB9AF8030000" , vfmsub231sd(xmm3, xmm11, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E2A1BB9A00040000" , vfmsub231sd(xmm3, xmm11, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E2A1BB9A00FCFFFF" , vfmsub231sd(xmm3, xmm11, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E2A1BB9AF8FBFFFF" , vfmsub231sd(xmm3, xmm11, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62626508BBED" , vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("6262650EBBED" , k(k6).vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("6262658EBBED" , k(k6).z().vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("62626518BBED" , rn_sae().vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("62626558BBED" , ru_sae().vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("62626538BBED" , rd_sae().vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("62626578BBED" , rz_sae().vfmsub231ss(xmm29, xmm3, xmm5)); + TEST_INSTRUCTION("62626508BB29" , vfmsub231ss(xmm29, xmm3, dword_ptr(rcx))); + TEST_INSTRUCTION("62226508BBACF023010000" , vfmsub231ss(xmm29, xmm3, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62626508BB6A7F" , vfmsub231ss(xmm29, xmm3, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62626508BBAA00020000" , vfmsub231ss(xmm29, xmm3, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62626508BB6A80" , vfmsub231ss(xmm29, xmm3, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62626508BBAAFCFDFFFF" , vfmsub231ss(xmm29, xmm3, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62A29D4097EA" , vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62A29D4797EA" , k(k7).vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62A29DC797EA" , k(k7).z().vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62A29D1097EA" , rn_sae().vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62A29D5097EA" , ru_sae().vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62A29D3097EA" , rd_sae().vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62A29D7097EA" , rz_sae().vfmsubadd132pd(zmm21, zmm28, zmm18)); + TEST_INSTRUCTION("62E29D409729" , vfmsubadd132pd(zmm21, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A29D4097ACF023010000" , vfmsubadd132pd(zmm21, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E29D509729" , vfmsubadd132pd(zmm21, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E29D40976A7F" , vfmsubadd132pd(zmm21, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E29D4097AA00200000" , vfmsubadd132pd(zmm21, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E29D40976A80" , vfmsubadd132pd(zmm21, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E29D4097AAC0DFFFFF" , vfmsubadd132pd(zmm21, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E29D50976A7F" , vfmsubadd132pd(zmm21, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E29D5097AA00040000" , vfmsubadd132pd(zmm21, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E29D50976A80" , vfmsubadd132pd(zmm21, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E29D5097AAF8FBFFFF" , vfmsubadd132pd(zmm21, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B2154897D5" , vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62B2154F97D5" , k(k7).vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62B215CF97D5" , k(k7).z().vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62B2151897D5" , rn_sae().vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62B2155897D5" , ru_sae().vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62B2153897D5" , rd_sae().vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62B2157897D5" , rz_sae().vfmsubadd132ps(zmm2, zmm13, zmm21)); + TEST_INSTRUCTION("62F215489711" , vfmsubadd132ps(zmm2, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B215489794F023010000" , vfmsubadd132ps(zmm2, zmm13, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F215589711" , vfmsubadd132ps(zmm2, zmm13, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F2154897527F" , vfmsubadd132ps(zmm2, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F21548979200200000" , vfmsubadd132ps(zmm2, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F21548975280" , vfmsubadd132ps(zmm2, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F215489792C0DFFFFF" , vfmsubadd132ps(zmm2, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2155897527F" , vfmsubadd132ps(zmm2, zmm13, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F21558979200020000" , vfmsubadd132ps(zmm2, zmm13, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F21558975280" , vfmsubadd132ps(zmm2, zmm13, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F215589792FCFDFFFF" , vfmsubadd132ps(zmm2, zmm13, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2C540A7D2" , vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C546A7D2" , k(k6).vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C5C6A7D2" , k(k6).z().vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C510A7D2" , rn_sae().vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C550A7D2" , ru_sae().vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C530A7D2" , rd_sae().vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C570A7D2" , rz_sae().vfmsubadd213pd(zmm2, zmm23, zmm2)); + TEST_INSTRUCTION("62F2C540A711" , vfmsubadd213pd(zmm2, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2C540A794F023010000" , vfmsubadd213pd(zmm2, zmm23, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2C550A711" , vfmsubadd213pd(zmm2, zmm23, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2C540A7527F" , vfmsubadd213pd(zmm2, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2C540A79200200000" , vfmsubadd213pd(zmm2, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2C540A75280" , vfmsubadd213pd(zmm2, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2C540A792C0DFFFFF" , vfmsubadd213pd(zmm2, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2C550A7527F" , vfmsubadd213pd(zmm2, zmm23, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2C550A79200040000" , vfmsubadd213pd(zmm2, zmm23, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2C550A75280" , vfmsubadd213pd(zmm2, zmm23, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2C550A792F8FBFFFF" , vfmsubadd213pd(zmm2, zmm23, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C21D48A7F6" , vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62C21D4EA7F6" , k(k6).vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62C21DCEA7F6" , k(k6).z().vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62C21D18A7F6" , rn_sae().vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62C21D58A7F6" , ru_sae().vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62C21D38A7F6" , rd_sae().vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62C21D78A7F6" , rz_sae().vfmsubadd213ps(zmm22, zmm12, zmm14)); + TEST_INSTRUCTION("62E21D48A731" , vfmsubadd213ps(zmm22, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A21D48A7B4F023010000" , vfmsubadd213ps(zmm22, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E21D58A731" , vfmsubadd213ps(zmm22, zmm12, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E21D48A7727F" , vfmsubadd213ps(zmm22, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E21D48A7B200200000" , vfmsubadd213ps(zmm22, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E21D48A77280" , vfmsubadd213ps(zmm22, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E21D48A7B2C0DFFFFF" , vfmsubadd213ps(zmm22, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E21D58A7727F" , vfmsubadd213ps(zmm22, zmm12, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E21D58A7B200020000" , vfmsubadd213ps(zmm22, zmm12, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E21D58A77280" , vfmsubadd213ps(zmm22, zmm12, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E21D58A7B2FCFDFFFF" , vfmsubadd213ps(zmm22, zmm12, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A2A540B7C5" , vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A542B7C5" , k(k2).vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A5C2B7C5" , k(k2).z().vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A510B7C5" , rn_sae().vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A550B7C5" , ru_sae().vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A530B7C5" , rd_sae().vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A570B7C5" , rz_sae().vfmsubadd231pd(zmm16, zmm27, zmm21)); + TEST_INSTRUCTION("62E2A540B701" , vfmsubadd231pd(zmm16, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2A540B784F023010000" , vfmsubadd231pd(zmm16, zmm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2A550B701" , vfmsubadd231pd(zmm16, zmm27, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2A540B7427F" , vfmsubadd231pd(zmm16, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2A540B78200200000" , vfmsubadd231pd(zmm16, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2A540B74280" , vfmsubadd231pd(zmm16, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2A540B782C0DFFFFF" , vfmsubadd231pd(zmm16, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2A550B7427F" , vfmsubadd231pd(zmm16, zmm27, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2A550B78200040000" , vfmsubadd231pd(zmm16, zmm27, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2A550B74280" , vfmsubadd231pd(zmm16, zmm27, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2A550B782F8FBFFFF" , vfmsubadd231pd(zmm16, zmm27, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62726540B7C1" , vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("62726542B7C1" , k(k2).vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("627265C2B7C1" , k(k2).z().vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("62726510B7C1" , rn_sae().vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("62726550B7C1" , ru_sae().vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("62726530B7C1" , rd_sae().vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("62726570B7C1" , rz_sae().vfmsubadd231ps(zmm8, zmm19, zmm1)); + TEST_INSTRUCTION("62726540B701" , vfmsubadd231ps(zmm8, zmm19, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62326540B784F023010000" , vfmsubadd231ps(zmm8, zmm19, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62726550B701" , vfmsubadd231ps(zmm8, zmm19, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62726540B7427F" , vfmsubadd231ps(zmm8, zmm19, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62726540B78200200000" , vfmsubadd231ps(zmm8, zmm19, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62726540B74280" , vfmsubadd231ps(zmm8, zmm19, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62726540B782C0DFFFFF" , vfmsubadd231ps(zmm8, zmm19, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62726550B7427F" , vfmsubadd231ps(zmm8, zmm19, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62726550B78200020000" , vfmsubadd231ps(zmm8, zmm19, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62726550B74280" , vfmsubadd231ps(zmm8, zmm19, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62726550B782FCFDFFFF" , vfmsubadd231ps(zmm8, zmm19, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62728D489CE1" , vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728D4F9CE1" , k(k7).vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728DCF9CE1" , k(k7).z().vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728D189CE1" , rn_sae().vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728D589CE1" , ru_sae().vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728D389CE1" , rd_sae().vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728D789CE1" , rz_sae().vfnmadd132pd(zmm12, zmm14, zmm1)); + TEST_INSTRUCTION("62728D489C21" , vfnmadd132pd(zmm12, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62328D489CA4F023010000" , vfnmadd132pd(zmm12, zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62728D589C21" , vfnmadd132pd(zmm12, zmm14, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62728D489C627F" , vfnmadd132pd(zmm12, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62728D489CA200200000" , vfnmadd132pd(zmm12, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62728D489C6280" , vfnmadd132pd(zmm12, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62728D489CA2C0DFFFFF" , vfnmadd132pd(zmm12, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62728D589C627F" , vfnmadd132pd(zmm12, zmm14, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62728D589CA200040000" , vfnmadd132pd(zmm12, zmm14, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62728D589C6280" , vfnmadd132pd(zmm12, zmm14, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62728D589CA2F8FBFFFF" , vfnmadd132pd(zmm12, zmm14, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C27D409CEA" , vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62C27D459CEA" , k(k5).vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62C27DC59CEA" , k(k5).z().vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62C27D109CEA" , rn_sae().vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62C27D509CEA" , ru_sae().vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62C27D309CEA" , rd_sae().vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62C27D709CEA" , rz_sae().vfnmadd132ps(zmm21, zmm16, zmm10)); + TEST_INSTRUCTION("62E27D409C29" , vfnmadd132ps(zmm21, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D409CACF023010000" , vfnmadd132ps(zmm21, zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E27D509C29" , vfnmadd132ps(zmm21, zmm16, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E27D409C6A7F" , vfnmadd132ps(zmm21, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E27D409CAA00200000" , vfnmadd132ps(zmm21, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E27D409C6A80" , vfnmadd132ps(zmm21, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E27D409CAAC0DFFFFF" , vfnmadd132ps(zmm21, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E27D509C6A7F" , vfnmadd132ps(zmm21, zmm16, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E27D509CAA00020000" , vfnmadd132ps(zmm21, zmm16, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E27D509C6A80" , vfnmadd132ps(zmm21, zmm16, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E27D509CAAFCFDFFFF" , vfnmadd132ps(zmm21, zmm16, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C2E5089DDB" , vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62C2E50A9DDB" , k(k2).vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62C2E58A9DDB" , k(k2).z().vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62C2E5189DDB" , rn_sae().vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62C2E5589DDB" , ru_sae().vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62C2E5389DDB" , rd_sae().vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62C2E5789DDB" , rz_sae().vfnmadd132sd(xmm19, xmm3, xmm11)); + TEST_INSTRUCTION("62E2E5089D19" , vfnmadd132sd(xmm19, xmm3, qword_ptr(rcx))); + TEST_INSTRUCTION("62A2E5089D9CF023010000" , vfnmadd132sd(xmm19, xmm3, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2E5089D5A7F" , vfnmadd132sd(xmm19, xmm3, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E2E5089D9A00040000" , vfnmadd132sd(xmm19, xmm3, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E2E5089D5A80" , vfnmadd132sd(xmm19, xmm3, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E2E5089D9AF8FBFFFF" , vfnmadd132sd(xmm19, xmm3, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("622275089DCF" , vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("6222750B9DCF" , k(k3).vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("6222758B9DCF" , k(k3).z().vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("622275189DCF" , rn_sae().vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("622275589DCF" , ru_sae().vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("622275389DCF" , rd_sae().vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("622275789DCF" , rz_sae().vfnmadd132ss(xmm25, xmm1, xmm23)); + TEST_INSTRUCTION("626275089D09" , vfnmadd132ss(xmm25, xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("622275089D8CF023010000" , vfnmadd132ss(xmm25, xmm1, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626275089D4A7F" , vfnmadd132ss(xmm25, xmm1, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("626275089D8A00020000" , vfnmadd132ss(xmm25, xmm1, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("626275089D4A80" , vfnmadd132ss(xmm25, xmm1, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("626275089D8AFCFDFFFF" , vfnmadd132ss(xmm25, xmm1, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C2FD40ACC9" , vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C2FD44ACC9" , k(k4).vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C2FDC4ACC9" , k(k4).z().vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C2FD10ACC9" , rn_sae().vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C2FD50ACC9" , ru_sae().vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C2FD30ACC9" , rd_sae().vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C2FD70ACC9" , rz_sae().vfnmadd213pd(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62E2FD40AC09" , vfnmadd213pd(zmm17, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2FD40AC8CF023010000" , vfnmadd213pd(zmm17, zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2FD50AC09" , vfnmadd213pd(zmm17, zmm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2FD40AC4A7F" , vfnmadd213pd(zmm17, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2FD40AC8A00200000" , vfnmadd213pd(zmm17, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2FD40AC4A80" , vfnmadd213pd(zmm17, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2FD40AC8AC0DFFFFF" , vfnmadd213pd(zmm17, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2FD50AC4A7F" , vfnmadd213pd(zmm17, zmm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2FD50AC8A00040000" , vfnmadd213pd(zmm17, zmm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2FD50AC4A80" , vfnmadd213pd(zmm17, zmm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2FD50AC8AF8FBFFFF" , vfnmadd213pd(zmm17, zmm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62622D48ACD6" , vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622D4EACD6" , k(k6).vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622DCEACD6" , k(k6).z().vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622D18ACD6" , rn_sae().vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622D58ACD6" , ru_sae().vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622D38ACD6" , rd_sae().vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622D78ACD6" , rz_sae().vfnmadd213ps(zmm26, zmm10, zmm6)); + TEST_INSTRUCTION("62622D48AC11" , vfnmadd213ps(zmm26, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62222D48AC94F023010000" , vfnmadd213ps(zmm26, zmm10, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62622D58AC11" , vfnmadd213ps(zmm26, zmm10, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62622D48AC527F" , vfnmadd213ps(zmm26, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62622D48AC9200200000" , vfnmadd213ps(zmm26, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62622D48AC5280" , vfnmadd213ps(zmm26, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62622D48AC92C0DFFFFF" , vfnmadd213ps(zmm26, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62622D58AC527F" , vfnmadd213ps(zmm26, zmm10, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62622D58AC9200020000" , vfnmadd213ps(zmm26, zmm10, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62622D58AC5280" , vfnmadd213ps(zmm26, zmm10, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62622D58AC92FCFDFFFF" , vfnmadd213ps(zmm26, zmm10, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6272A500ADEA" , vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A507ADEA" , k(k7).vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A587ADEA" , k(k7).z().vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A510ADEA" , rn_sae().vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A550ADEA" , ru_sae().vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A530ADEA" , rd_sae().vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A570ADEA" , rz_sae().vfnmadd213sd(xmm13, xmm27, xmm2)); + TEST_INSTRUCTION("6272A500AD29" , vfnmadd213sd(xmm13, xmm27, qword_ptr(rcx))); + TEST_INSTRUCTION("6232A500ADACF023010000" , vfnmadd213sd(xmm13, xmm27, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272A500AD6A7F" , vfnmadd213sd(xmm13, xmm27, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6272A500ADAA00040000" , vfnmadd213sd(xmm13, xmm27, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6272A500AD6A80" , vfnmadd213sd(xmm13, xmm27, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6272A500ADAAF8FBFFFF" , vfnmadd213sd(xmm13, xmm27, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62024508ADEC" , vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("6202450AADEC" , k(k2).vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("6202458AADEC" , k(k2).z().vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("62024518ADEC" , rn_sae().vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("62024558ADEC" , ru_sae().vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("62024538ADEC" , rd_sae().vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("62024578ADEC" , rz_sae().vfnmadd213ss(xmm29, xmm7, xmm28)); + TEST_INSTRUCTION("62624508AD29" , vfnmadd213ss(xmm29, xmm7, dword_ptr(rcx))); + TEST_INSTRUCTION("62224508ADACF023010000" , vfnmadd213ss(xmm29, xmm7, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62624508AD6A7F" , vfnmadd213ss(xmm29, xmm7, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62624508ADAA00020000" , vfnmadd213ss(xmm29, xmm7, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62624508AD6A80" , vfnmadd213ss(xmm29, xmm7, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62624508ADAAFCFDFFFF" , vfnmadd213ss(xmm29, xmm7, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6232A548BCE0" , vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6232A54EBCE0" , k(k6).vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6232A5CEBCE0" , k(k6).z().vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6232A518BCE0" , rn_sae().vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6232A558BCE0" , ru_sae().vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6232A538BCE0" , rd_sae().vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6232A578BCE0" , rz_sae().vfnmadd231pd(zmm12, zmm11, zmm16)); + TEST_INSTRUCTION("6272A548BC21" , vfnmadd231pd(zmm12, zmm11, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232A548BCA4F023010000" , vfnmadd231pd(zmm12, zmm11, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272A558BC21" , vfnmadd231pd(zmm12, zmm11, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272A548BC627F" , vfnmadd231pd(zmm12, zmm11, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272A548BCA200200000" , vfnmadd231pd(zmm12, zmm11, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272A548BC6280" , vfnmadd231pd(zmm12, zmm11, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272A548BCA2C0DFFFFF" , vfnmadd231pd(zmm12, zmm11, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272A558BC627F" , vfnmadd231pd(zmm12, zmm11, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272A558BCA200040000" , vfnmadd231pd(zmm12, zmm11, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272A558BC6280" , vfnmadd231pd(zmm12, zmm11, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272A558BCA2F8FBFFFF" , vfnmadd231pd(zmm12, zmm11, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62124548BCF0" , vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("6212454DBCF0" , k(k5).vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("621245CDBCF0" , k(k5).z().vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("62124518BCF0" , rn_sae().vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("62124558BCF0" , ru_sae().vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("62124538BCF0" , rd_sae().vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("62124578BCF0" , rz_sae().vfnmadd231ps(zmm14, zmm7, zmm24)); + TEST_INSTRUCTION("62724548BC31" , vfnmadd231ps(zmm14, zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62324548BCB4F023010000" , vfnmadd231ps(zmm14, zmm7, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62724558BC31" , vfnmadd231ps(zmm14, zmm7, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62724548BC727F" , vfnmadd231ps(zmm14, zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62724548BCB200200000" , vfnmadd231ps(zmm14, zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62724548BC7280" , vfnmadd231ps(zmm14, zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62724548BCB2C0DFFFFF" , vfnmadd231ps(zmm14, zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62724558BC727F" , vfnmadd231ps(zmm14, zmm7, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62724558BCB200020000" , vfnmadd231ps(zmm14, zmm7, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62724558BC7280" , vfnmadd231ps(zmm14, zmm7, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62724558BCB2FCFDFFFF" , vfnmadd231ps(zmm14, zmm7, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B2A508BDF2" , vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("62B2A50BBDF2" , k(k3).vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("62B2A58BBDF2" , k(k3).z().vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("62B2A518BDF2" , rn_sae().vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("62B2A558BDF2" , ru_sae().vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("62B2A538BDF2" , rd_sae().vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("62B2A578BDF2" , rz_sae().vfnmadd231sd(xmm6, xmm11, xmm18)); + TEST_INSTRUCTION("C4E2A1BD31" , vfnmadd231sd(xmm6, xmm11, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A2A1BDB4F023010000" , vfnmadd231sd(xmm6, xmm11, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C4E2A1BDB2F8030000" , vfnmadd231sd(xmm6, xmm11, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E2A1BDB200040000" , vfnmadd231sd(xmm6, xmm11, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E2A1BDB200FCFFFF" , vfnmadd231sd(xmm6, xmm11, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E2A1BDB2F8FBFFFF" , vfnmadd231sd(xmm6, xmm11, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62226D08BDD9" , vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62226D09BDD9" , k(k1).vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62226D89BDD9" , k(k1).z().vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62226D18BDD9" , rn_sae().vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62226D58BDD9" , ru_sae().vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62226D38BDD9" , rd_sae().vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62226D78BDD9" , rz_sae().vfnmadd231ss(xmm27, xmm2, xmm17)); + TEST_INSTRUCTION("62626D08BD19" , vfnmadd231ss(xmm27, xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62226D08BD9CF023010000" , vfnmadd231ss(xmm27, xmm2, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62626D08BD5A7F" , vfnmadd231ss(xmm27, xmm2, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62626D08BD9A00020000" , vfnmadd231ss(xmm27, xmm2, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62626D08BD5A80" , vfnmadd231ss(xmm27, xmm2, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62626D08BD9AFCFDFFFF" , vfnmadd231ss(xmm27, xmm2, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6262D5489EE6" , vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D54A9EE6" , k(k2).vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D5CA9EE6" , k(k2).z().vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D5189EE6" , rn_sae().vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D5589EE6" , ru_sae().vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D5389EE6" , rd_sae().vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D5789EE6" , rz_sae().vfnmsub132pd(zmm28, zmm5, zmm6)); + TEST_INSTRUCTION("6262D5489E21" , vfnmsub132pd(zmm28, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222D5489EA4F023010000" , vfnmsub132pd(zmm28, zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262D5589E21" , vfnmsub132pd(zmm28, zmm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262D5489E627F" , vfnmsub132pd(zmm28, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262D5489EA200200000" , vfnmsub132pd(zmm28, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262D5489E6280" , vfnmsub132pd(zmm28, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262D5489EA2C0DFFFFF" , vfnmsub132pd(zmm28, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262D5589E627F" , vfnmsub132pd(zmm28, zmm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262D5589EA200040000" , vfnmsub132pd(zmm28, zmm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262D5589E6280" , vfnmsub132pd(zmm28, zmm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262D5589EA2F8FBFFFF" , vfnmsub132pd(zmm28, zmm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F26D409EE6" , vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26D429EE6" , k(k2).vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26DC29EE6" , k(k2).z().vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26D109EE6" , rn_sae().vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26D509EE6" , ru_sae().vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26D309EE6" , rd_sae().vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26D709EE6" , rz_sae().vfnmsub132ps(zmm4, zmm18, zmm6)); + TEST_INSTRUCTION("62F26D409E21" , vfnmsub132ps(zmm4, zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B26D409EA4F023010000" , vfnmsub132ps(zmm4, zmm18, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F26D509E21" , vfnmsub132ps(zmm4, zmm18, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F26D409E627F" , vfnmsub132ps(zmm4, zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F26D409EA200200000" , vfnmsub132ps(zmm4, zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F26D409E6280" , vfnmsub132ps(zmm4, zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F26D409EA2C0DFFFFF" , vfnmsub132ps(zmm4, zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F26D509E627F" , vfnmsub132ps(zmm4, zmm18, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F26D509EA200020000" , vfnmsub132ps(zmm4, zmm18, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F26D509E6280" , vfnmsub132ps(zmm4, zmm18, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F26D509EA2FCFDFFFF" , vfnmsub132ps(zmm4, zmm18, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6242A5089FD5" , vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6242A50E9FD5" , k(k6).vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6242A58E9FD5" , k(k6).z().vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6242A5189FD5" , rn_sae().vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6242A5589FD5" , ru_sae().vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6242A5389FD5" , rd_sae().vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6242A5789FD5" , rz_sae().vfnmsub132sd(xmm26, xmm11, xmm13)); + TEST_INSTRUCTION("6262A5089F11" , vfnmsub132sd(xmm26, xmm11, qword_ptr(rcx))); + TEST_INSTRUCTION("6222A5089F94F023010000" , vfnmsub132sd(xmm26, xmm11, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262A5089F527F" , vfnmsub132sd(xmm26, xmm11, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262A5089F9200040000" , vfnmsub132sd(xmm26, xmm11, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262A5089F5280" , vfnmsub132sd(xmm26, xmm11, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262A5089F92F8FBFFFF" , vfnmsub132sd(xmm26, xmm11, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62824D009FF8" , vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62824D069FF8" , k(k6).vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62824D869FF8" , k(k6).z().vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62824D109FF8" , rn_sae().vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62824D509FF8" , ru_sae().vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62824D309FF8" , rd_sae().vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62824D709FF8" , rz_sae().vfnmsub132ss(xmm23, xmm22, xmm24)); + TEST_INSTRUCTION("62E24D009F39" , vfnmsub132ss(xmm23, xmm22, dword_ptr(rcx))); + TEST_INSTRUCTION("62A24D009FBCF023010000" , vfnmsub132ss(xmm23, xmm22, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E24D009F7A7F" , vfnmsub132ss(xmm23, xmm22, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E24D009FBA00020000" , vfnmsub132ss(xmm23, xmm22, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E24D009F7A80" , vfnmsub132ss(xmm23, xmm22, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E24D009FBAFCFDFFFF" , vfnmsub132ss(xmm23, xmm22, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C2ED40AEFB" , vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62C2ED42AEFB" , k(k2).vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62C2EDC2AEFB" , k(k2).z().vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62C2ED10AEFB" , rn_sae().vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62C2ED50AEFB" , ru_sae().vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62C2ED30AEFB" , rd_sae().vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62C2ED70AEFB" , rz_sae().vfnmsub213pd(zmm23, zmm18, zmm11)); + TEST_INSTRUCTION("62E2ED40AE39" , vfnmsub213pd(zmm23, zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2ED40AEBCF023010000" , vfnmsub213pd(zmm23, zmm18, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2ED50AE39" , vfnmsub213pd(zmm23, zmm18, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2ED40AE7A7F" , vfnmsub213pd(zmm23, zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2ED40AEBA00200000" , vfnmsub213pd(zmm23, zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2ED40AE7A80" , vfnmsub213pd(zmm23, zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2ED40AEBAC0DFFFFF" , vfnmsub213pd(zmm23, zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2ED50AE7A7F" , vfnmsub213pd(zmm23, zmm18, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2ED50AEBA00040000" , vfnmsub213pd(zmm23, zmm18, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2ED50AE7A80" , vfnmsub213pd(zmm23, zmm18, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2ED50AEBAF8FBFFFF" , vfnmsub213pd(zmm23, zmm18, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E21548AEEA" , vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E2154BAEEA" , k(k3).vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E215CBAEEA" , k(k3).z().vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E21518AEEA" , rn_sae().vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E21558AEEA" , ru_sae().vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E21538AEEA" , rd_sae().vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E21578AEEA" , rz_sae().vfnmsub213ps(zmm21, zmm13, zmm2)); + TEST_INSTRUCTION("62E21548AE29" , vfnmsub213ps(zmm21, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A21548AEACF023010000" , vfnmsub213ps(zmm21, zmm13, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E21558AE29" , vfnmsub213ps(zmm21, zmm13, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E21548AE6A7F" , vfnmsub213ps(zmm21, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E21548AEAA00200000" , vfnmsub213ps(zmm21, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E21548AE6A80" , vfnmsub213ps(zmm21, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E21548AEAAC0DFFFFF" , vfnmsub213ps(zmm21, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E21558AE6A7F" , vfnmsub213ps(zmm21, zmm13, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E21558AEAA00020000" , vfnmsub213ps(zmm21, zmm13, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E21558AE6A80" , vfnmsub213ps(zmm21, zmm13, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E21558AEAAFCFDFFFF" , vfnmsub213ps(zmm21, zmm13, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6202C500AFEC" , vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6202C503AFEC" , k(k3).vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6202C583AFEC" , k(k3).z().vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6202C510AFEC" , rn_sae().vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6202C550AFEC" , ru_sae().vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6202C530AFEC" , rd_sae().vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6202C570AFEC" , rz_sae().vfnmsub213sd(xmm29, xmm23, xmm28)); + TEST_INSTRUCTION("6262C500AF29" , vfnmsub213sd(xmm29, xmm23, qword_ptr(rcx))); + TEST_INSTRUCTION("6222C500AFACF023010000" , vfnmsub213sd(xmm29, xmm23, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262C500AF6A7F" , vfnmsub213sd(xmm29, xmm23, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262C500AFAA00040000" , vfnmsub213sd(xmm29, xmm23, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262C500AF6A80" , vfnmsub213sd(xmm29, xmm23, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262C500AFAAF8FBFFFF" , vfnmsub213sd(xmm29, xmm23, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62521D00AFF4" , vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62521D04AFF4" , k(k4).vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62521D84AFF4" , k(k4).z().vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62521D10AFF4" , rn_sae().vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62521D50AFF4" , ru_sae().vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62521D30AFF4" , rd_sae().vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62521D70AFF4" , rz_sae().vfnmsub213ss(xmm14, xmm28, xmm12)); + TEST_INSTRUCTION("62721D00AF31" , vfnmsub213ss(xmm14, xmm28, dword_ptr(rcx))); + TEST_INSTRUCTION("62321D00AFB4F023010000" , vfnmsub213ss(xmm14, xmm28, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62721D00AF727F" , vfnmsub213ss(xmm14, xmm28, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62721D00AFB200020000" , vfnmsub213ss(xmm14, xmm28, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62721D00AF7280" , vfnmsub213ss(xmm14, xmm28, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62721D00AFB2FCFDFFFF" , vfnmsub213ss(xmm14, xmm28, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6202DD48BEE8" , vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6202DD4FBEE8" , k(k7).vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6202DDCFBEE8" , k(k7).z().vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6202DD18BEE8" , rn_sae().vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6202DD58BEE8" , ru_sae().vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6202DD38BEE8" , rd_sae().vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6202DD78BEE8" , rz_sae().vfnmsub231pd(zmm29, zmm4, zmm24)); + TEST_INSTRUCTION("6262DD48BE29" , vfnmsub231pd(zmm29, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222DD48BEACF023010000" , vfnmsub231pd(zmm29, zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262DD58BE29" , vfnmsub231pd(zmm29, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262DD48BE6A7F" , vfnmsub231pd(zmm29, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262DD48BEAA00200000" , vfnmsub231pd(zmm29, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262DD48BE6A80" , vfnmsub231pd(zmm29, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262DD48BEAAC0DFFFFF" , vfnmsub231pd(zmm29, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262DD58BE6A7F" , vfnmsub231pd(zmm29, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262DD58BEAA00040000" , vfnmsub231pd(zmm29, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262DD58BE6A80" , vfnmsub231pd(zmm29, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262DD58BEAAF8FBFFFF" , vfnmsub231pd(zmm29, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62524D48BEC5" , vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62524D4ABEC5" , k(k2).vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62524DCABEC5" , k(k2).z().vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62524D18BEC5" , rn_sae().vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62524D58BEC5" , ru_sae().vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62524D38BEC5" , rd_sae().vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62524D78BEC5" , rz_sae().vfnmsub231ps(zmm8, zmm6, zmm13)); + TEST_INSTRUCTION("62724D48BE01" , vfnmsub231ps(zmm8, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62324D48BE84F023010000" , vfnmsub231ps(zmm8, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62724D58BE01" , vfnmsub231ps(zmm8, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62724D48BE427F" , vfnmsub231ps(zmm8, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62724D48BE8200200000" , vfnmsub231ps(zmm8, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62724D48BE4280" , vfnmsub231ps(zmm8, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62724D48BE82C0DFFFFF" , vfnmsub231ps(zmm8, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62724D58BE427F" , vfnmsub231ps(zmm8, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62724D58BE8200020000" , vfnmsub231ps(zmm8, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62724D58BE4280" , vfnmsub231ps(zmm8, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62724D58BE82FCFDFFFF" , vfnmsub231ps(zmm8, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D2DD00BFF6" , vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62D2DD01BFF6" , k(k1).vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62D2DD81BFF6" , k(k1).z().vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62D2DD10BFF6" , rn_sae().vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62D2DD50BFF6" , ru_sae().vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62D2DD30BFF6" , rd_sae().vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62D2DD70BFF6" , rz_sae().vfnmsub231sd(xmm6, xmm20, xmm14)); + TEST_INSTRUCTION("62F2DD00BF31" , vfnmsub231sd(xmm6, xmm20, qword_ptr(rcx))); + TEST_INSTRUCTION("62B2DD00BFB4F023010000" , vfnmsub231sd(xmm6, xmm20, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2DD00BF727F" , vfnmsub231sd(xmm6, xmm20, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F2DD00BFB200040000" , vfnmsub231sd(xmm6, xmm20, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F2DD00BF7280" , vfnmsub231sd(xmm6, xmm20, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F2DD00BFB2F8FBFFFF" , vfnmsub231sd(xmm6, xmm20, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62421508BFD2" , vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("6242150CBFD2" , k(k4).vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("6242158CBFD2" , k(k4).z().vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("62421518BFD2" , rn_sae().vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("62421558BFD2" , ru_sae().vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("62421538BFD2" , rd_sae().vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("62421578BFD2" , rz_sae().vfnmsub231ss(xmm26, xmm13, xmm10)); + TEST_INSTRUCTION("62621508BF11" , vfnmsub231ss(xmm26, xmm13, dword_ptr(rcx))); + TEST_INSTRUCTION("62221508BF94F023010000" , vfnmsub231ss(xmm26, xmm13, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62621508BF527F" , vfnmsub231ss(xmm26, xmm13, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62621508BF9200020000" , vfnmsub231ss(xmm26, xmm13, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62621508BF5280" , vfnmsub231ss(xmm26, xmm13, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62621508BF92FCFDFFFF" , vfnmsub231ss(xmm26, xmm13, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6212FD4842F1" , vgetexppd(zmm14, zmm25)); + TEST_INSTRUCTION("6212FD4D42F1" , k(k5).vgetexppd(zmm14, zmm25)); + TEST_INSTRUCTION("6212FDCD42F1" , k(k5).z().vgetexppd(zmm14, zmm25)); + TEST_INSTRUCTION("6212FD1842F1" , sae().vgetexppd(zmm14, zmm25)); + TEST_INSTRUCTION("6272FD484231" , vgetexppd(zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232FD4842B4F023010000" , vgetexppd(zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272FD584231" , vgetexppd(zmm14, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272FD4842727F" , vgetexppd(zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272FD4842B200200000" , vgetexppd(zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272FD48427280" , vgetexppd(zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272FD4842B2C0DFFFFF" , vgetexppd(zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272FD5842727F" , vgetexppd(zmm14, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272FD5842B200040000" , vgetexppd(zmm14, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272FD58427280" , vgetexppd(zmm14, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272FD5842B2F8FBFFFF" , vgetexppd(zmm14, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F27D4842CE" , vgetexpps(zmm1, zmm6)); + TEST_INSTRUCTION("62F27D4B42CE" , k(k3).vgetexpps(zmm1, zmm6)); + TEST_INSTRUCTION("62F27DCB42CE" , k(k3).z().vgetexpps(zmm1, zmm6)); + TEST_INSTRUCTION("62F27D1842CE" , sae().vgetexpps(zmm1, zmm6)); + TEST_INSTRUCTION("62F27D484209" , vgetexpps(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D48428CF023010000" , vgetexpps(zmm1, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D584209" , vgetexpps(zmm1, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27D48424A7F" , vgetexpps(zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27D48428A00200000" , vgetexpps(zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27D48424A80" , vgetexpps(zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27D48428AC0DFFFFF" , vgetexpps(zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27D58424A7F" , vgetexpps(zmm1, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27D58428A00020000" , vgetexpps(zmm1, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27D58424A80" , vgetexpps(zmm1, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27D58428AFCFDFFFF" , vgetexpps(zmm1, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2C50843D2" , vgetexpsd(xmm2, xmm7, xmm2)); + TEST_INSTRUCTION("62F2C50D43D2" , k(k5).vgetexpsd(xmm2, xmm7, xmm2)); + TEST_INSTRUCTION("62F2C58D43D2" , k(k5).z().vgetexpsd(xmm2, xmm7, xmm2)); + TEST_INSTRUCTION("62F2C51843D2" , sae().vgetexpsd(xmm2, xmm7, xmm2)); + TEST_INSTRUCTION("62F2C5084311" , vgetexpsd(xmm2, xmm7, qword_ptr(rcx))); + TEST_INSTRUCTION("62B2C5084394F023010000" , vgetexpsd(xmm2, xmm7, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2C50843527F" , vgetexpsd(xmm2, xmm7, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F2C508439200040000" , vgetexpsd(xmm2, xmm7, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F2C508435280" , vgetexpsd(xmm2, xmm7, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F2C5084392F8FBFFFF" , vgetexpsd(xmm2, xmm7, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6282750843E2" , vgetexpss(xmm20, xmm1, xmm26)); + TEST_INSTRUCTION("6282750F43E2" , k(k7).vgetexpss(xmm20, xmm1, xmm26)); + TEST_INSTRUCTION("6282758F43E2" , k(k7).z().vgetexpss(xmm20, xmm1, xmm26)); + TEST_INSTRUCTION("6282751843E2" , sae().vgetexpss(xmm20, xmm1, xmm26)); + TEST_INSTRUCTION("62E275084321" , vgetexpss(xmm20, xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("62A2750843A4F023010000" , vgetexpss(xmm20, xmm1, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2750843627F" , vgetexpss(xmm20, xmm1, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E2750843A200020000" , vgetexpss(xmm20, xmm1, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E27508436280" , vgetexpss(xmm20, xmm1, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E2750843A2FCFDFFFF" , vgetexpss(xmm20, xmm1, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6293FD4826D2AB" , vgetmantpd(zmm2, zmm26, 171)); + TEST_INSTRUCTION("6293FD4F26D2AB" , k(k7).vgetmantpd(zmm2, zmm26, 171)); + TEST_INSTRUCTION("6293FDCF26D2AB" , k(k7).z().vgetmantpd(zmm2, zmm26, 171)); + TEST_INSTRUCTION("6293FD1826D2AB" , sae().vgetmantpd(zmm2, zmm26, 171)); + TEST_INSTRUCTION("6293FD4826D27B" , vgetmantpd(zmm2, zmm26, 123)); + TEST_INSTRUCTION("6293FD1826D27B" , sae().vgetmantpd(zmm2, zmm26, 123)); + TEST_INSTRUCTION("62F3FD4826117B" , vgetmantpd(zmm2, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3FD482694F0230100007B" , vgetmantpd(zmm2, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F3FD5826117B" , vgetmantpd(zmm2, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD4826527F7B" , vgetmantpd(zmm2, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F3FD482692002000007B" , vgetmantpd(zmm2, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F3FD482652807B" , vgetmantpd(zmm2, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F3FD482692C0DFFFFF7B" , vgetmantpd(zmm2, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F3FD5826527F7B" , vgetmantpd(zmm2, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD582692000400007B" , vgetmantpd(zmm2, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD582652807B" , vgetmantpd(zmm2, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD582692F8FBFFFF7B" , vgetmantpd(zmm2, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62837D4826F4AB" , vgetmantps(zmm22, zmm28, 171)); + TEST_INSTRUCTION("62837D4B26F4AB" , k(k3).vgetmantps(zmm22, zmm28, 171)); + TEST_INSTRUCTION("62837DCB26F4AB" , k(k3).z().vgetmantps(zmm22, zmm28, 171)); + TEST_INSTRUCTION("62837D1826F4AB" , sae().vgetmantps(zmm22, zmm28, 171)); + TEST_INSTRUCTION("62837D4826F47B" , vgetmantps(zmm22, zmm28, 123)); + TEST_INSTRUCTION("62837D1826F47B" , sae().vgetmantps(zmm22, zmm28, 123)); + TEST_INSTRUCTION("62E37D4826317B" , vgetmantps(zmm22, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A37D4826B4F0230100007B" , vgetmantps(zmm22, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62E37D5826317B" , vgetmantps(zmm22, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62E37D4826727F7B" , vgetmantps(zmm22, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62E37D4826B2002000007B" , vgetmantps(zmm22, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62E37D482672807B" , vgetmantps(zmm22, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62E37D4826B2C0DFFFFF7B" , vgetmantps(zmm22, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62E37D5826727F7B" , vgetmantps(zmm22, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62E37D5826B2000200007B" , vgetmantps(zmm22, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62E37D582672807B" , vgetmantps(zmm22, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62E37D5826B2FCFDFFFF7B" , vgetmantps(zmm22, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D3A50027D8AB" , vgetmantsd(xmm3, xmm27, xmm8, 171)); + TEST_INSTRUCTION("62D3A50627D8AB" , k(k6).vgetmantsd(xmm3, xmm27, xmm8, 171)); + TEST_INSTRUCTION("62D3A58627D8AB" , k(k6).z().vgetmantsd(xmm3, xmm27, xmm8, 171)); + TEST_INSTRUCTION("62D3A51027D8AB" , sae().vgetmantsd(xmm3, xmm27, xmm8, 171)); + TEST_INSTRUCTION("62D3A50027D87B" , vgetmantsd(xmm3, xmm27, xmm8, 123)); + TEST_INSTRUCTION("62D3A51027D87B" , sae().vgetmantsd(xmm3, xmm27, xmm8, 123)); + TEST_INSTRUCTION("62F3A50027197B" , vgetmantsd(xmm3, xmm27, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3A500279CF0230100007B" , vgetmantsd(xmm3, xmm27, qword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F3A500275A7F7B" , vgetmantsd(xmm3, xmm27, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("62F3A500279A000400007B" , vgetmantsd(xmm3, xmm27, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("62F3A500275A807B" , vgetmantsd(xmm3, xmm27, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("62F3A500279AF8FBFFFF7B" , vgetmantsd(xmm3, xmm27, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62D36D0827DCAB" , vgetmantss(xmm3, xmm2, xmm12, 171)); + TEST_INSTRUCTION("62D36D0F27DCAB" , k(k7).vgetmantss(xmm3, xmm2, xmm12, 171)); + TEST_INSTRUCTION("62D36D8F27DCAB" , k(k7).z().vgetmantss(xmm3, xmm2, xmm12, 171)); + TEST_INSTRUCTION("62D36D1827DCAB" , sae().vgetmantss(xmm3, xmm2, xmm12, 171)); + TEST_INSTRUCTION("62D36D0827DC7B" , vgetmantss(xmm3, xmm2, xmm12, 123)); + TEST_INSTRUCTION("62D36D1827DC7B" , sae().vgetmantss(xmm3, xmm2, xmm12, 123)); + TEST_INSTRUCTION("62F36D0827197B" , vgetmantss(xmm3, xmm2, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B36D08279CF0230100007B" , vgetmantss(xmm3, xmm2, dword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F36D08275A7F7B" , vgetmantss(xmm3, xmm2, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62F36D08279A000200007B" , vgetmantss(xmm3, xmm2, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62F36D08275A807B" , vgetmantss(xmm3, xmm2, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62F36D08279AFCFDFFFF7B" , vgetmantss(xmm3, xmm2, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62732D4018DBAB" , vinsertf32x4(zmm11, zmm26, xmm3, 171)); + TEST_INSTRUCTION("62732D4118DBAB" , k(k1).vinsertf32x4(zmm11, zmm26, xmm3, 171)); + TEST_INSTRUCTION("62732DC118DBAB" , k(k1).z().vinsertf32x4(zmm11, zmm26, xmm3, 171)); + TEST_INSTRUCTION("62732D4018DB7B" , vinsertf32x4(zmm11, zmm26, xmm3, 123)); + TEST_INSTRUCTION("62732D4018197B" , vinsertf32x4(zmm11, zmm26, xmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62332D40189CF0230100007B" , vinsertf32x4(zmm11, zmm26, xmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62732D40185A7F7B" , vinsertf32x4(zmm11, zmm26, xmmword_ptr(rdx, 2032), 123)); + TEST_INSTRUCTION("62732D40189A000800007B" , vinsertf32x4(zmm11, zmm26, xmmword_ptr(rdx, 2048), 123)); + TEST_INSTRUCTION("62732D40185A807B" , vinsertf32x4(zmm11, zmm26, xmmword_ptr(rdx, -2048), 123)); + TEST_INSTRUCTION("62732D40189AF0F7FFFF7B" , vinsertf32x4(zmm11, zmm26, xmmword_ptr(rdx, -2064), 123)); + TEST_INSTRUCTION("62F3D5481ACFAB" , vinsertf64x4(zmm1, zmm5, ymm7, 171)); + TEST_INSTRUCTION("62F3D5491ACFAB" , k(k1).vinsertf64x4(zmm1, zmm5, ymm7, 171)); + TEST_INSTRUCTION("62F3D5C91ACFAB" , k(k1).z().vinsertf64x4(zmm1, zmm5, ymm7, 171)); + TEST_INSTRUCTION("62F3D5481ACF7B" , vinsertf64x4(zmm1, zmm5, ymm7, 123)); + TEST_INSTRUCTION("62F3D5481A097B" , vinsertf64x4(zmm1, zmm5, ymmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3D5481A8CF0230100007B" , vinsertf64x4(zmm1, zmm5, ymmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F3D5481A4A7F7B" , vinsertf64x4(zmm1, zmm5, ymmword_ptr(rdx, 4064), 123)); + TEST_INSTRUCTION("62F3D5481A8A001000007B" , vinsertf64x4(zmm1, zmm5, ymmword_ptr(rdx, 4096), 123)); + TEST_INSTRUCTION("62F3D5481A4A807B" , vinsertf64x4(zmm1, zmm5, ymmword_ptr(rdx, -4096), 123)); + TEST_INSTRUCTION("62F3D5481A8AE0EFFFFF7B" , vinsertf64x4(zmm1, zmm5, ymmword_ptr(rdx, -4128), 123)); + TEST_INSTRUCTION("62C3154838CAAB" , vinserti32x4(zmm17, zmm13, xmm10, 171)); + TEST_INSTRUCTION("62C3154E38CAAB" , k(k6).vinserti32x4(zmm17, zmm13, xmm10, 171)); + TEST_INSTRUCTION("62C315CE38CAAB" , k(k6).z().vinserti32x4(zmm17, zmm13, xmm10, 171)); + TEST_INSTRUCTION("62C3154838CA7B" , vinserti32x4(zmm17, zmm13, xmm10, 123)); + TEST_INSTRUCTION("62E3154838097B" , vinserti32x4(zmm17, zmm13, xmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A31548388CF0230100007B" , vinserti32x4(zmm17, zmm13, xmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62E31548384A7F7B" , vinserti32x4(zmm17, zmm13, xmmword_ptr(rdx, 2032), 123)); + TEST_INSTRUCTION("62E31548388A000800007B" , vinserti32x4(zmm17, zmm13, xmmword_ptr(rdx, 2048), 123)); + TEST_INSTRUCTION("62E31548384A807B" , vinserti32x4(zmm17, zmm13, xmmword_ptr(rdx, -2048), 123)); + TEST_INSTRUCTION("62E31548388AF0F7FFFF7B" , vinserti32x4(zmm17, zmm13, xmmword_ptr(rdx, -2064), 123)); + TEST_INSTRUCTION("62F3B5403AE4AB" , vinserti64x4(zmm4, zmm25, ymm4, 171)); + TEST_INSTRUCTION("62F3B5413AE4AB" , k(k1).vinserti64x4(zmm4, zmm25, ymm4, 171)); + TEST_INSTRUCTION("62F3B5C13AE4AB" , k(k1).z().vinserti64x4(zmm4, zmm25, ymm4, 171)); + TEST_INSTRUCTION("62F3B5403AE47B" , vinserti64x4(zmm4, zmm25, ymm4, 123)); + TEST_INSTRUCTION("62F3B5403A217B" , vinserti64x4(zmm4, zmm25, ymmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3B5403AA4F0230100007B" , vinserti64x4(zmm4, zmm25, ymmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F3B5403A627F7B" , vinserti64x4(zmm4, zmm25, ymmword_ptr(rdx, 4064), 123)); + TEST_INSTRUCTION("62F3B5403AA2001000007B" , vinserti64x4(zmm4, zmm25, ymmword_ptr(rdx, 4096), 123)); + TEST_INSTRUCTION("62F3B5403A62807B" , vinserti64x4(zmm4, zmm25, ymmword_ptr(rdx, -4096), 123)); + TEST_INSTRUCTION("62F3B5403AA2E0EFFFFF7B" , vinserti64x4(zmm4, zmm25, ymmword_ptr(rdx, -4128), 123)); + TEST_INSTRUCTION("6263750021F5AB" , vinsertps(xmm30, xmm17, xmm5, 171)); + TEST_INSTRUCTION("6263750021F57B" , vinsertps(xmm30, xmm17, xmm5, 123)); + TEST_INSTRUCTION("6263750021317B" , vinsertps(xmm30, xmm17, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223750021B4F0230100007B" , vinsertps(xmm30, xmm17, dword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6263750021727F7B" , vinsertps(xmm30, xmm17, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("6263750021B2000200007B" , vinsertps(xmm30, xmm17, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("626375002172807B" , vinsertps(xmm30, xmm17, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("6263750021B2FCFDFFFF7B" , vinsertps(xmm30, xmm17, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62219D405FF4" , vmaxpd(zmm30, zmm28, zmm20)); + TEST_INSTRUCTION("62219D415FF4" , k(k1).vmaxpd(zmm30, zmm28, zmm20)); + TEST_INSTRUCTION("62219DC15FF4" , k(k1).z().vmaxpd(zmm30, zmm28, zmm20)); + TEST_INSTRUCTION("62219D105FF4" , sae().vmaxpd(zmm30, zmm28, zmm20)); + TEST_INSTRUCTION("62619D405F31" , vmaxpd(zmm30, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62219D405FB4F023010000" , vmaxpd(zmm30, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62619D505F31" , vmaxpd(zmm30, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62619D405F727F" , vmaxpd(zmm30, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62619D405FB200200000" , vmaxpd(zmm30, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62619D405F7280" , vmaxpd(zmm30, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62619D405FB2C0DFFFFF" , vmaxpd(zmm30, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62619D505F727F" , vmaxpd(zmm30, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62619D505FB200040000" , vmaxpd(zmm30, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62619D505F7280" , vmaxpd(zmm30, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62619D505FB2F8FBFFFF" , vmaxpd(zmm30, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62214C485FCC" , vmaxps(zmm25, zmm6, zmm20)); + TEST_INSTRUCTION("62214C495FCC" , k(k1).vmaxps(zmm25, zmm6, zmm20)); + TEST_INSTRUCTION("62214CC95FCC" , k(k1).z().vmaxps(zmm25, zmm6, zmm20)); + TEST_INSTRUCTION("62214C185FCC" , sae().vmaxps(zmm25, zmm6, zmm20)); + TEST_INSTRUCTION("62614C485F09" , vmaxps(zmm25, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62214C485F8CF023010000" , vmaxps(zmm25, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62614C585F09" , vmaxps(zmm25, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62614C485F4A7F" , vmaxps(zmm25, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62614C485F8A00200000" , vmaxps(zmm25, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62614C485F4A80" , vmaxps(zmm25, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62614C485F8AC0DFFFFF" , vmaxps(zmm25, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62614C585F4A7F" , vmaxps(zmm25, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62614C585F8A00020000" , vmaxps(zmm25, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62614C585F4A80" , vmaxps(zmm25, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62614C585F8AFCFDFFFF" , vmaxps(zmm25, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6281E7005FE1" , vmaxsd(xmm20, xmm19, xmm25)); + TEST_INSTRUCTION("6281E7035FE1" , k(k3).vmaxsd(xmm20, xmm19, xmm25)); + TEST_INSTRUCTION("6281E7835FE1" , k(k3).z().vmaxsd(xmm20, xmm19, xmm25)); + TEST_INSTRUCTION("6281E7105FE1" , sae().vmaxsd(xmm20, xmm19, xmm25)); + TEST_INSTRUCTION("62E1E7005F21" , vmaxsd(xmm20, xmm19, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1E7005FA4F023010000" , vmaxsd(xmm20, xmm19, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1E7005F627F" , vmaxsd(xmm20, xmm19, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1E7005FA200040000" , vmaxsd(xmm20, xmm19, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1E7005F6280" , vmaxsd(xmm20, xmm19, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1E7005FA2F8FBFFFF" , vmaxsd(xmm20, xmm19, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C55A5FC6" , vmaxss(xmm8, xmm4, xmm6)); + TEST_INSTRUCTION("62715E0C5FC6" , k(k4).vmaxss(xmm8, xmm4, xmm6)); + TEST_INSTRUCTION("62715E8C5FC6" , k(k4).z().vmaxss(xmm8, xmm4, xmm6)); + TEST_INSTRUCTION("62715E185FC6" , sae().vmaxss(xmm8, xmm4, xmm6)); + TEST_INSTRUCTION("C55A5F01" , vmaxss(xmm8, xmm4, dword_ptr(rcx))); + TEST_INSTRUCTION("C4215A5F84F023010000" , vmaxss(xmm8, xmm4, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C55A5F82FC010000" , vmaxss(xmm8, xmm4, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C55A5F8200020000" , vmaxss(xmm8, xmm4, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C55A5F8200FEFFFF" , vmaxss(xmm8, xmm4, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C55A5F82FCFDFFFF" , vmaxss(xmm8, xmm4, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B1CD485DF6" , vminpd(zmm6, zmm6, zmm22)); + TEST_INSTRUCTION("62B1CD4F5DF6" , k(k7).vminpd(zmm6, zmm6, zmm22)); + TEST_INSTRUCTION("62B1CDCF5DF6" , k(k7).z().vminpd(zmm6, zmm6, zmm22)); + TEST_INSTRUCTION("62B1CD185DF6" , sae().vminpd(zmm6, zmm6, zmm22)); + TEST_INSTRUCTION("62F1CD485D31" , vminpd(zmm6, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1CD485DB4F023010000" , vminpd(zmm6, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1CD585D31" , vminpd(zmm6, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1CD485D727F" , vminpd(zmm6, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1CD485DB200200000" , vminpd(zmm6, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1CD485D7280" , vminpd(zmm6, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1CD485DB2C0DFFFFF" , vminpd(zmm6, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1CD585D727F" , vminpd(zmm6, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1CD585DB200040000" , vminpd(zmm6, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1CD585D7280" , vminpd(zmm6, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1CD585DB2F8FBFFFF" , vminpd(zmm6, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F164485DDF" , vminps(zmm3, zmm3, zmm7)); + TEST_INSTRUCTION("62F1644B5DDF" , k(k3).vminps(zmm3, zmm3, zmm7)); + TEST_INSTRUCTION("62F164CB5DDF" , k(k3).z().vminps(zmm3, zmm3, zmm7)); + TEST_INSTRUCTION("62F164185DDF" , sae().vminps(zmm3, zmm3, zmm7)); + TEST_INSTRUCTION("62F164485D19" , vminps(zmm3, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B164485D9CF023010000" , vminps(zmm3, zmm3, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F164585D19" , vminps(zmm3, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F164485D5A7F" , vminps(zmm3, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F164485D9A00200000" , vminps(zmm3, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F164485D5A80" , vminps(zmm3, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F164485D9AC0DFFFFF" , vminps(zmm3, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F164585D5A7F" , vminps(zmm3, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F164585D9A00020000" , vminps(zmm3, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F164585D5A80" , vminps(zmm3, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F164585D9AFCFDFFFF" , vminps(zmm3, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6291B7005DEA" , vminsd(xmm5, xmm25, xmm26)); + TEST_INSTRUCTION("6291B7035DEA" , k(k3).vminsd(xmm5, xmm25, xmm26)); + TEST_INSTRUCTION("6291B7835DEA" , k(k3).z().vminsd(xmm5, xmm25, xmm26)); + TEST_INSTRUCTION("6291B7105DEA" , sae().vminsd(xmm5, xmm25, xmm26)); + TEST_INSTRUCTION("62F1B7005D29" , vminsd(xmm5, xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1B7005DACF023010000" , vminsd(xmm5, xmm25, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1B7005D6A7F" , vminsd(xmm5, xmm25, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1B7005DAA00040000" , vminsd(xmm5, xmm25, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1B7005D6A80" , vminsd(xmm5, xmm25, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1B7005DAAF8FBFFFF" , vminsd(xmm5, xmm25, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("623176005DD3" , vminss(xmm10, xmm17, xmm19)); + TEST_INSTRUCTION("623176055DD3" , k(k5).vminss(xmm10, xmm17, xmm19)); + TEST_INSTRUCTION("623176855DD3" , k(k5).z().vminss(xmm10, xmm17, xmm19)); + TEST_INSTRUCTION("623176105DD3" , sae().vminss(xmm10, xmm17, xmm19)); + TEST_INSTRUCTION("627176005D11" , vminss(xmm10, xmm17, dword_ptr(rcx))); + TEST_INSTRUCTION("623176005D94F023010000" , vminss(xmm10, xmm17, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("627176005D527F" , vminss(xmm10, xmm17, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("627176005D9200020000" , vminss(xmm10, xmm17, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("627176005D5280" , vminss(xmm10, xmm17, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("627176005D92FCFDFFFF" , vminss(xmm10, xmm17, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62D1FD4828FE" , vmovapd(zmm7, zmm14)); + TEST_INSTRUCTION("62D1FD4D28FE" , k(k5).vmovapd(zmm7, zmm14)); + TEST_INSTRUCTION("62D1FDCD28FE" , k(k5).z().vmovapd(zmm7, zmm14)); + TEST_INSTRUCTION("62F1FD482839" , vmovapd(zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FD4828BCF023010000" , vmovapd(zmm7, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FD48287A7F" , vmovapd(zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FD4828BA00200000" , vmovapd(zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FD48287A80" , vmovapd(zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FD4828BAC0DFFFFF" , vmovapd(zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62D17C4828E9" , vmovaps(zmm5, zmm9)); + TEST_INSTRUCTION("62D17C4928E9" , k(k1).vmovaps(zmm5, zmm9)); + TEST_INSTRUCTION("62D17CC928E9" , k(k1).z().vmovaps(zmm5, zmm9)); + TEST_INSTRUCTION("62F17C482829" , vmovaps(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17C4828ACF023010000" , vmovaps(zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17C48286A7F" , vmovaps(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17C4828AA00200000" , vmovaps(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17C48286A80" , vmovaps(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17C4828AAC0DFFFFF" , vmovaps(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62617D086ED0" , vmovd(xmm26, eax)); + TEST_INSTRUCTION("62617D086ED5" , vmovd(xmm26, ebp)); + TEST_INSTRUCTION("62417D086ED5" , vmovd(xmm26, r13d)); + TEST_INSTRUCTION("62617D086E11" , vmovd(xmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62217D086E94F023010000" , vmovd(xmm26, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62617D086E527F" , vmovd(xmm26, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62617D086E9200020000" , vmovd(xmm26, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62617D086E5280" , vmovd(xmm26, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62617D086E92FCFDFFFF" , vmovd(xmm26, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("C5F97E29" , vmovd(dword_ptr(rcx), xmm5)); + TEST_INSTRUCTION("C4A1797EACF023010000" , vmovd(dword_ptr(rax, r14, 3, 291), xmm5)); + TEST_INSTRUCTION("C5F97EAAFC010000" , vmovd(dword_ptr(rdx, 508), xmm5)); + TEST_INSTRUCTION("C5F97EAA00020000" , vmovd(dword_ptr(rdx, 512), xmm5)); + TEST_INSTRUCTION("C5F97EAA00FEFFFF" , vmovd(dword_ptr(rdx, -512), xmm5)); + TEST_INSTRUCTION("C5F97EAAFCFDFFFF" , vmovd(dword_ptr(rdx, -516), xmm5)); + TEST_INSTRUCTION("6291FF4812ED" , vmovddup(zmm5, zmm29)); + TEST_INSTRUCTION("6291FF4C12ED" , k(k4).vmovddup(zmm5, zmm29)); + TEST_INSTRUCTION("6291FFCC12ED" , k(k4).z().vmovddup(zmm5, zmm29)); + TEST_INSTRUCTION("62F1FF481229" , vmovddup(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF4812ACF023010000" , vmovddup(zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FF48126A7F" , vmovddup(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FF4812AA00200000" , vmovddup(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FF48126A80" , vmovddup(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FF4812AAC0DFFFFF" , vmovddup(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62A17D486FF2" , vmovdqa32(zmm22, zmm18)); + TEST_INSTRUCTION("62A17D4E6FF2" , k(k6).vmovdqa32(zmm22, zmm18)); + TEST_INSTRUCTION("62A17DCE6FF2" , k(k6).z().vmovdqa32(zmm22, zmm18)); + TEST_INSTRUCTION("62E17D486F31" , vmovdqa32(zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17D486FB4F023010000" , vmovdqa32(zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17D486F727F" , vmovdqa32(zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17D486FB200200000" , vmovdqa32(zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17D486F7280" , vmovdqa32(zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17D486FB2C0DFFFFF" , vmovdqa32(zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62C1FD486FF4" , vmovdqa64(zmm22, zmm12)); + TEST_INSTRUCTION("62C1FD4D6FF4" , k(k5).vmovdqa64(zmm22, zmm12)); + TEST_INSTRUCTION("62C1FDCD6FF4" , k(k5).z().vmovdqa64(zmm22, zmm12)); + TEST_INSTRUCTION("62E1FD486F31" , vmovdqa64(zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD486FB4F023010000" , vmovdqa64(zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1FD486F727F" , vmovdqa64(zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FD486FB200200000" , vmovdqa64(zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FD486F7280" , vmovdqa64(zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FD486FB2C0DFFFFF" , vmovdqa64(zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62917E486FE8" , vmovdqu32(zmm5, zmm24)); + TEST_INSTRUCTION("62917E4D6FE8" , k(k5).vmovdqu32(zmm5, zmm24)); + TEST_INSTRUCTION("62917ECD6FE8" , k(k5).z().vmovdqu32(zmm5, zmm24)); + TEST_INSTRUCTION("62F17E486F29" , vmovdqu32(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17E486FACF023010000" , vmovdqu32(zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17E486F6A7F" , vmovdqu32(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17E486FAA00200000" , vmovdqu32(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17E486F6A80" , vmovdqu32(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17E486FAAC0DFFFFF" , vmovdqu32(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62D1FE486FF7" , vmovdqu64(zmm6, zmm15)); + TEST_INSTRUCTION("62D1FE4B6FF7" , k(k3).vmovdqu64(zmm6, zmm15)); + TEST_INSTRUCTION("62D1FECB6FF7" , k(k3).z().vmovdqu64(zmm6, zmm15)); + TEST_INSTRUCTION("62F1FE486F31" , vmovdqu64(zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FE486FB4F023010000" , vmovdqu64(zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FE486F727F" , vmovdqu64(zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FE486FB200200000" , vmovdqu64(zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FE486F7280" , vmovdqu64(zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FE486FB2C0DFFFFF" , vmovdqu64(zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62A1740812D7" , vmovhlps(xmm18, xmm1, xmm23)); + TEST_INSTRUCTION("62E19D001619" , vmovhpd(xmm19, xmm28, qword_ptr(rcx))); + TEST_INSTRUCTION("62A19D00169CF023010000" , vmovhpd(xmm19, xmm28, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E19D00165A7F" , vmovhpd(xmm19, xmm28, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E19D00169A00040000" , vmovhpd(xmm19, xmm28, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E19D00165A80" , vmovhpd(xmm19, xmm28, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E19D00169AF8FBFFFF" , vmovhpd(xmm19, xmm28, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C5791739" , vmovhpd(qword_ptr(rcx), xmm15)); + TEST_INSTRUCTION("C4217917BCF023010000" , vmovhpd(qword_ptr(rax, r14, 3, 291), xmm15)); + TEST_INSTRUCTION("C57917BAF8030000" , vmovhpd(qword_ptr(rdx, 1016), xmm15)); + TEST_INSTRUCTION("C57917BA00040000" , vmovhpd(qword_ptr(rdx, 1024), xmm15)); + TEST_INSTRUCTION("C57917BA00FCFFFF" , vmovhpd(qword_ptr(rdx, -1024), xmm15)); + TEST_INSTRUCTION("C57917BAF8FBFFFF" , vmovhpd(qword_ptr(rdx, -1032), xmm15)); + TEST_INSTRUCTION("62E174001621" , vmovhps(xmm20, xmm17, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1740016A4F023010000" , vmovhps(xmm20, xmm17, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1740016627F" , vmovhps(xmm20, xmm17, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1740016A200040000" , vmovhps(xmm20, xmm17, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E17400166280" , vmovhps(xmm20, xmm17, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1740016A2F8FBFFFF" , vmovhps(xmm20, xmm17, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62E17C081711" , vmovhps(qword_ptr(rcx), xmm18)); + TEST_INSTRUCTION("62A17C081794F023010000" , vmovhps(qword_ptr(rax, r14, 3, 291), xmm18)); + TEST_INSTRUCTION("62E17C0817527F" , vmovhps(qword_ptr(rdx, 1016), xmm18)); + TEST_INSTRUCTION("62E17C08179200040000" , vmovhps(qword_ptr(rdx, 1024), xmm18)); + TEST_INSTRUCTION("62E17C08175280" , vmovhps(qword_ptr(rdx, -1024), xmm18)); + TEST_INSTRUCTION("62E17C081792F8FBFFFF" , vmovhps(qword_ptr(rdx, -1032), xmm18)); + TEST_INSTRUCTION("6211140816EC" , vmovlhps(xmm13, xmm13, xmm28)); + TEST_INSTRUCTION("6261CD081229" , vmovlpd(xmm29, xmm6, qword_ptr(rcx))); + TEST_INSTRUCTION("6221CD0812ACF023010000" , vmovlpd(xmm29, xmm6, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261CD08126A7F" , vmovlpd(xmm29, xmm6, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261CD0812AA00040000" , vmovlpd(xmm29, xmm6, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6261CD08126A80" , vmovlpd(xmm29, xmm6, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261CD0812AAF8FBFFFF" , vmovlpd(xmm29, xmm6, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C5791339" , vmovlpd(qword_ptr(rcx), xmm15)); + TEST_INSTRUCTION("C4217913BCF023010000" , vmovlpd(qword_ptr(rax, r14, 3, 291), xmm15)); + TEST_INSTRUCTION("C57913BAF8030000" , vmovlpd(qword_ptr(rdx, 1016), xmm15)); + TEST_INSTRUCTION("C57913BA00040000" , vmovlpd(qword_ptr(rdx, 1024), xmm15)); + TEST_INSTRUCTION("C57913BA00FCFFFF" , vmovlpd(qword_ptr(rdx, -1024), xmm15)); + TEST_INSTRUCTION("C57913BAF8FBFFFF" , vmovlpd(qword_ptr(rdx, -1032), xmm15)); + TEST_INSTRUCTION("62F15C001239" , vmovlps(xmm7, xmm20, qword_ptr(rcx))); + TEST_INSTRUCTION("62B15C0012BCF023010000" , vmovlps(xmm7, xmm20, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F15C00127A7F" , vmovlps(xmm7, xmm20, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F15C0012BA00040000" , vmovlps(xmm7, xmm20, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F15C00127A80" , vmovlps(xmm7, xmm20, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F15C0012BAF8FBFFFF" , vmovlps(xmm7, xmm20, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62617C081319" , vmovlps(qword_ptr(rcx), xmm27)); + TEST_INSTRUCTION("62217C08139CF023010000" , vmovlps(qword_ptr(rax, r14, 3, 291), xmm27)); + TEST_INSTRUCTION("62617C08135A7F" , vmovlps(qword_ptr(rdx, 1016), xmm27)); + TEST_INSTRUCTION("62617C08139A00040000" , vmovlps(qword_ptr(rdx, 1024), xmm27)); + TEST_INSTRUCTION("62617C08135A80" , vmovlps(qword_ptr(rdx, -1024), xmm27)); + TEST_INSTRUCTION("62617C08139AF8FBFFFF" , vmovlps(qword_ptr(rdx, -1032), xmm27)); + TEST_INSTRUCTION("62617D48E701" , vmovntdq(zmmword_ptr(rcx), zmm24)); + TEST_INSTRUCTION("62217D48E784F023010000" , vmovntdq(zmmword_ptr(rax, r14, 3, 291), zmm24)); + TEST_INSTRUCTION("62617D48E7427F" , vmovntdq(zmmword_ptr(rdx, 8128), zmm24)); + TEST_INSTRUCTION("62617D48E78200200000" , vmovntdq(zmmword_ptr(rdx, 8192), zmm24)); + TEST_INSTRUCTION("62617D48E74280" , vmovntdq(zmmword_ptr(rdx, -8192), zmm24)); + TEST_INSTRUCTION("62617D48E782C0DFFFFF" , vmovntdq(zmmword_ptr(rdx, -8256), zmm24)); + TEST_INSTRUCTION("62E27D482A09" , vmovntdqa(zmm17, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D482A8CF023010000" , vmovntdqa(zmm17, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E27D482A4A7F" , vmovntdqa(zmm17, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E27D482A8A00200000" , vmovntdqa(zmm17, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E27D482A4A80" , vmovntdqa(zmm17, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E27D482A8AC0DFFFFF" , vmovntdqa(zmm17, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FD482B09" , vmovntpd(zmmword_ptr(rcx), zmm17)); + TEST_INSTRUCTION("62A1FD482B8CF023010000" , vmovntpd(zmmword_ptr(rax, r14, 3, 291), zmm17)); + TEST_INSTRUCTION("62E1FD482B4A7F" , vmovntpd(zmmword_ptr(rdx, 8128), zmm17)); + TEST_INSTRUCTION("62E1FD482B8A00200000" , vmovntpd(zmmword_ptr(rdx, 8192), zmm17)); + TEST_INSTRUCTION("62E1FD482B4A80" , vmovntpd(zmmword_ptr(rdx, -8192), zmm17)); + TEST_INSTRUCTION("62E1FD482B8AC0DFFFFF" , vmovntpd(zmmword_ptr(rdx, -8256), zmm17)); + TEST_INSTRUCTION("62F17C482B29" , vmovntps(zmmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62B17C482BACF023010000" , vmovntps(zmmword_ptr(rax, r14, 3, 291), zmm5)); + TEST_INSTRUCTION("62F17C482B6A7F" , vmovntps(zmmword_ptr(rdx, 8128), zmm5)); + TEST_INSTRUCTION("62F17C482BAA00200000" , vmovntps(zmmword_ptr(rdx, 8192), zmm5)); + TEST_INSTRUCTION("62F17C482B6A80" , vmovntps(zmmword_ptr(rdx, -8192), zmm5)); + TEST_INSTRUCTION("62F17C482BAAC0DFFFFF" , vmovntps(zmmword_ptr(rdx, -8256), zmm5)); + TEST_INSTRUCTION("6261FF081009" , vmovsd(xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6261FF0B1009" , k(k3).vmovsd(xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6261FF8B1009" , k(k3).z().vmovsd(xmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6221FF08108CF023010000" , vmovsd(xmm25, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261FF08104A7F" , vmovsd(xmm25, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261FF08108A00040000" , vmovsd(xmm25, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6261FF08104A80" , vmovsd(xmm25, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261FF08108AF8FBFFFF" , vmovsd(xmm25, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6261FF081109" , vmovsd(qword_ptr(rcx), xmm25)); + TEST_INSTRUCTION("6261FF0A1109" , k(k2).vmovsd(qword_ptr(rcx), xmm25)); + TEST_INSTRUCTION("6221FF08118CF023010000" , vmovsd(qword_ptr(rax, r14, 3, 291), xmm25)); + TEST_INSTRUCTION("6261FF08114A7F" , vmovsd(qword_ptr(rdx, 1016), xmm25)); + TEST_INSTRUCTION("6261FF08118A00040000" , vmovsd(qword_ptr(rdx, 1024), xmm25)); + TEST_INSTRUCTION("6261FF08114A80" , vmovsd(qword_ptr(rdx, -1024), xmm25)); + TEST_INSTRUCTION("6261FF08118AF8FBFFFF" , vmovsd(qword_ptr(rdx, -1032), xmm25)); + TEST_INSTRUCTION("6221E70810DB" , vmovsd(xmm27, xmm3, xmm19)); + TEST_INSTRUCTION("6221E70B10DB" , k(k3).vmovsd(xmm27, xmm3, xmm19)); + TEST_INSTRUCTION("6221E78B10DB" , k(k3).z().vmovsd(xmm27, xmm3, xmm19)); + TEST_INSTRUCTION("62817E4816C3" , vmovshdup(zmm16, zmm27)); + TEST_INSTRUCTION("62817E4C16C3" , k(k4).vmovshdup(zmm16, zmm27)); + TEST_INSTRUCTION("62817ECC16C3" , k(k4).z().vmovshdup(zmm16, zmm27)); + TEST_INSTRUCTION("62E17E481601" , vmovshdup(zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17E481684F023010000" , vmovshdup(zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17E4816427F" , vmovshdup(zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17E48168200200000" , vmovshdup(zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17E48164280" , vmovshdup(zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17E481682C0DFFFFF" , vmovshdup(zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62517E4812EE" , vmovsldup(zmm13, zmm14)); + TEST_INSTRUCTION("62517E4E12EE" , k(k6).vmovsldup(zmm13, zmm14)); + TEST_INSTRUCTION("62517ECE12EE" , k(k6).z().vmovsldup(zmm13, zmm14)); + TEST_INSTRUCTION("62717E481229" , vmovsldup(zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62317E4812ACF023010000" , vmovsldup(zmm13, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717E48126A7F" , vmovsldup(zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62717E4812AA00200000" , vmovsldup(zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62717E48126A80" , vmovsldup(zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62717E4812AAC0DFFFFF" , vmovsldup(zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("C5FA1011" , vmovss(xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62F17E0C1011" , k(k4).vmovss(xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62F17E8C1011" , k(k4).z().vmovss(xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("C4A17A1094F023010000" , vmovss(xmm2, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5FA1092FC010000" , vmovss(xmm2, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5FA109200020000" , vmovss(xmm2, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5FA109200FEFFFF" , vmovss(xmm2, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5FA1092FCFDFFFF" , vmovss(xmm2, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("C5FA1129" , vmovss(dword_ptr(rcx), xmm5)); + TEST_INSTRUCTION("62F17E0E1129" , k(k6).vmovss(dword_ptr(rcx), xmm5)); + TEST_INSTRUCTION("C4A17A11ACF023010000" , vmovss(dword_ptr(rax, r14, 3, 291), xmm5)); + TEST_INSTRUCTION("C5FA11AAFC010000" , vmovss(dword_ptr(rdx, 508), xmm5)); + TEST_INSTRUCTION("C5FA11AA00020000" , vmovss(dword_ptr(rdx, 512), xmm5)); + TEST_INSTRUCTION("C5FA11AA00FEFFFF" , vmovss(dword_ptr(rdx, -512), xmm5)); + TEST_INSTRUCTION("C5FA11AAFCFDFFFF" , vmovss(dword_ptr(rdx, -516), xmm5)); + TEST_INSTRUCTION("6201360810E2" , vmovss(xmm28, xmm9, xmm26)); + TEST_INSTRUCTION("6201360C10E2" , k(k4).vmovss(xmm28, xmm9, xmm26)); + TEST_INSTRUCTION("6201368C10E2" , k(k4).z().vmovss(xmm28, xmm9, xmm26)); + TEST_INSTRUCTION("6241FD4810D9" , vmovupd(zmm27, zmm9)); + TEST_INSTRUCTION("6241FD4A10D9" , k(k2).vmovupd(zmm27, zmm9)); + TEST_INSTRUCTION("6241FDCA10D9" , k(k2).z().vmovupd(zmm27, zmm9)); + TEST_INSTRUCTION("6261FD481019" , vmovupd(zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221FD48109CF023010000" , vmovupd(zmm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261FD48105A7F" , vmovupd(zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261FD48109A00200000" , vmovupd(zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261FD48105A80" , vmovupd(zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261FD48109AC0DFFFFF" , vmovupd(zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62A17C4810F6" , vmovups(zmm22, zmm22)); + TEST_INSTRUCTION("62A17C4B10F6" , k(k3).vmovups(zmm22, zmm22)); + TEST_INSTRUCTION("62A17CCB10F6" , k(k3).z().vmovups(zmm22, zmm22)); + TEST_INSTRUCTION("62E17C481031" , vmovups(zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17C4810B4F023010000" , vmovups(zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17C4810727F" , vmovups(zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17C4810B200200000" , vmovups(zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17C48107280" , vmovups(zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17C4810B2C0DFFFFF" , vmovups(zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6221DD4859C7" , vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6221DD4E59C7" , k(k6).vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6221DDCE59C7" , k(k6).z().vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6221DD1859C7" , rn_sae().vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6221DD5859C7" , ru_sae().vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6221DD3859C7" , rd_sae().vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6221DD7859C7" , rz_sae().vmulpd(zmm24, zmm4, zmm23)); + TEST_INSTRUCTION("6261DD485901" , vmulpd(zmm24, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221DD485984F023010000" , vmulpd(zmm24, zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261DD585901" , vmulpd(zmm24, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261DD4859427F" , vmulpd(zmm24, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261DD48598200200000" , vmulpd(zmm24, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261DD48594280" , vmulpd(zmm24, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261DD485982C0DFFFFF" , vmulpd(zmm24, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261DD5859427F" , vmulpd(zmm24, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261DD58598200040000" , vmulpd(zmm24, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261DD58594280" , vmulpd(zmm24, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261DD585982F8FBFFFF" , vmulpd(zmm24, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62914C4859D8" , vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62914C4C59D8" , k(k4).vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62914CCC59D8" , k(k4).z().vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62914C1859D8" , rn_sae().vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62914C5859D8" , ru_sae().vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62914C3859D8" , rd_sae().vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62914C7859D8" , rz_sae().vmulps(zmm3, zmm6, zmm24)); + TEST_INSTRUCTION("62F14C485919" , vmulps(zmm3, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B14C48599CF023010000" , vmulps(zmm3, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F14C585919" , vmulps(zmm3, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F14C48595A7F" , vmulps(zmm3, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F14C48599A00200000" , vmulps(zmm3, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F14C48595A80" , vmulps(zmm3, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F14C48599AC0DFFFFF" , vmulps(zmm3, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F14C58595A7F" , vmulps(zmm3, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F14C58599A00020000" , vmulps(zmm3, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F14C58595A80" , vmulps(zmm3, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F14C58599AFCFDFFFF" , vmulps(zmm3, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6231DF0859EA" , vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("6231DF0A59EA" , k(k2).vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("6231DF8A59EA" , k(k2).z().vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("6231DF1859EA" , rn_sae().vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("6231DF5859EA" , ru_sae().vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("6231DF3859EA" , rd_sae().vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("6231DF7859EA" , rz_sae().vmulsd(xmm13, xmm4, xmm18)); + TEST_INSTRUCTION("C55B5929" , vmulsd(xmm13, xmm4, qword_ptr(rcx))); + TEST_INSTRUCTION("C4215B59ACF023010000" , vmulsd(xmm13, xmm4, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C55B59AAF8030000" , vmulsd(xmm13, xmm4, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C55B59AA00040000" , vmulsd(xmm13, xmm4, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C55B59AA00FCFFFF" , vmulsd(xmm13, xmm4, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C55B59AAF8FBFFFF" , vmulsd(xmm13, xmm4, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62C12E0859F6" , vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62C12E0C59F6" , k(k4).vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62C12E8C59F6" , k(k4).z().vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62C12E1859F6" , rn_sae().vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62C12E5859F6" , ru_sae().vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62C12E3859F6" , rd_sae().vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62C12E7859F6" , rz_sae().vmulss(xmm22, xmm10, xmm14)); + TEST_INSTRUCTION("62E12E085931" , vmulss(xmm22, xmm10, dword_ptr(rcx))); + TEST_INSTRUCTION("62A12E0859B4F023010000" , vmulss(xmm22, xmm10, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E12E0859727F" , vmulss(xmm22, xmm10, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E12E0859B200020000" , vmulss(xmm22, xmm10, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E12E08597280" , vmulss(xmm22, xmm10, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E12E0859B2FCFDFFFF" , vmulss(xmm22, xmm10, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62527D481EFE" , vpabsd(zmm15, zmm14)); + TEST_INSTRUCTION("62527D4E1EFE" , k(k6).vpabsd(zmm15, zmm14)); + TEST_INSTRUCTION("62527DCE1EFE" , k(k6).z().vpabsd(zmm15, zmm14)); + TEST_INSTRUCTION("62727D481E39" , vpabsd(zmm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D481EBCF023010000" , vpabsd(zmm15, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62727D581E39" , vpabsd(zmm15, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62727D481E7A7F" , vpabsd(zmm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62727D481EBA00200000" , vpabsd(zmm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62727D481E7A80" , vpabsd(zmm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62727D481EBAC0DFFFFF" , vpabsd(zmm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62727D581E7A7F" , vpabsd(zmm15, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62727D581EBA00020000" , vpabsd(zmm15, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62727D581E7A80" , vpabsd(zmm15, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62727D581EBAFCFDFFFF" , vpabsd(zmm15, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6292FD481FE8" , vpabsq(zmm5, zmm24)); + TEST_INSTRUCTION("6292FD4E1FE8" , k(k6).vpabsq(zmm5, zmm24)); + TEST_INSTRUCTION("6292FDCE1FE8" , k(k6).z().vpabsq(zmm5, zmm24)); + TEST_INSTRUCTION("62F2FD481F29" , vpabsq(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2FD481FACF023010000" , vpabsq(zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2FD581F29" , vpabsq(zmm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2FD481F6A7F" , vpabsq(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2FD481FAA00200000" , vpabsq(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2FD481F6A80" , vpabsq(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2FD481FAAC0DFFFFF" , vpabsq(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2FD581F6A7F" , vpabsq(zmm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2FD581FAA00040000" , vpabsq(zmm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2FD581F6A80" , vpabsq(zmm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2FD581FAAF8FBFFFF" , vpabsq(zmm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62215548FED4" , vpaddd(zmm26, zmm5, zmm20)); + TEST_INSTRUCTION("62215549FED4" , k(k1).vpaddd(zmm26, zmm5, zmm20)); + TEST_INSTRUCTION("622155C9FED4" , k(k1).z().vpaddd(zmm26, zmm5, zmm20)); + TEST_INSTRUCTION("62615548FE11" , vpaddd(zmm26, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62215548FE94F023010000" , vpaddd(zmm26, zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62615558FE11" , vpaddd(zmm26, zmm5, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62615548FE527F" , vpaddd(zmm26, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62615548FE9200200000" , vpaddd(zmm26, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62615548FE5280" , vpaddd(zmm26, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62615548FE92C0DFFFFF" , vpaddd(zmm26, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62615558FE527F" , vpaddd(zmm26, zmm5, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62615558FE9200020000" , vpaddd(zmm26, zmm5, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62615558FE5280" , vpaddd(zmm26, zmm5, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62615558FE92FCFDFFFF" , vpaddd(zmm26, zmm5, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6251B540D4C6" , vpaddq(zmm8, zmm25, zmm14)); + TEST_INSTRUCTION("6251B543D4C6" , k(k3).vpaddq(zmm8, zmm25, zmm14)); + TEST_INSTRUCTION("6251B5C3D4C6" , k(k3).z().vpaddq(zmm8, zmm25, zmm14)); + TEST_INSTRUCTION("6271B540D401" , vpaddq(zmm8, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231B540D484F023010000" , vpaddq(zmm8, zmm25, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271B550D401" , vpaddq(zmm8, zmm25, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271B540D4427F" , vpaddq(zmm8, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271B540D48200200000" , vpaddq(zmm8, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271B540D44280" , vpaddq(zmm8, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271B540D482C0DFFFFF" , vpaddq(zmm8, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271B550D4427F" , vpaddq(zmm8, zmm25, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271B550D48200040000" , vpaddq(zmm8, zmm25, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271B550D44280" , vpaddq(zmm8, zmm25, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271B550D482F8FBFFFF" , vpaddq(zmm8, zmm25, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62814D40DBD9" , vpandd(zmm19, zmm22, zmm25)); + TEST_INSTRUCTION("62814D41DBD9" , k(k1).vpandd(zmm19, zmm22, zmm25)); + TEST_INSTRUCTION("62814DC1DBD9" , k(k1).z().vpandd(zmm19, zmm22, zmm25)); + TEST_INSTRUCTION("62E14D40DB19" , vpandd(zmm19, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A14D40DB9CF023010000" , vpandd(zmm19, zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E14D50DB19" , vpandd(zmm19, zmm22, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E14D40DB5A7F" , vpandd(zmm19, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E14D40DB9A00200000" , vpandd(zmm19, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E14D40DB5A80" , vpandd(zmm19, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E14D40DB9AC0DFFFFF" , vpandd(zmm19, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E14D50DB5A7F" , vpandd(zmm19, zmm22, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E14D50DB9A00020000" , vpandd(zmm19, zmm22, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E14D50DB5A80" , vpandd(zmm19, zmm22, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E14D50DB9AFCFDFFFF" , vpandd(zmm19, zmm22, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62411D40DFF7" , vpandnd(zmm30, zmm28, zmm15)); + TEST_INSTRUCTION("62411D43DFF7" , k(k3).vpandnd(zmm30, zmm28, zmm15)); + TEST_INSTRUCTION("62411DC3DFF7" , k(k3).z().vpandnd(zmm30, zmm28, zmm15)); + TEST_INSTRUCTION("62611D40DF31" , vpandnd(zmm30, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62211D40DFB4F023010000" , vpandnd(zmm30, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62611D50DF31" , vpandnd(zmm30, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62611D40DF727F" , vpandnd(zmm30, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62611D40DFB200200000" , vpandnd(zmm30, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62611D40DF7280" , vpandnd(zmm30, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62611D40DFB2C0DFFFFF" , vpandnd(zmm30, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62611D50DF727F" , vpandnd(zmm30, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62611D50DFB200020000" , vpandnd(zmm30, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62611D50DF7280" , vpandnd(zmm30, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62611D50DFB2FCFDFFFF" , vpandnd(zmm30, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A1C548DFE3" , vpandnq(zmm20, zmm7, zmm19)); + TEST_INSTRUCTION("62A1C54DDFE3" , k(k5).vpandnq(zmm20, zmm7, zmm19)); + TEST_INSTRUCTION("62A1C5CDDFE3" , k(k5).z().vpandnq(zmm20, zmm7, zmm19)); + TEST_INSTRUCTION("62E1C548DF21" , vpandnq(zmm20, zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1C548DFA4F023010000" , vpandnq(zmm20, zmm7, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1C558DF21" , vpandnq(zmm20, zmm7, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1C548DF627F" , vpandnq(zmm20, zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1C548DFA200200000" , vpandnq(zmm20, zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1C548DF6280" , vpandnq(zmm20, zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1C548DFA2C0DFFFFF" , vpandnq(zmm20, zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1C558DF627F" , vpandnq(zmm20, zmm7, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1C558DFA200040000" , vpandnq(zmm20, zmm7, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1C558DF6280" , vpandnq(zmm20, zmm7, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1C558DFA2F8FBFFFF" , vpandnq(zmm20, zmm7, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6281DD48DBCA" , vpandq(zmm17, zmm4, zmm26)); + TEST_INSTRUCTION("6281DD4FDBCA" , k(k7).vpandq(zmm17, zmm4, zmm26)); + TEST_INSTRUCTION("6281DDCFDBCA" , k(k7).z().vpandq(zmm17, zmm4, zmm26)); + TEST_INSTRUCTION("62E1DD48DB09" , vpandq(zmm17, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1DD48DB8CF023010000" , vpandq(zmm17, zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1DD58DB09" , vpandq(zmm17, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1DD48DB4A7F" , vpandq(zmm17, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1DD48DB8A00200000" , vpandq(zmm17, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1DD48DB4A80" , vpandq(zmm17, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1DD48DB8AC0DFFFFF" , vpandq(zmm17, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1DD58DB4A7F" , vpandq(zmm17, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1DD58DB8A00040000" , vpandq(zmm17, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1DD58DB4A80" , vpandq(zmm17, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1DD58DB8AF8FBFFFF" , vpandq(zmm17, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D2354064EB" , vpblendmd(zmm5, zmm25, zmm11)); + TEST_INSTRUCTION("62D2354364EB" , k(k3).vpblendmd(zmm5, zmm25, zmm11)); + TEST_INSTRUCTION("62D235C364EB" , k(k3).z().vpblendmd(zmm5, zmm25, zmm11)); + TEST_INSTRUCTION("62F235406429" , vpblendmd(zmm5, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2354064ACF023010000" , vpblendmd(zmm5, zmm25, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F235506429" , vpblendmd(zmm5, zmm25, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F23540646A7F" , vpblendmd(zmm5, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2354064AA00200000" , vpblendmd(zmm5, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F23540646A80" , vpblendmd(zmm5, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2354064AAC0DFFFFF" , vpblendmd(zmm5, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F23550646A7F" , vpblendmd(zmm5, zmm25, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F2355064AA00020000" , vpblendmd(zmm5, zmm25, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F23550646A80" , vpblendmd(zmm5, zmm25, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F2355064AAFCFDFFFF" , vpblendmd(zmm5, zmm25, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62627D485811" , vpbroadcastd(zmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62627D4A5811" , k(k2).vpbroadcastd(zmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62627DCA5811" , k(k2).z().vpbroadcastd(zmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62227D485894F023010000" , vpbroadcastd(zmm26, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62627D4858527F" , vpbroadcastd(zmm26, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62627D48589200020000" , vpbroadcastd(zmm26, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62627D48585280" , vpbroadcastd(zmm26, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62627D485892FCFDFFFF" , vpbroadcastd(zmm26, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62327D4858D6" , vpbroadcastd(zmm10, xmm22)); + TEST_INSTRUCTION("62327D4F58D6" , k(k7).vpbroadcastd(zmm10, xmm22)); + TEST_INSTRUCTION("62327DCF58D6" , k(k7).z().vpbroadcastd(zmm10, xmm22)); + TEST_INSTRUCTION("62727D487CD8" , vpbroadcastd(zmm11, eax)); + TEST_INSTRUCTION("62727D4E7CD8" , k(k6).vpbroadcastd(zmm11, eax)); + TEST_INSTRUCTION("62727DCE7CD8" , k(k6).z().vpbroadcastd(zmm11, eax)); + TEST_INSTRUCTION("62727D487CDD" , vpbroadcastd(zmm11, ebp)); + TEST_INSTRUCTION("62527D487CDD" , vpbroadcastd(zmm11, r13d)); + TEST_INSTRUCTION("6262FD485909" , vpbroadcastq(zmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6262FD4A5909" , k(k2).vpbroadcastq(zmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6262FDCA5909" , k(k2).z().vpbroadcastq(zmm25, qword_ptr(rcx))); + TEST_INSTRUCTION("6222FD48598CF023010000" , vpbroadcastq(zmm25, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262FD48594A7F" , vpbroadcastq(zmm25, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262FD48598A00040000" , vpbroadcastq(zmm25, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262FD48594A80" , vpbroadcastq(zmm25, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262FD48598AF8FBFFFF" , vpbroadcastq(zmm25, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62F2FD4859DD" , vpbroadcastq(zmm3, xmm5)); + TEST_INSTRUCTION("62F2FD4D59DD" , k(k5).vpbroadcastq(zmm3, xmm5)); + TEST_INSTRUCTION("62F2FDCD59DD" , k(k5).z().vpbroadcastq(zmm3, xmm5)); + TEST_INSTRUCTION("62F2FD487CC8" , vpbroadcastq(zmm1, rax)); + TEST_INSTRUCTION("62F2FD4E7CC8" , k(k6).vpbroadcastq(zmm1, rax)); + TEST_INSTRUCTION("62F2FDCE7CC8" , k(k6).z().vpbroadcastq(zmm1, rax)); + TEST_INSTRUCTION("62D2FD487CC8" , vpbroadcastq(zmm1, r8)); + TEST_INSTRUCTION("62D335401FEAAB" , vpcmpd(k5, zmm25, zmm10, 171)); + TEST_INSTRUCTION("62D335431FEAAB" , k(k3).vpcmpd(k5, zmm25, zmm10, 171)); + TEST_INSTRUCTION("62D335401FEA7B" , vpcmpd(k5, zmm25, zmm10, 123)); + TEST_INSTRUCTION("62F335401F297B" , vpcmpd(k5, zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B335401FACF0230100007B" , vpcmpd(k5, zmm25, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F335501F297B" , vpcmpd(k5, zmm25, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F335401F6A7F7B" , vpcmpd(k5, zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F335401FAA002000007B" , vpcmpd(k5, zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F335401F6A807B" , vpcmpd(k5, zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F335401FAAC0DFFFFF7B" , vpcmpd(k5, zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F335501F6A7F7B" , vpcmpd(k5, zmm25, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F335501FAA000200007B" , vpcmpd(k5, zmm25, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F335501F6A807B" , vpcmpd(k5, zmm25, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F335501FAAFCFDFFFF7B" , vpcmpd(k5, zmm25, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D16D4876EA" , vpcmpeqd(k5, zmm2, zmm10)); + TEST_INSTRUCTION("62D16D4F76EA" , k(k7).vpcmpeqd(k5, zmm2, zmm10)); + TEST_INSTRUCTION("62F16D487629" , vpcmpeqd(k5, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B16D4876ACF023010000" , vpcmpeqd(k5, zmm2, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F16D587629" , vpcmpeqd(k5, zmm2, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F16D48766A7F" , vpcmpeqd(k5, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F16D4876AA00200000" , vpcmpeqd(k5, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F16D48766A80" , vpcmpeqd(k5, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F16D4876AAC0DFFFFF" , vpcmpeqd(k5, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F16D58766A7F" , vpcmpeqd(k5, zmm2, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F16D5876AA00020000" , vpcmpeqd(k5, zmm2, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F16D58766A80" , vpcmpeqd(k5, zmm2, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F16D5876AAFCFDFFFF" , vpcmpeqd(k5, zmm2, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2CD4029DA" , vpcmpeqq(k3, zmm22, zmm2)); + TEST_INSTRUCTION("62F2CD4629DA" , k(k6).vpcmpeqq(k3, zmm22, zmm2)); + TEST_INSTRUCTION("62F2CD402919" , vpcmpeqq(k3, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2CD40299CF023010000" , vpcmpeqq(k3, zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2CD502919" , vpcmpeqq(k3, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2CD40295A7F" , vpcmpeqq(k3, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2CD40299A00200000" , vpcmpeqq(k3, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2CD40295A80" , vpcmpeqq(k3, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2CD40299AC0DFFFFF" , vpcmpeqq(k3, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2CD50295A7F" , vpcmpeqq(k3, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2CD50299A00040000" , vpcmpeqq(k3, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2CD50295A80" , vpcmpeqq(k3, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2CD50299AF8FBFFFF" , vpcmpeqq(k3, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D1554066E8" , vpcmpgtd(k5, zmm21, zmm8)); + TEST_INSTRUCTION("62D1554566E8" , k(k5).vpcmpgtd(k5, zmm21, zmm8)); + TEST_INSTRUCTION("62F155406629" , vpcmpgtd(k5, zmm21, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1554066ACF023010000" , vpcmpgtd(k5, zmm21, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F155506629" , vpcmpgtd(k5, zmm21, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F15540666A7F" , vpcmpgtd(k5, zmm21, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1554066AA00200000" , vpcmpgtd(k5, zmm21, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F15540666A80" , vpcmpgtd(k5, zmm21, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1554066AAC0DFFFFF" , vpcmpgtd(k5, zmm21, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F15550666A7F" , vpcmpgtd(k5, zmm21, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F1555066AA00020000" , vpcmpgtd(k5, zmm21, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F15550666A80" , vpcmpgtd(k5, zmm21, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F1555066AAFCFDFFFF" , vpcmpgtd(k5, zmm21, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B2DD4037D1" , vpcmpgtq(k2, zmm20, zmm17)); + TEST_INSTRUCTION("62B2DD4337D1" , k(k3).vpcmpgtq(k2, zmm20, zmm17)); + TEST_INSTRUCTION("62F2DD403711" , vpcmpgtq(k2, zmm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2DD403794F023010000" , vpcmpgtq(k2, zmm20, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2DD503711" , vpcmpgtq(k2, zmm20, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2DD4037527F" , vpcmpgtq(k2, zmm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2DD40379200200000" , vpcmpgtq(k2, zmm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2DD40375280" , vpcmpgtq(k2, zmm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2DD403792C0DFFFFF" , vpcmpgtq(k2, zmm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2DD5037527F" , vpcmpgtq(k2, zmm20, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2DD50379200040000" , vpcmpgtq(k2, zmm20, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2DD50375280" , vpcmpgtq(k2, zmm20, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2DD503792F8FBFFFF" , vpcmpgtq(k2, zmm20, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62939D401FECAB" , vpcmpq(k5, zmm28, zmm28, 171)); + TEST_INSTRUCTION("62939D431FECAB" , k(k3).vpcmpq(k5, zmm28, zmm28, 171)); + TEST_INSTRUCTION("62939D401FEC7B" , vpcmpq(k5, zmm28, zmm28, 123)); + TEST_INSTRUCTION("62F39D401F297B" , vpcmpq(k5, zmm28, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B39D401FACF0230100007B" , vpcmpq(k5, zmm28, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F39D501F297B" , vpcmpq(k5, zmm28, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F39D401F6A7F7B" , vpcmpq(k5, zmm28, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F39D401FAA002000007B" , vpcmpq(k5, zmm28, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F39D401F6A807B" , vpcmpq(k5, zmm28, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F39D401FAAC0DFFFFF7B" , vpcmpq(k5, zmm28, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F39D501F6A7F7B" , vpcmpq(k5, zmm28, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F39D501FAA000400007B" , vpcmpq(k5, zmm28, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F39D501F6A807B" , vpcmpq(k5, zmm28, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F39D501FAAF8FBFFFF7B" , vpcmpq(k5, zmm28, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F335401ED7AB" , vpcmpud(k2, zmm25, zmm7, 171)); + TEST_INSTRUCTION("62F335411ED7AB" , k(k1).vpcmpud(k2, zmm25, zmm7, 171)); + TEST_INSTRUCTION("62F335401ED77B" , vpcmpud(k2, zmm25, zmm7, 123)); + TEST_INSTRUCTION("62F335401E117B" , vpcmpud(k2, zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B335401E94F0230100007B" , vpcmpud(k2, zmm25, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F335501E117B" , vpcmpud(k2, zmm25, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F335401E527F7B" , vpcmpud(k2, zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F335401E92002000007B" , vpcmpud(k2, zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F335401E52807B" , vpcmpud(k2, zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F335401E92C0DFFFFF7B" , vpcmpud(k2, zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F335501E527F7B" , vpcmpud(k2, zmm25, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F335501E92000200007B" , vpcmpud(k2, zmm25, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F335501E52807B" , vpcmpud(k2, zmm25, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F335501E92FCFDFFFF7B" , vpcmpud(k2, zmm25, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D38D481ED8AB" , vpcmpuq(k3, zmm14, zmm8, 171)); + TEST_INSTRUCTION("62D38D4A1ED8AB" , k(k2).vpcmpuq(k3, zmm14, zmm8, 171)); + TEST_INSTRUCTION("62D38D481ED87B" , vpcmpuq(k3, zmm14, zmm8, 123)); + TEST_INSTRUCTION("62F38D481E197B" , vpcmpuq(k3, zmm14, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B38D481E9CF0230100007B" , vpcmpuq(k3, zmm14, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F38D581E197B" , vpcmpuq(k3, zmm14, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F38D481E5A7F7B" , vpcmpuq(k3, zmm14, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F38D481E9A002000007B" , vpcmpuq(k3, zmm14, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F38D481E5A807B" , vpcmpuq(k3, zmm14, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F38D481E9AC0DFFFFF7B" , vpcmpuq(k3, zmm14, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F38D581E5A7F7B" , vpcmpuq(k3, zmm14, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F38D581E9A000400007B" , vpcmpuq(k3, zmm14, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F38D581E5A807B" , vpcmpuq(k3, zmm14, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F38D581E9AF8FBFFFF7B" , vpcmpuq(k3, zmm14, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62228D4864D9" , vpblendmq(zmm27, zmm14, zmm17)); + TEST_INSTRUCTION("62228D4D64D9" , k(k5).vpblendmq(zmm27, zmm14, zmm17)); + TEST_INSTRUCTION("62228DCD64D9" , k(k5).z().vpblendmq(zmm27, zmm14, zmm17)); + TEST_INSTRUCTION("62628D486419" , vpblendmq(zmm27, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62228D48649CF023010000" , vpblendmq(zmm27, zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62628D586419" , vpblendmq(zmm27, zmm14, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62628D48645A7F" , vpblendmq(zmm27, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62628D48649A00200000" , vpblendmq(zmm27, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62628D48645A80" , vpblendmq(zmm27, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62628D48649AC0DFFFFF" , vpblendmq(zmm27, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62628D58645A7F" , vpblendmq(zmm27, zmm14, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62628D58649A00040000" , vpblendmq(zmm27, zmm14, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62628D58645A80" , vpblendmq(zmm27, zmm14, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62628D58649AF8FBFFFF" , vpblendmq(zmm27, zmm14, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E27D488B39" , vpcompressd(zmmword_ptr(rcx), zmm23)); + TEST_INSTRUCTION("62E27D4F8B39" , k(k7).vpcompressd(zmmword_ptr(rcx), zmm23)); + TEST_INSTRUCTION("62A27D488BBCF023010000" , vpcompressd(zmmword_ptr(rax, r14, 3, 291), zmm23)); + TEST_INSTRUCTION("62E27D488B7A7F" , vpcompressd(zmmword_ptr(rdx, 508), zmm23)); + TEST_INSTRUCTION("62E27D488BBA00020000" , vpcompressd(zmmword_ptr(rdx, 512), zmm23)); + TEST_INSTRUCTION("62E27D488B7A80" , vpcompressd(zmmword_ptr(rdx, -512), zmm23)); + TEST_INSTRUCTION("62E27D488BBAFCFDFFFF" , vpcompressd(zmmword_ptr(rdx, -516), zmm23)); + TEST_INSTRUCTION("62A27D488BD0" , vpcompressd(zmm16, zmm18)); + TEST_INSTRUCTION("62A27D4A8BD0" , k(k2).vpcompressd(zmm16, zmm18)); + TEST_INSTRUCTION("62A27DCA8BD0" , k(k2).z().vpcompressd(zmm16, zmm18)); + TEST_INSTRUCTION("62C21D4036F1" , vpermd(zmm22, zmm28, zmm9)); + TEST_INSTRUCTION("62C21D4136F1" , k(k1).vpermd(zmm22, zmm28, zmm9)); + TEST_INSTRUCTION("62C21DC136F1" , k(k1).z().vpermd(zmm22, zmm28, zmm9)); + TEST_INSTRUCTION("62E21D403631" , vpermd(zmm22, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A21D4036B4F023010000" , vpermd(zmm22, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E21D503631" , vpermd(zmm22, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E21D4036727F" , vpermd(zmm22, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E21D4036B200200000" , vpermd(zmm22, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E21D40367280" , vpermd(zmm22, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E21D4036B2C0DFFFFF" , vpermd(zmm22, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E21D5036727F" , vpermd(zmm22, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E21D5036B200020000" , vpermd(zmm22, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E21D50367280" , vpermd(zmm22, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E21D5036B2FCFDFFFF" , vpermd(zmm22, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62E3FD4805DCAB" , vpermilpd(zmm19, zmm4, 171)); + TEST_INSTRUCTION("62E3FD4905DCAB" , k(k1).vpermilpd(zmm19, zmm4, 171)); + TEST_INSTRUCTION("62E3FDC905DCAB" , k(k1).z().vpermilpd(zmm19, zmm4, 171)); + TEST_INSTRUCTION("62E3FD4805DC7B" , vpermilpd(zmm19, zmm4, 123)); + TEST_INSTRUCTION("62E3FD4805197B" , vpermilpd(zmm19, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A3FD48059CF0230100007B" , vpermilpd(zmm19, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62E3FD5805197B" , vpermilpd(zmm19, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD48055A7F7B" , vpermilpd(zmm19, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62E3FD48059A002000007B" , vpermilpd(zmm19, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62E3FD48055A807B" , vpermilpd(zmm19, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62E3FD48059AC0DFFFFF7B" , vpermilpd(zmm19, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62E3FD58055A7F7B" , vpermilpd(zmm19, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD58059A000400007B" , vpermilpd(zmm19, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD58055A807B" , vpermilpd(zmm19, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD58059AF8FBFFFF7B" , vpermilpd(zmm19, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62B2AD400DCD" , vpermilpd(zmm1, zmm26, zmm21)); + TEST_INSTRUCTION("62B2AD420DCD" , k(k2).vpermilpd(zmm1, zmm26, zmm21)); + TEST_INSTRUCTION("62B2ADC20DCD" , k(k2).z().vpermilpd(zmm1, zmm26, zmm21)); + TEST_INSTRUCTION("62F2AD400D09" , vpermilpd(zmm1, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2AD400D8CF023010000" , vpermilpd(zmm1, zmm26, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2AD500D09" , vpermilpd(zmm1, zmm26, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2AD400D4A7F" , vpermilpd(zmm1, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2AD400D8A00200000" , vpermilpd(zmm1, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2AD400D4A80" , vpermilpd(zmm1, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2AD400D8AC0DFFFFF" , vpermilpd(zmm1, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2AD500D4A7F" , vpermilpd(zmm1, zmm26, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2AD500D8A00040000" , vpermilpd(zmm1, zmm26, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2AD500D4A80" , vpermilpd(zmm1, zmm26, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2AD500D8AF8FBFFFF" , vpermilpd(zmm1, zmm26, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B37D4804D6AB" , vpermilps(zmm2, zmm22, 171)); + TEST_INSTRUCTION("62B37D4A04D6AB" , k(k2).vpermilps(zmm2, zmm22, 171)); + TEST_INSTRUCTION("62B37DCA04D6AB" , k(k2).z().vpermilps(zmm2, zmm22, 171)); + TEST_INSTRUCTION("62B37D4804D67B" , vpermilps(zmm2, zmm22, 123)); + TEST_INSTRUCTION("62F37D4804117B" , vpermilps(zmm2, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B37D480494F0230100007B" , vpermilps(zmm2, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F37D5804117B" , vpermilps(zmm2, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F37D4804527F7B" , vpermilps(zmm2, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F37D480492002000007B" , vpermilps(zmm2, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F37D480452807B" , vpermilps(zmm2, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F37D480492C0DFFFFF7B" , vpermilps(zmm2, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F37D5804527F7B" , vpermilps(zmm2, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F37D580492000200007B" , vpermilps(zmm2, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F37D580452807B" , vpermilps(zmm2, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F37D580492FCFDFFFF7B" , vpermilps(zmm2, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62725D400CEA" , vpermilps(zmm13, zmm20, zmm2)); + TEST_INSTRUCTION("62725D410CEA" , k(k1).vpermilps(zmm13, zmm20, zmm2)); + TEST_INSTRUCTION("62725DC10CEA" , k(k1).z().vpermilps(zmm13, zmm20, zmm2)); + TEST_INSTRUCTION("62725D400C29" , vpermilps(zmm13, zmm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62325D400CACF023010000" , vpermilps(zmm13, zmm20, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62725D500C29" , vpermilps(zmm13, zmm20, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62725D400C6A7F" , vpermilps(zmm13, zmm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62725D400CAA00200000" , vpermilps(zmm13, zmm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62725D400C6A80" , vpermilps(zmm13, zmm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62725D400CAAC0DFFFFF" , vpermilps(zmm13, zmm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62725D500C6A7F" , vpermilps(zmm13, zmm20, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62725D500CAA00020000" , vpermilps(zmm13, zmm20, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62725D500C6A80" , vpermilps(zmm13, zmm20, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62725D500CAAFCFDFFFF" , vpermilps(zmm13, zmm20, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6293FD4801DBAB" , vpermpd(zmm3, zmm27, 171)); + TEST_INSTRUCTION("6293FD4A01DBAB" , k(k2).vpermpd(zmm3, zmm27, 171)); + TEST_INSTRUCTION("6293FDCA01DBAB" , k(k2).z().vpermpd(zmm3, zmm27, 171)); + TEST_INSTRUCTION("6293FD4801DB7B" , vpermpd(zmm3, zmm27, 123)); + TEST_INSTRUCTION("62F3FD4801197B" , vpermpd(zmm3, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3FD48019CF0230100007B" , vpermpd(zmm3, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F3FD5801197B" , vpermpd(zmm3, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD48015A7F7B" , vpermpd(zmm3, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F3FD48019A002000007B" , vpermpd(zmm3, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F3FD48015A807B" , vpermpd(zmm3, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F3FD48019AC0DFFFFF7B" , vpermpd(zmm3, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F3FD58015A7F7B" , vpermpd(zmm3, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD58019A000400007B" , vpermpd(zmm3, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD58015A807B" , vpermpd(zmm3, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD58019AF8FBFFFF7B" , vpermpd(zmm3, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62926D4816E0" , vpermps(zmm4, zmm2, zmm24)); + TEST_INSTRUCTION("62926D4C16E0" , k(k4).vpermps(zmm4, zmm2, zmm24)); + TEST_INSTRUCTION("62926DCC16E0" , k(k4).z().vpermps(zmm4, zmm2, zmm24)); + TEST_INSTRUCTION("62F26D481621" , vpermps(zmm4, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B26D4816A4F023010000" , vpermps(zmm4, zmm2, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F26D581621" , vpermps(zmm4, zmm2, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F26D4816627F" , vpermps(zmm4, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F26D4816A200200000" , vpermps(zmm4, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F26D48166280" , vpermps(zmm4, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F26D4816A2C0DFFFFF" , vpermps(zmm4, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F26D5816627F" , vpermps(zmm4, zmm2, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F26D5816A200020000" , vpermps(zmm4, zmm2, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F26D58166280" , vpermps(zmm4, zmm2, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F26D5816A2FCFDFFFF" , vpermps(zmm4, zmm2, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6263FD4800CCAB" , vpermq(zmm25, zmm4, 171)); + TEST_INSTRUCTION("6263FD4E00CCAB" , k(k6).vpermq(zmm25, zmm4, 171)); + TEST_INSTRUCTION("6263FDCE00CCAB" , k(k6).z().vpermq(zmm25, zmm4, 171)); + TEST_INSTRUCTION("6263FD4800CC7B" , vpermq(zmm25, zmm4, 123)); + TEST_INSTRUCTION("6263FD4800097B" , vpermq(zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223FD48008CF0230100007B" , vpermq(zmm25, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6263FD5800097B" , vpermq(zmm25, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6263FD48004A7F7B" , vpermq(zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6263FD48008A002000007B" , vpermq(zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6263FD48004A807B" , vpermq(zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6263FD48008AC0DFFFFF7B" , vpermq(zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6263FD58004A7F7B" , vpermq(zmm25, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6263FD58008A000400007B" , vpermq(zmm25, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6263FD58004A807B" , vpermq(zmm25, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6263FD58008AF8FBFFFF7B" , vpermq(zmm25, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F27D488909" , vpexpandd(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27D4F8909" , k(k7).vpexpandd(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27DCF8909" , k(k7).z().vpexpandd(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D48898CF023010000" , vpexpandd(zmm1, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D48894A7F" , vpexpandd(zmm1, zmmword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F27D48898A00020000" , vpexpandd(zmm1, zmmword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F27D48894A80" , vpexpandd(zmm1, zmmword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F27D48898AFCFDFFFF" , vpexpandd(zmm1, zmmword_ptr(rdx, -516))); + TEST_INSTRUCTION("62827D4889D9" , vpexpandd(zmm19, zmm25)); + TEST_INSTRUCTION("62827D4D89D9" , k(k5).vpexpandd(zmm19, zmm25)); + TEST_INSTRUCTION("62827DCD89D9" , k(k5).z().vpexpandd(zmm19, zmm25)); + TEST_INSTRUCTION("6262FD488901" , vpexpandq(zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6262FD4F8901" , k(k7).vpexpandq(zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6262FDCF8901" , k(k7).z().vpexpandq(zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222FD488984F023010000" , vpexpandq(zmm24, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262FD4889427F" , vpexpandq(zmm24, zmmword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262FD48898200040000" , vpexpandq(zmm24, zmmword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262FD48894280" , vpexpandq(zmm24, zmmword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262FD488982F8FBFFFF" , vpexpandq(zmm24, zmmword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6252FD4889F8" , vpexpandq(zmm15, zmm8)); + TEST_INSTRUCTION("6252FD4F89F8" , k(k7).vpexpandq(zmm15, zmm8)); + TEST_INSTRUCTION("6252FDCF89F8" , k(k7).z().vpexpandq(zmm15, zmm8)); + TEST_INSTRUCTION("62B23D483DF0" , vpmaxsd(zmm6, zmm8, zmm16)); + TEST_INSTRUCTION("62B23D4B3DF0" , k(k3).vpmaxsd(zmm6, zmm8, zmm16)); + TEST_INSTRUCTION("62B23DCB3DF0" , k(k3).z().vpmaxsd(zmm6, zmm8, zmm16)); + TEST_INSTRUCTION("62F23D483D31" , vpmaxsd(zmm6, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B23D483DB4F023010000" , vpmaxsd(zmm6, zmm8, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F23D583D31" , vpmaxsd(zmm6, zmm8, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F23D483D727F" , vpmaxsd(zmm6, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F23D483DB200200000" , vpmaxsd(zmm6, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F23D483D7280" , vpmaxsd(zmm6, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F23D483DB2C0DFFFFF" , vpmaxsd(zmm6, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F23D583D727F" , vpmaxsd(zmm6, zmm8, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F23D583DB200020000" , vpmaxsd(zmm6, zmm8, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F23D583D7280" , vpmaxsd(zmm6, zmm8, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F23D583DB2FCFDFFFF" , vpmaxsd(zmm6, zmm8, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2CD483DF1" , vpmaxsq(zmm6, zmm6, zmm1)); + TEST_INSTRUCTION("62F2CD4F3DF1" , k(k7).vpmaxsq(zmm6, zmm6, zmm1)); + TEST_INSTRUCTION("62F2CDCF3DF1" , k(k7).z().vpmaxsq(zmm6, zmm6, zmm1)); + TEST_INSTRUCTION("62F2CD483D31" , vpmaxsq(zmm6, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2CD483DB4F023010000" , vpmaxsq(zmm6, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2CD583D31" , vpmaxsq(zmm6, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2CD483D727F" , vpmaxsq(zmm6, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2CD483DB200200000" , vpmaxsq(zmm6, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2CD483D7280" , vpmaxsq(zmm6, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2CD483DB2C0DFFFFF" , vpmaxsq(zmm6, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2CD583D727F" , vpmaxsq(zmm6, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2CD583DB200040000" , vpmaxsq(zmm6, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2CD583D7280" , vpmaxsq(zmm6, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2CD583DB2F8FBFFFF" , vpmaxsq(zmm6, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("628245483FC9" , vpmaxud(zmm17, zmm7, zmm25)); + TEST_INSTRUCTION("6282454D3FC9" , k(k5).vpmaxud(zmm17, zmm7, zmm25)); + TEST_INSTRUCTION("628245CD3FC9" , k(k5).z().vpmaxud(zmm17, zmm7, zmm25)); + TEST_INSTRUCTION("62E245483F09" , vpmaxud(zmm17, zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A245483F8CF023010000" , vpmaxud(zmm17, zmm7, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E245583F09" , vpmaxud(zmm17, zmm7, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E245483F4A7F" , vpmaxud(zmm17, zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E245483F8A00200000" , vpmaxud(zmm17, zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E245483F4A80" , vpmaxud(zmm17, zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E245483F8AC0DFFFFF" , vpmaxud(zmm17, zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E245583F4A7F" , vpmaxud(zmm17, zmm7, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E245583F8A00020000" , vpmaxud(zmm17, zmm7, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E245583F4A80" , vpmaxud(zmm17, zmm7, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E245583F8AFCFDFFFF" , vpmaxud(zmm17, zmm7, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6202CD403FF1" , vpmaxuq(zmm30, zmm22, zmm25)); + TEST_INSTRUCTION("6202CD413FF1" , k(k1).vpmaxuq(zmm30, zmm22, zmm25)); + TEST_INSTRUCTION("6202CDC13FF1" , k(k1).z().vpmaxuq(zmm30, zmm22, zmm25)); + TEST_INSTRUCTION("6262CD403F31" , vpmaxuq(zmm30, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222CD403FB4F023010000" , vpmaxuq(zmm30, zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262CD503F31" , vpmaxuq(zmm30, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262CD403F727F" , vpmaxuq(zmm30, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262CD403FB200200000" , vpmaxuq(zmm30, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262CD403F7280" , vpmaxuq(zmm30, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262CD403FB2C0DFFFFF" , vpmaxuq(zmm30, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262CD503F727F" , vpmaxuq(zmm30, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262CD503FB200040000" , vpmaxuq(zmm30, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262CD503F7280" , vpmaxuq(zmm30, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262CD503FB2F8FBFFFF" , vpmaxuq(zmm30, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62927D4039D0" , vpminsd(zmm2, zmm16, zmm24)); + TEST_INSTRUCTION("62927D4339D0" , k(k3).vpminsd(zmm2, zmm16, zmm24)); + TEST_INSTRUCTION("62927DC339D0" , k(k3).z().vpminsd(zmm2, zmm16, zmm24)); + TEST_INSTRUCTION("62F27D403911" , vpminsd(zmm2, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D403994F023010000" , vpminsd(zmm2, zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D503911" , vpminsd(zmm2, zmm16, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27D4039527F" , vpminsd(zmm2, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27D40399200200000" , vpminsd(zmm2, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27D40395280" , vpminsd(zmm2, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27D403992C0DFFFFF" , vpminsd(zmm2, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27D5039527F" , vpminsd(zmm2, zmm16, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27D50399200020000" , vpminsd(zmm2, zmm16, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27D50395280" , vpminsd(zmm2, zmm16, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27D503992FCFDFFFF" , vpminsd(zmm2, zmm16, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A2FD4039E1" , vpminsq(zmm20, zmm16, zmm17)); + TEST_INSTRUCTION("62A2FD4639E1" , k(k6).vpminsq(zmm20, zmm16, zmm17)); + TEST_INSTRUCTION("62A2FDC639E1" , k(k6).z().vpminsq(zmm20, zmm16, zmm17)); + TEST_INSTRUCTION("62E2FD403921" , vpminsq(zmm20, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2FD4039A4F023010000" , vpminsq(zmm20, zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2FD503921" , vpminsq(zmm20, zmm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2FD4039627F" , vpminsq(zmm20, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2FD4039A200200000" , vpminsq(zmm20, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2FD40396280" , vpminsq(zmm20, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2FD4039A2C0DFFFFF" , vpminsq(zmm20, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2FD5039627F" , vpminsq(zmm20, zmm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2FD5039A200040000" , vpminsq(zmm20, zmm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2FD50396280" , vpminsq(zmm20, zmm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2FD5039A2F8FBFFFF" , vpminsq(zmm20, zmm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B245403BDC" , vpminud(zmm3, zmm23, zmm20)); + TEST_INSTRUCTION("62B245433BDC" , k(k3).vpminud(zmm3, zmm23, zmm20)); + TEST_INSTRUCTION("62B245C33BDC" , k(k3).z().vpminud(zmm3, zmm23, zmm20)); + TEST_INSTRUCTION("62F245403B19" , vpminud(zmm3, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B245403B9CF023010000" , vpminud(zmm3, zmm23, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F245503B19" , vpminud(zmm3, zmm23, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F245403B5A7F" , vpminud(zmm3, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F245403B9A00200000" , vpminud(zmm3, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F245403B5A80" , vpminud(zmm3, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F245403B9AC0DFFFFF" , vpminud(zmm3, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F245503B5A7F" , vpminud(zmm3, zmm23, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F245503B9A00020000" , vpminud(zmm3, zmm23, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F245503B5A80" , vpminud(zmm3, zmm23, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F245503B9AFCFDFFFF" , vpminud(zmm3, zmm23, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6272AD403BDF" , vpminuq(zmm11, zmm26, zmm7)); + TEST_INSTRUCTION("6272AD453BDF" , k(k5).vpminuq(zmm11, zmm26, zmm7)); + TEST_INSTRUCTION("6272ADC53BDF" , k(k5).z().vpminuq(zmm11, zmm26, zmm7)); + TEST_INSTRUCTION("6272AD403B19" , vpminuq(zmm11, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232AD403B9CF023010000" , vpminuq(zmm11, zmm26, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272AD503B19" , vpminuq(zmm11, zmm26, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272AD403B5A7F" , vpminuq(zmm11, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272AD403B9A00200000" , vpminuq(zmm11, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272AD403B5A80" , vpminuq(zmm11, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272AD403B9AC0DFFFFF" , vpminuq(zmm11, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272AD503B5A7F" , vpminuq(zmm11, zmm26, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272AD503B9A00040000" , vpminuq(zmm11, zmm26, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272AD503B5A80" , vpminuq(zmm11, zmm26, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272AD503B9AF8FBFFFF" , vpminuq(zmm11, zmm26, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62627D4821DF" , vpmovsxbd(zmm27, xmm7)); + TEST_INSTRUCTION("62627D4D21DF" , k(k5).vpmovsxbd(zmm27, xmm7)); + TEST_INSTRUCTION("62627DCD21DF" , k(k5).z().vpmovsxbd(zmm27, xmm7)); + TEST_INSTRUCTION("62627D482119" , vpmovsxbd(zmm27, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62227D48219CF023010000" , vpmovsxbd(zmm27, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62627D48215A7F" , vpmovsxbd(zmm27, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62627D48219A00080000" , vpmovsxbd(zmm27, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62627D48215A80" , vpmovsxbd(zmm27, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62627D48219AF0F7FFFF" , vpmovsxbd(zmm27, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62527D4822DB" , vpmovsxbq(zmm11, xmm11)); + TEST_INSTRUCTION("62527D4D22DB" , k(k5).vpmovsxbq(zmm11, xmm11)); + TEST_INSTRUCTION("62527DCD22DB" , k(k5).z().vpmovsxbq(zmm11, xmm11)); + TEST_INSTRUCTION("62727D482219" , vpmovsxbq(zmm11, qword_ptr(rcx))); + TEST_INSTRUCTION("62327D48229CF023010000" , vpmovsxbq(zmm11, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62727D48225A7F" , vpmovsxbq(zmm11, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62727D48229A00040000" , vpmovsxbq(zmm11, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62727D48225A80" , vpmovsxbq(zmm11, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62727D48229AF8FBFFFF" , vpmovsxbq(zmm11, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62027D4825D5" , vpmovsxdq(zmm26, ymm29)); + TEST_INSTRUCTION("62027D4925D5" , k(k1).vpmovsxdq(zmm26, ymm29)); + TEST_INSTRUCTION("62027DC925D5" , k(k1).z().vpmovsxdq(zmm26, ymm29)); + TEST_INSTRUCTION("62627D482511" , vpmovsxdq(zmm26, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62227D482594F023010000" , vpmovsxdq(zmm26, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62627D4825527F" , vpmovsxdq(zmm26, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62627D48259200100000" , vpmovsxdq(zmm26, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62627D48255280" , vpmovsxdq(zmm26, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62627D482592E0EFFFFF" , vpmovsxdq(zmm26, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62C27D4823FB" , vpmovsxwd(zmm23, ymm11)); + TEST_INSTRUCTION("62C27D4A23FB" , k(k2).vpmovsxwd(zmm23, ymm11)); + TEST_INSTRUCTION("62C27DCA23FB" , k(k2).z().vpmovsxwd(zmm23, ymm11)); + TEST_INSTRUCTION("62E27D482339" , vpmovsxwd(zmm23, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D4823BCF023010000" , vpmovsxwd(zmm23, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E27D48237A7F" , vpmovsxwd(zmm23, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62E27D4823BA00100000" , vpmovsxwd(zmm23, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62E27D48237A80" , vpmovsxwd(zmm23, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62E27D4823BAE0EFFFFF" , vpmovsxwd(zmm23, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62027D4824C9" , vpmovsxwq(zmm25, xmm25)); + TEST_INSTRUCTION("62027D4C24C9" , k(k4).vpmovsxwq(zmm25, xmm25)); + TEST_INSTRUCTION("62027DCC24C9" , k(k4).z().vpmovsxwq(zmm25, xmm25)); + TEST_INSTRUCTION("62627D482409" , vpmovsxwq(zmm25, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62227D48248CF023010000" , vpmovsxwq(zmm25, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62627D48244A7F" , vpmovsxwq(zmm25, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62627D48248A00080000" , vpmovsxwq(zmm25, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62627D48244A80" , vpmovsxwq(zmm25, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62627D48248AF0F7FFFF" , vpmovsxwq(zmm25, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62827D4831D1" , vpmovzxbd(zmm18, xmm25)); + TEST_INSTRUCTION("62827D4F31D1" , k(k7).vpmovzxbd(zmm18, xmm25)); + TEST_INSTRUCTION("62827DCF31D1" , k(k7).z().vpmovzxbd(zmm18, xmm25)); + TEST_INSTRUCTION("62E27D483111" , vpmovzxbd(zmm18, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D483194F023010000" , vpmovzxbd(zmm18, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E27D4831527F" , vpmovzxbd(zmm18, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E27D48319200080000" , vpmovzxbd(zmm18, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E27D48315280" , vpmovzxbd(zmm18, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E27D483192F0F7FFFF" , vpmovzxbd(zmm18, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62D27D4832EF" , vpmovzxbq(zmm5, xmm15)); + TEST_INSTRUCTION("62D27D4932EF" , k(k1).vpmovzxbq(zmm5, xmm15)); + TEST_INSTRUCTION("62D27DC932EF" , k(k1).z().vpmovzxbq(zmm5, xmm15)); + TEST_INSTRUCTION("62F27D483229" , vpmovzxbq(zmm5, qword_ptr(rcx))); + TEST_INSTRUCTION("62B27D4832ACF023010000" , vpmovzxbq(zmm5, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D48326A7F" , vpmovzxbq(zmm5, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F27D4832AA00040000" , vpmovzxbq(zmm5, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F27D48326A80" , vpmovzxbq(zmm5, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F27D4832AAF8FBFFFF" , vpmovzxbq(zmm5, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62E27D4835E4" , vpmovzxdq(zmm20, ymm4)); + TEST_INSTRUCTION("62E27D4B35E4" , k(k3).vpmovzxdq(zmm20, ymm4)); + TEST_INSTRUCTION("62E27DCB35E4" , k(k3).z().vpmovzxdq(zmm20, ymm4)); + TEST_INSTRUCTION("62E27D483521" , vpmovzxdq(zmm20, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D4835A4F023010000" , vpmovzxdq(zmm20, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E27D4835627F" , vpmovzxdq(zmm20, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62E27D4835A200100000" , vpmovzxdq(zmm20, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62E27D48356280" , vpmovzxdq(zmm20, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62E27D4835A2E0EFFFFF" , vpmovzxdq(zmm20, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62727D4833C6" , vpmovzxwd(zmm8, ymm6)); + TEST_INSTRUCTION("62727D4F33C6" , k(k7).vpmovzxwd(zmm8, ymm6)); + TEST_INSTRUCTION("62727DCF33C6" , k(k7).z().vpmovzxwd(zmm8, ymm6)); + TEST_INSTRUCTION("62727D483301" , vpmovzxwd(zmm8, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62327D483384F023010000" , vpmovzxwd(zmm8, ymmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62727D4833427F" , vpmovzxwd(zmm8, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62727D48338200100000" , vpmovzxwd(zmm8, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62727D48334280" , vpmovzxwd(zmm8, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62727D483382E0EFFFFF" , vpmovzxwd(zmm8, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62D27D4834EF" , vpmovzxwq(zmm5, xmm15)); + TEST_INSTRUCTION("62D27D4F34EF" , k(k7).vpmovzxwq(zmm5, xmm15)); + TEST_INSTRUCTION("62D27DCF34EF" , k(k7).z().vpmovzxwq(zmm5, xmm15)); + TEST_INSTRUCTION("62F27D483429" , vpmovzxwq(zmm5, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D4834ACF023010000" , vpmovzxwq(zmm5, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F27D48346A7F" , vpmovzxwq(zmm5, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62F27D4834AA00080000" , vpmovzxwq(zmm5, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62F27D48346A80" , vpmovzxwq(zmm5, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62F27D4834AAF0F7FFFF" , vpmovzxwq(zmm5, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6242B54828E9" , vpmuldq(zmm29, zmm9, zmm9)); + TEST_INSTRUCTION("6242B54D28E9" , k(k5).vpmuldq(zmm29, zmm9, zmm9)); + TEST_INSTRUCTION("6242B5CD28E9" , k(k5).z().vpmuldq(zmm29, zmm9, zmm9)); + TEST_INSTRUCTION("6262B5482829" , vpmuldq(zmm29, zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222B54828ACF023010000" , vpmuldq(zmm29, zmm9, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262B5582829" , vpmuldq(zmm29, zmm9, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262B548286A7F" , vpmuldq(zmm29, zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262B54828AA00200000" , vpmuldq(zmm29, zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262B548286A80" , vpmuldq(zmm29, zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262B54828AAC0DFFFFF" , vpmuldq(zmm29, zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262B558286A7F" , vpmuldq(zmm29, zmm9, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262B55828AA00040000" , vpmuldq(zmm29, zmm9, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262B558286A80" , vpmuldq(zmm29, zmm9, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262B55828AAF8FBFFFF" , vpmuldq(zmm29, zmm9, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6272654840E2" , vpmulld(zmm12, zmm3, zmm2)); + TEST_INSTRUCTION("6272654E40E2" , k(k6).vpmulld(zmm12, zmm3, zmm2)); + TEST_INSTRUCTION("627265CE40E2" , k(k6).z().vpmulld(zmm12, zmm3, zmm2)); + TEST_INSTRUCTION("627265484021" , vpmulld(zmm12, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232654840A4F023010000" , vpmulld(zmm12, zmm3, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("627265584021" , vpmulld(zmm12, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("6272654840627F" , vpmulld(zmm12, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272654840A200200000" , vpmulld(zmm12, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62726548406280" , vpmulld(zmm12, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272654840A2C0DFFFFF" , vpmulld(zmm12, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272655840627F" , vpmulld(zmm12, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("6272655840A200020000" , vpmulld(zmm12, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62726558406280" , vpmulld(zmm12, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("6272655840A2FCFDFFFF" , vpmulld(zmm12, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C1D548F4F9" , vpmuludq(zmm23, zmm5, zmm9)); + TEST_INSTRUCTION("62C1D54CF4F9" , k(k4).vpmuludq(zmm23, zmm5, zmm9)); + TEST_INSTRUCTION("62C1D5CCF4F9" , k(k4).z().vpmuludq(zmm23, zmm5, zmm9)); + TEST_INSTRUCTION("62E1D548F439" , vpmuludq(zmm23, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1D548F4BCF023010000" , vpmuludq(zmm23, zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1D558F439" , vpmuludq(zmm23, zmm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1D548F47A7F" , vpmuludq(zmm23, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1D548F4BA00200000" , vpmuludq(zmm23, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1D548F47A80" , vpmuludq(zmm23, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1D548F4BAC0DFFFFF" , vpmuludq(zmm23, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1D558F47A7F" , vpmuludq(zmm23, zmm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1D558F4BA00040000" , vpmuludq(zmm23, zmm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1D558F47A80" , vpmuludq(zmm23, zmm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1D558F4BAF8FBFFFF" , vpmuludq(zmm23, zmm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62A16D48EBFC" , vpord(zmm23, zmm2, zmm20)); + TEST_INSTRUCTION("62A16D4AEBFC" , k(k2).vpord(zmm23, zmm2, zmm20)); + TEST_INSTRUCTION("62A16DCAEBFC" , k(k2).z().vpord(zmm23, zmm2, zmm20)); + TEST_INSTRUCTION("62E16D48EB39" , vpord(zmm23, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A16D48EBBCF023010000" , vpord(zmm23, zmm2, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E16D58EB39" , vpord(zmm23, zmm2, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E16D48EB7A7F" , vpord(zmm23, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E16D48EBBA00200000" , vpord(zmm23, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E16D48EB7A80" , vpord(zmm23, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E16D48EBBAC0DFFFFF" , vpord(zmm23, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E16D58EB7A7F" , vpord(zmm23, zmm2, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E16D58EBBA00020000" , vpord(zmm23, zmm2, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E16D58EB7A80" , vpord(zmm23, zmm2, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E16D58EBBAFCFDFFFF" , vpord(zmm23, zmm2, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F1AD48EBCE" , vporq(zmm1, zmm10, zmm6)); + TEST_INSTRUCTION("62F1AD4AEBCE" , k(k2).vporq(zmm1, zmm10, zmm6)); + TEST_INSTRUCTION("62F1ADCAEBCE" , k(k2).z().vporq(zmm1, zmm10, zmm6)); + TEST_INSTRUCTION("62F1AD48EB09" , vporq(zmm1, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1AD48EB8CF023010000" , vporq(zmm1, zmm10, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1AD58EB09" , vporq(zmm1, zmm10, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1AD48EB4A7F" , vporq(zmm1, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1AD48EB8A00200000" , vporq(zmm1, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1AD48EB4A80" , vporq(zmm1, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1AD48EB8AC0DFFFFF" , vporq(zmm1, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1AD58EB4A7F" , vporq(zmm1, zmm10, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1AD58EB8A00040000" , vporq(zmm1, zmm10, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1AD58EB4A80" , vporq(zmm1, zmm10, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1AD58EB8AF8FBFFFF" , vporq(zmm1, zmm10, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62817D4870D9AB" , vpshufd(zmm19, zmm25, 171)); + TEST_INSTRUCTION("62817D4E70D9AB" , k(k6).vpshufd(zmm19, zmm25, 171)); + TEST_INSTRUCTION("62817DCE70D9AB" , k(k6).z().vpshufd(zmm19, zmm25, 171)); + TEST_INSTRUCTION("62817D4870D97B" , vpshufd(zmm19, zmm25, 123)); + TEST_INSTRUCTION("62E17D4870197B" , vpshufd(zmm19, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A17D48709CF0230100007B" , vpshufd(zmm19, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62E17D5870197B" , vpshufd(zmm19, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62E17D48705A7F7B" , vpshufd(zmm19, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62E17D48709A002000007B" , vpshufd(zmm19, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62E17D48705A807B" , vpshufd(zmm19, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62E17D48709AC0DFFFFF7B" , vpshufd(zmm19, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62E17D58705A7F7B" , vpshufd(zmm19, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62E17D58709A000200007B" , vpshufd(zmm19, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62E17D58705A807B" , vpshufd(zmm19, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62E17D58709AFCFDFFFF7B" , vpshufd(zmm19, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62E14D48F2CB" , vpslld(zmm17, zmm6, xmm3)); + TEST_INSTRUCTION("62E14D4BF2CB" , k(k3).vpslld(zmm17, zmm6, xmm3)); + TEST_INSTRUCTION("62E14DCBF2CB" , k(k3).z().vpslld(zmm17, zmm6, xmm3)); + TEST_INSTRUCTION("62E14D48F209" , vpslld(zmm17, zmm6, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A14D48F28CF023010000" , vpslld(zmm17, zmm6, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E14D48F24A7F" , vpslld(zmm17, zmm6, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E14D48F28A00080000" , vpslld(zmm17, zmm6, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E14D48F24A80" , vpslld(zmm17, zmm6, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E14D48F28AF0F7FFFF" , vpslld(zmm17, zmm6, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6221F540F3D7" , vpsllq(zmm26, zmm17, xmm23)); + TEST_INSTRUCTION("6221F546F3D7" , k(k6).vpsllq(zmm26, zmm17, xmm23)); + TEST_INSTRUCTION("6221F5C6F3D7" , k(k6).z().vpsllq(zmm26, zmm17, xmm23)); + TEST_INSTRUCTION("6261F540F311" , vpsllq(zmm26, zmm17, xmmword_ptr(rcx))); + TEST_INSTRUCTION("6221F540F394F023010000" , vpsllq(zmm26, zmm17, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261F540F3527F" , vpsllq(zmm26, zmm17, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("6261F540F39200080000" , vpsllq(zmm26, zmm17, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("6261F540F35280" , vpsllq(zmm26, zmm17, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("6261F540F392F0F7FFFF" , vpsllq(zmm26, zmm17, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62321D4847D6" , vpsllvd(zmm10, zmm12, zmm22)); + TEST_INSTRUCTION("62321D4E47D6" , k(k6).vpsllvd(zmm10, zmm12, zmm22)); + TEST_INSTRUCTION("62321DCE47D6" , k(k6).z().vpsllvd(zmm10, zmm12, zmm22)); + TEST_INSTRUCTION("62721D484711" , vpsllvd(zmm10, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62321D484794F023010000" , vpsllvd(zmm10, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62721D584711" , vpsllvd(zmm10, zmm12, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62721D4847527F" , vpsllvd(zmm10, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62721D48479200200000" , vpsllvd(zmm10, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62721D48475280" , vpsllvd(zmm10, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62721D484792C0DFFFFF" , vpsllvd(zmm10, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62721D5847527F" , vpsllvd(zmm10, zmm12, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62721D58479200020000" , vpsllvd(zmm10, zmm12, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62721D58475280" , vpsllvd(zmm10, zmm12, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62721D584792FCFDFFFF" , vpsllvd(zmm10, zmm12, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6282D54847C2" , vpsllvq(zmm16, zmm5, zmm26)); + TEST_INSTRUCTION("6282D54D47C2" , k(k5).vpsllvq(zmm16, zmm5, zmm26)); + TEST_INSTRUCTION("6282D5CD47C2" , k(k5).z().vpsllvq(zmm16, zmm5, zmm26)); + TEST_INSTRUCTION("62E2D5484701" , vpsllvq(zmm16, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2D5484784F023010000" , vpsllvq(zmm16, zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2D5584701" , vpsllvq(zmm16, zmm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2D54847427F" , vpsllvq(zmm16, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2D548478200200000" , vpsllvq(zmm16, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2D548474280" , vpsllvq(zmm16, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2D5484782C0DFFFFF" , vpsllvq(zmm16, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2D55847427F" , vpsllvq(zmm16, zmm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2D558478200040000" , vpsllvq(zmm16, zmm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2D558474280" , vpsllvq(zmm16, zmm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2D5584782F8FBFFFF" , vpsllvq(zmm16, zmm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E10D48E2D6" , vpsrad(zmm18, zmm14, xmm6)); + TEST_INSTRUCTION("62E10D49E2D6" , k(k1).vpsrad(zmm18, zmm14, xmm6)); + TEST_INSTRUCTION("62E10DC9E2D6" , k(k1).z().vpsrad(zmm18, zmm14, xmm6)); + TEST_INSTRUCTION("62E10D48E211" , vpsrad(zmm18, zmm14, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A10D48E294F023010000" , vpsrad(zmm18, zmm14, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E10D48E2527F" , vpsrad(zmm18, zmm14, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E10D48E29200080000" , vpsrad(zmm18, zmm14, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E10D48E25280" , vpsrad(zmm18, zmm14, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E10D48E292F0F7FFFF" , vpsrad(zmm18, zmm14, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62A1F540E2EE" , vpsraq(zmm21, zmm17, xmm22)); + TEST_INSTRUCTION("62A1F543E2EE" , k(k3).vpsraq(zmm21, zmm17, xmm22)); + TEST_INSTRUCTION("62A1F5C3E2EE" , k(k3).z().vpsraq(zmm21, zmm17, xmm22)); + TEST_INSTRUCTION("62E1F540E229" , vpsraq(zmm21, zmm17, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1F540E2ACF023010000" , vpsraq(zmm21, zmm17, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1F540E26A7F" , vpsraq(zmm21, zmm17, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E1F540E2AA00080000" , vpsraq(zmm21, zmm17, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E1F540E26A80" , vpsraq(zmm21, zmm17, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E1F540E2AAF0F7FFFF" , vpsraq(zmm21, zmm17, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6222154046E9" , vpsravd(zmm29, zmm29, zmm17)); + TEST_INSTRUCTION("6222154246E9" , k(k2).vpsravd(zmm29, zmm29, zmm17)); + TEST_INSTRUCTION("622215C246E9" , k(k2).z().vpsravd(zmm29, zmm29, zmm17)); + TEST_INSTRUCTION("626215404629" , vpsravd(zmm29, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222154046ACF023010000" , vpsravd(zmm29, zmm29, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626215504629" , vpsravd(zmm29, zmm29, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62621540466A7F" , vpsravd(zmm29, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262154046AA00200000" , vpsravd(zmm29, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62621540466A80" , vpsravd(zmm29, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262154046AAC0DFFFFF" , vpsravd(zmm29, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62621550466A7F" , vpsravd(zmm29, zmm29, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("6262155046AA00020000" , vpsravd(zmm29, zmm29, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62621550466A80" , vpsravd(zmm29, zmm29, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("6262155046AAFCFDFFFF" , vpsravd(zmm29, zmm29, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62E2DD4046F2" , vpsravq(zmm22, zmm20, zmm2)); + TEST_INSTRUCTION("62E2DD4246F2" , k(k2).vpsravq(zmm22, zmm20, zmm2)); + TEST_INSTRUCTION("62E2DDC246F2" , k(k2).z().vpsravq(zmm22, zmm20, zmm2)); + TEST_INSTRUCTION("62E2DD404631" , vpsravq(zmm22, zmm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2DD4046B4F023010000" , vpsravq(zmm22, zmm20, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2DD504631" , vpsravq(zmm22, zmm20, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2DD4046727F" , vpsravq(zmm22, zmm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2DD4046B200200000" , vpsravq(zmm22, zmm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2DD40467280" , vpsravq(zmm22, zmm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2DD4046B2C0DFFFFF" , vpsravq(zmm22, zmm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2DD5046727F" , vpsravq(zmm22, zmm20, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2DD5046B200040000" , vpsravq(zmm22, zmm20, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2DD50467280" , vpsravq(zmm22, zmm20, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2DD5046B2F8FBFFFF" , vpsravq(zmm22, zmm20, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62917540D2C9" , vpsrld(zmm1, zmm17, xmm25)); + TEST_INSTRUCTION("62917544D2C9" , k(k4).vpsrld(zmm1, zmm17, xmm25)); + TEST_INSTRUCTION("629175C4D2C9" , k(k4).z().vpsrld(zmm1, zmm17, xmm25)); + TEST_INSTRUCTION("62F17540D209" , vpsrld(zmm1, zmm17, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17540D28CF023010000" , vpsrld(zmm1, zmm17, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17540D24A7F" , vpsrld(zmm1, zmm17, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62F17540D28A00080000" , vpsrld(zmm1, zmm17, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62F17540D24A80" , vpsrld(zmm1, zmm17, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62F17540D28AF0F7FFFF" , vpsrld(zmm1, zmm17, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6271A548D3CB" , vpsrlq(zmm9, zmm11, xmm3)); + TEST_INSTRUCTION("6271A54DD3CB" , k(k5).vpsrlq(zmm9, zmm11, xmm3)); + TEST_INSTRUCTION("6271A5CDD3CB" , k(k5).z().vpsrlq(zmm9, zmm11, xmm3)); + TEST_INSTRUCTION("6271A548D309" , vpsrlq(zmm9, zmm11, xmmword_ptr(rcx))); + TEST_INSTRUCTION("6231A548D38CF023010000" , vpsrlq(zmm9, zmm11, xmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271A548D34A7F" , vpsrlq(zmm9, zmm11, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("6271A548D38A00080000" , vpsrlq(zmm9, zmm11, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("6271A548D34A80" , vpsrlq(zmm9, zmm11, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("6271A548D38AF0F7FFFF" , vpsrlq(zmm9, zmm11, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62120D4845C4" , vpsrlvd(zmm8, zmm14, zmm28)); + TEST_INSTRUCTION("62120D4C45C4" , k(k4).vpsrlvd(zmm8, zmm14, zmm28)); + TEST_INSTRUCTION("62120DCC45C4" , k(k4).z().vpsrlvd(zmm8, zmm14, zmm28)); + TEST_INSTRUCTION("62720D484501" , vpsrlvd(zmm8, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62320D484584F023010000" , vpsrlvd(zmm8, zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62720D584501" , vpsrlvd(zmm8, zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62720D4845427F" , vpsrlvd(zmm8, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62720D48458200200000" , vpsrlvd(zmm8, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62720D48454280" , vpsrlvd(zmm8, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62720D484582C0DFFFFF" , vpsrlvd(zmm8, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62720D5845427F" , vpsrlvd(zmm8, zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62720D58458200020000" , vpsrlvd(zmm8, zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62720D58454280" , vpsrlvd(zmm8, zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62720D584582FCFDFFFF" , vpsrlvd(zmm8, zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6282C54845E2" , vpsrlvq(zmm20, zmm7, zmm26)); + TEST_INSTRUCTION("6282C54D45E2" , k(k5).vpsrlvq(zmm20, zmm7, zmm26)); + TEST_INSTRUCTION("6282C5CD45E2" , k(k5).z().vpsrlvq(zmm20, zmm7, zmm26)); + TEST_INSTRUCTION("62E2C5484521" , vpsrlvq(zmm20, zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2C54845A4F023010000" , vpsrlvq(zmm20, zmm7, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2C5584521" , vpsrlvq(zmm20, zmm7, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2C54845627F" , vpsrlvq(zmm20, zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2C54845A200200000" , vpsrlvq(zmm20, zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2C548456280" , vpsrlvq(zmm20, zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2C54845A2C0DFFFFF" , vpsrlvq(zmm20, zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2C55845627F" , vpsrlvq(zmm20, zmm7, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2C55845A200040000" , vpsrlvq(zmm20, zmm7, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2C558456280" , vpsrlvq(zmm20, zmm7, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2C55845A2F8FBFFFF" , vpsrlvq(zmm20, zmm7, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F1654872D5AB" , vpsrld(zmm3, zmm5, 171)); + TEST_INSTRUCTION("62F1654C72D5AB" , k(k4).vpsrld(zmm3, zmm5, 171)); + TEST_INSTRUCTION("62F165CC72D5AB" , k(k4).z().vpsrld(zmm3, zmm5, 171)); + TEST_INSTRUCTION("62F1654872D57B" , vpsrld(zmm3, zmm5, 123)); + TEST_INSTRUCTION("62F1654872117B" , vpsrld(zmm3, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B165487294F0230100007B" , vpsrld(zmm3, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1655872117B" , vpsrld(zmm3, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1654872527F7B" , vpsrld(zmm3, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F165487292002000007B" , vpsrld(zmm3, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F165487252807B" , vpsrld(zmm3, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F165487292C0DFFFFF7B" , vpsrld(zmm3, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1655872527F7B" , vpsrld(zmm3, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F165587292000200007B" , vpsrld(zmm3, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F165587252807B" , vpsrld(zmm3, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F165587292FCFDFFFF7B" , vpsrld(zmm3, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6291ED4073D1AB" , vpsrlq(zmm18, zmm25, 171)); + TEST_INSTRUCTION("6291ED4173D1AB" , k(k1).vpsrlq(zmm18, zmm25, 171)); + TEST_INSTRUCTION("6291EDC173D1AB" , k(k1).z().vpsrlq(zmm18, zmm25, 171)); + TEST_INSTRUCTION("6291ED4073D17B" , vpsrlq(zmm18, zmm25, 123)); + TEST_INSTRUCTION("62F1ED4073117B" , vpsrlq(zmm18, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1ED407394F0230100007B" , vpsrlq(zmm18, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1ED5073117B" , vpsrlq(zmm18, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1ED4073527F7B" , vpsrlq(zmm18, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1ED407392002000007B" , vpsrlq(zmm18, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1ED407352807B" , vpsrlq(zmm18, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1ED407392C0DFFFFF7B" , vpsrlq(zmm18, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1ED5073527F7B" , vpsrlq(zmm18, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1ED507392000400007B" , vpsrlq(zmm18, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1ED507352807B" , vpsrlq(zmm18, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1ED507392F8FBFFFF7B" , vpsrlq(zmm18, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F11D40FAFF" , vpsubd(zmm7, zmm28, zmm7)); + TEST_INSTRUCTION("62F11D43FAFF" , k(k3).vpsubd(zmm7, zmm28, zmm7)); + TEST_INSTRUCTION("62F11DC3FAFF" , k(k3).z().vpsubd(zmm7, zmm28, zmm7)); + TEST_INSTRUCTION("62F11D40FA39" , vpsubd(zmm7, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B11D40FABCF023010000" , vpsubd(zmm7, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F11D50FA39" , vpsubd(zmm7, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F11D40FA7A7F" , vpsubd(zmm7, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F11D40FABA00200000" , vpsubd(zmm7, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F11D40FA7A80" , vpsubd(zmm7, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F11D40FABAC0DFFFFF" , vpsubd(zmm7, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F11D50FA7A7F" , vpsubd(zmm7, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F11D50FABA00020000" , vpsubd(zmm7, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F11D50FA7A80" , vpsubd(zmm7, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F11D50FABAFCFDFFFF" , vpsubd(zmm7, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62219D40FBE9" , vpsubq(zmm29, zmm28, zmm17)); + TEST_INSTRUCTION("62219D42FBE9" , k(k2).vpsubq(zmm29, zmm28, zmm17)); + TEST_INSTRUCTION("62219DC2FBE9" , k(k2).z().vpsubq(zmm29, zmm28, zmm17)); + TEST_INSTRUCTION("62619D40FB29" , vpsubq(zmm29, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62219D40FBACF023010000" , vpsubq(zmm29, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62619D50FB29" , vpsubq(zmm29, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62619D40FB6A7F" , vpsubq(zmm29, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62619D40FBAA00200000" , vpsubq(zmm29, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62619D40FB6A80" , vpsubq(zmm29, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62619D40FBAAC0DFFFFF" , vpsubq(zmm29, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62619D50FB6A7F" , vpsubq(zmm29, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62619D50FBAA00040000" , vpsubq(zmm29, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62619D50FB6A80" , vpsubq(zmm29, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62619D50FBAAF8FBFFFF" , vpsubq(zmm29, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B21D4827D0" , vptestmd(k2, zmm12, zmm16)); + TEST_INSTRUCTION("62B21D4927D0" , k(k1).vptestmd(k2, zmm12, zmm16)); + TEST_INSTRUCTION("62F21D482711" , vptestmd(k2, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B21D482794F023010000" , vptestmd(k2, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F21D582711" , vptestmd(k2, zmm12, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F21D4827527F" , vptestmd(k2, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F21D48279200200000" , vptestmd(k2, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F21D48275280" , vptestmd(k2, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F21D482792C0DFFFFF" , vptestmd(k2, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F21D5827527F" , vptestmd(k2, zmm12, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F21D58279200020000" , vptestmd(k2, zmm12, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F21D58275280" , vptestmd(k2, zmm12, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F21D582792FCFDFFFF" , vptestmd(k2, zmm12, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B2CD4827ED" , vptestmq(k5, zmm6, zmm21)); + TEST_INSTRUCTION("62B2CD4D27ED" , k(k5).vptestmq(k5, zmm6, zmm21)); + TEST_INSTRUCTION("62F2CD482729" , vptestmq(k5, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2CD4827ACF023010000" , vptestmq(k5, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2CD582729" , vptestmq(k5, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2CD48276A7F" , vptestmq(k5, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2CD4827AA00200000" , vptestmq(k5, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2CD48276A80" , vptestmq(k5, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2CD4827AAC0DFFFFF" , vptestmq(k5, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2CD58276A7F" , vptestmq(k5, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2CD5827AA00040000" , vptestmq(k5, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2CD58276A80" , vptestmq(k5, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2CD5827AAF8FBFFFF" , vptestmq(k5, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D15D486AF5" , vpunpckhdq(zmm6, zmm4, zmm13)); + TEST_INSTRUCTION("62D15D4D6AF5" , k(k5).vpunpckhdq(zmm6, zmm4, zmm13)); + TEST_INSTRUCTION("62D15DCD6AF5" , k(k5).z().vpunpckhdq(zmm6, zmm4, zmm13)); + TEST_INSTRUCTION("62F15D486A31" , vpunpckhdq(zmm6, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B15D486AB4F023010000" , vpunpckhdq(zmm6, zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F15D586A31" , vpunpckhdq(zmm6, zmm4, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F15D486A727F" , vpunpckhdq(zmm6, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F15D486AB200200000" , vpunpckhdq(zmm6, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F15D486A7280" , vpunpckhdq(zmm6, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F15D486AB2C0DFFFFF" , vpunpckhdq(zmm6, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F15D586A727F" , vpunpckhdq(zmm6, zmm4, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F15D586AB200020000" , vpunpckhdq(zmm6, zmm4, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F15D586A7280" , vpunpckhdq(zmm6, zmm4, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F15D586AB2FCFDFFFF" , vpunpckhdq(zmm6, zmm4, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("622185486DD8" , vpunpckhqdq(zmm27, zmm15, zmm16)); + TEST_INSTRUCTION("6221854B6DD8" , k(k3).vpunpckhqdq(zmm27, zmm15, zmm16)); + TEST_INSTRUCTION("622185CB6DD8" , k(k3).z().vpunpckhqdq(zmm27, zmm15, zmm16)); + TEST_INSTRUCTION("626185486D19" , vpunpckhqdq(zmm27, zmm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622185486D9CF023010000" , vpunpckhqdq(zmm27, zmm15, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626185586D19" , vpunpckhqdq(zmm27, zmm15, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("626185486D5A7F" , vpunpckhqdq(zmm27, zmm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("626185486D9A00200000" , vpunpckhqdq(zmm27, zmm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("626185486D5A80" , vpunpckhqdq(zmm27, zmm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626185486D9AC0DFFFFF" , vpunpckhqdq(zmm27, zmm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("626185586D5A7F" , vpunpckhqdq(zmm27, zmm15, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("626185586D9A00040000" , vpunpckhqdq(zmm27, zmm15, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("626185586D5A80" , vpunpckhqdq(zmm27, zmm15, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("626185586D9AF8FBFFFF" , vpunpckhqdq(zmm27, zmm15, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6221654862C1" , vpunpckldq(zmm24, zmm3, zmm17)); + TEST_INSTRUCTION("6221654B62C1" , k(k3).vpunpckldq(zmm24, zmm3, zmm17)); + TEST_INSTRUCTION("622165CB62C1" , k(k3).z().vpunpckldq(zmm24, zmm3, zmm17)); + TEST_INSTRUCTION("626165486201" , vpunpckldq(zmm24, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622165486284F023010000" , vpunpckldq(zmm24, zmm3, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626165586201" , vpunpckldq(zmm24, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("6261654862427F" , vpunpckldq(zmm24, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62616548628200200000" , vpunpckldq(zmm24, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62616548624280" , vpunpckldq(zmm24, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626165486282C0DFFFFF" , vpunpckldq(zmm24, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261655862427F" , vpunpckldq(zmm24, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62616558628200020000" , vpunpckldq(zmm24, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62616558624280" , vpunpckldq(zmm24, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("626165586282FCFDFFFF" , vpunpckldq(zmm24, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B1DD486CD9" , vpunpcklqdq(zmm3, zmm4, zmm17)); + TEST_INSTRUCTION("62B1DD496CD9" , k(k1).vpunpcklqdq(zmm3, zmm4, zmm17)); + TEST_INSTRUCTION("62B1DDC96CD9" , k(k1).z().vpunpcklqdq(zmm3, zmm4, zmm17)); + TEST_INSTRUCTION("62F1DD486C19" , vpunpcklqdq(zmm3, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1DD486C9CF023010000" , vpunpcklqdq(zmm3, zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1DD586C19" , vpunpcklqdq(zmm3, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1DD486C5A7F" , vpunpcklqdq(zmm3, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1DD486C9A00200000" , vpunpcklqdq(zmm3, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1DD486C5A80" , vpunpcklqdq(zmm3, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1DD486C9AC0DFFFFF" , vpunpcklqdq(zmm3, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1DD586C5A7F" , vpunpcklqdq(zmm3, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1DD586C9A00040000" , vpunpcklqdq(zmm3, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1DD586C5A80" , vpunpcklqdq(zmm3, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1DD586C9AF8FBFFFF" , vpunpcklqdq(zmm3, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62111D48EFC0" , vpxord(zmm8, zmm12, zmm24)); + TEST_INSTRUCTION("62111D4EEFC0" , k(k6).vpxord(zmm8, zmm12, zmm24)); + TEST_INSTRUCTION("62111DCEEFC0" , k(k6).z().vpxord(zmm8, zmm12, zmm24)); + TEST_INSTRUCTION("62711D48EF01" , vpxord(zmm8, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62311D48EF84F023010000" , vpxord(zmm8, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62711D58EF01" , vpxord(zmm8, zmm12, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62711D48EF427F" , vpxord(zmm8, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62711D48EF8200200000" , vpxord(zmm8, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62711D48EF4280" , vpxord(zmm8, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62711D48EF82C0DFFFFF" , vpxord(zmm8, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62711D58EF427F" , vpxord(zmm8, zmm12, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62711D58EF8200020000" , vpxord(zmm8, zmm12, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62711D58EF4280" , vpxord(zmm8, zmm12, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62711D58EF82FCFDFFFF" , vpxord(zmm8, zmm12, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D1CD40EFFA" , vpxorq(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D1CD46EFFA" , k(k6).vpxorq(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D1CDC6EFFA" , k(k6).z().vpxorq(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62F1CD40EF39" , vpxorq(zmm7, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1CD40EFBCF023010000" , vpxorq(zmm7, zmm22, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1CD50EF39" , vpxorq(zmm7, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1CD40EF7A7F" , vpxorq(zmm7, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1CD40EFBA00200000" , vpxorq(zmm7, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1CD40EF7A80" , vpxorq(zmm7, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1CD40EFBAC0DFFFFF" , vpxorq(zmm7, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1CD50EF7A7F" , vpxorq(zmm7, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1CD50EFBA00040000" , vpxorq(zmm7, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1CD50EF7A80" , vpxorq(zmm7, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1CD50EFBAF8FBFFFF" , vpxorq(zmm7, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6272FD484CEC" , vrcp14pd(zmm13, zmm4)); + TEST_INSTRUCTION("6272FD4D4CEC" , k(k5).vrcp14pd(zmm13, zmm4)); + TEST_INSTRUCTION("6272FDCD4CEC" , k(k5).z().vrcp14pd(zmm13, zmm4)); + TEST_INSTRUCTION("6272FD484C29" , vrcp14pd(zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232FD484CACF023010000" , vrcp14pd(zmm13, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272FD584C29" , vrcp14pd(zmm13, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272FD484C6A7F" , vrcp14pd(zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272FD484CAA00200000" , vrcp14pd(zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272FD484C6A80" , vrcp14pd(zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272FD484CAAC0DFFFFF" , vrcp14pd(zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272FD584C6A7F" , vrcp14pd(zmm13, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272FD584CAA00040000" , vrcp14pd(zmm13, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272FD584C6A80" , vrcp14pd(zmm13, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272FD584CAAF8FBFFFF" , vrcp14pd(zmm13, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62127D484CD1" , vrcp14ps(zmm10, zmm25)); + TEST_INSTRUCTION("62127D494CD1" , k(k1).vrcp14ps(zmm10, zmm25)); + TEST_INSTRUCTION("62127DC94CD1" , k(k1).z().vrcp14ps(zmm10, zmm25)); + TEST_INSTRUCTION("62727D484C11" , vrcp14ps(zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D484C94F023010000" , vrcp14ps(zmm10, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62727D584C11" , vrcp14ps(zmm10, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62727D484C527F" , vrcp14ps(zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62727D484C9200200000" , vrcp14ps(zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62727D484C5280" , vrcp14ps(zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62727D484C92C0DFFFFF" , vrcp14ps(zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62727D584C527F" , vrcp14ps(zmm10, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62727D584C9200020000" , vrcp14ps(zmm10, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62727D584C5280" , vrcp14ps(zmm10, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62727D584C92FCFDFFFF" , vrcp14ps(zmm10, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6252CD004DE6" , vrcp14sd(xmm12, xmm22, xmm14)); + TEST_INSTRUCTION("6252CD024DE6" , k(k2).vrcp14sd(xmm12, xmm22, xmm14)); + TEST_INSTRUCTION("6252CD824DE6" , k(k2).z().vrcp14sd(xmm12, xmm22, xmm14)); + TEST_INSTRUCTION("6272CD004D21" , vrcp14sd(xmm12, xmm22, qword_ptr(rcx))); + TEST_INSTRUCTION("6232CD004DA4F023010000" , vrcp14sd(xmm12, xmm22, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272CD004D627F" , vrcp14sd(xmm12, xmm22, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6272CD004DA200040000" , vrcp14sd(xmm12, xmm22, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6272CD004D6280" , vrcp14sd(xmm12, xmm22, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6272CD004DA2F8FBFFFF" , vrcp14sd(xmm12, xmm22, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62723D084DC3" , vrcp14ss(xmm8, xmm8, xmm3)); + TEST_INSTRUCTION("62723D0F4DC3" , k(k7).vrcp14ss(xmm8, xmm8, xmm3)); + TEST_INSTRUCTION("62723D8F4DC3" , k(k7).z().vrcp14ss(xmm8, xmm8, xmm3)); + TEST_INSTRUCTION("62723D084D01" , vrcp14ss(xmm8, xmm8, dword_ptr(rcx))); + TEST_INSTRUCTION("62323D084D84F023010000" , vrcp14ss(xmm8, xmm8, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62723D084D427F" , vrcp14ss(xmm8, xmm8, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62723D084D8200020000" , vrcp14ss(xmm8, xmm8, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62723D084D4280" , vrcp14ss(xmm8, xmm8, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62723D084D82FCFDFFFF" , vrcp14ss(xmm8, xmm8, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C2FD484EDE" , vrsqrt14pd(zmm19, zmm14)); + TEST_INSTRUCTION("62C2FD494EDE" , k(k1).vrsqrt14pd(zmm19, zmm14)); + TEST_INSTRUCTION("62C2FDC94EDE" , k(k1).z().vrsqrt14pd(zmm19, zmm14)); + TEST_INSTRUCTION("62E2FD484E19" , vrsqrt14pd(zmm19, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2FD484E9CF023010000" , vrsqrt14pd(zmm19, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2FD584E19" , vrsqrt14pd(zmm19, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2FD484E5A7F" , vrsqrt14pd(zmm19, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2FD484E9A00200000" , vrsqrt14pd(zmm19, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2FD484E5A80" , vrsqrt14pd(zmm19, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2FD484E9AC0DFFFFF" , vrsqrt14pd(zmm19, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2FD584E5A7F" , vrsqrt14pd(zmm19, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2FD584E9A00040000" , vrsqrt14pd(zmm19, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2FD584E5A80" , vrsqrt14pd(zmm19, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2FD584E9AF8FBFFFF" , vrsqrt14pd(zmm19, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C27D484EC1" , vrsqrt14ps(zmm16, zmm9)); + TEST_INSTRUCTION("62C27D4D4EC1" , k(k5).vrsqrt14ps(zmm16, zmm9)); + TEST_INSTRUCTION("62C27DCD4EC1" , k(k5).z().vrsqrt14ps(zmm16, zmm9)); + TEST_INSTRUCTION("62E27D484E01" , vrsqrt14ps(zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D484E84F023010000" , vrsqrt14ps(zmm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E27D584E01" , vrsqrt14ps(zmm16, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E27D484E427F" , vrsqrt14ps(zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E27D484E8200200000" , vrsqrt14ps(zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E27D484E4280" , vrsqrt14ps(zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E27D484E82C0DFFFFF" , vrsqrt14ps(zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E27D584E427F" , vrsqrt14ps(zmm16, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E27D584E8200020000" , vrsqrt14ps(zmm16, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E27D584E4280" , vrsqrt14ps(zmm16, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E27D584E82FCFDFFFF" , vrsqrt14ps(zmm16, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6242CD084FD2" , vrsqrt14sd(xmm26, xmm6, xmm10)); + TEST_INSTRUCTION("6242CD0D4FD2" , k(k5).vrsqrt14sd(xmm26, xmm6, xmm10)); + TEST_INSTRUCTION("6242CD8D4FD2" , k(k5).z().vrsqrt14sd(xmm26, xmm6, xmm10)); + TEST_INSTRUCTION("6262CD084F11" , vrsqrt14sd(xmm26, xmm6, qword_ptr(rcx))); + TEST_INSTRUCTION("6222CD084F94F023010000" , vrsqrt14sd(xmm26, xmm6, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262CD084F527F" , vrsqrt14sd(xmm26, xmm6, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262CD084F9200040000" , vrsqrt14sd(xmm26, xmm6, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262CD084F5280" , vrsqrt14sd(xmm26, xmm6, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262CD084F92F8FBFFFF" , vrsqrt14sd(xmm26, xmm6, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62520D084FF1" , vrsqrt14ss(xmm14, xmm14, xmm9)); + TEST_INSTRUCTION("62520D094FF1" , k(k1).vrsqrt14ss(xmm14, xmm14, xmm9)); + TEST_INSTRUCTION("62520D894FF1" , k(k1).z().vrsqrt14ss(xmm14, xmm14, xmm9)); + TEST_INSTRUCTION("62720D084F31" , vrsqrt14ss(xmm14, xmm14, dword_ptr(rcx))); + TEST_INSTRUCTION("62320D084FB4F023010000" , vrsqrt14ss(xmm14, xmm14, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62720D084F727F" , vrsqrt14ss(xmm14, xmm14, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62720D084FB200020000" , vrsqrt14ss(xmm14, xmm14, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62720D084F7280" , vrsqrt14ss(xmm14, xmm14, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62720D084FB2FCFDFFFF" , vrsqrt14ss(xmm14, xmm14, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6221BD48C6E6AB" , vshufpd(zmm28, zmm8, zmm22, 171)); + TEST_INSTRUCTION("6221BD4AC6E6AB" , k(k2).vshufpd(zmm28, zmm8, zmm22, 171)); + TEST_INSTRUCTION("6221BDCAC6E6AB" , k(k2).z().vshufpd(zmm28, zmm8, zmm22, 171)); + TEST_INSTRUCTION("6221BD48C6E67B" , vshufpd(zmm28, zmm8, zmm22, 123)); + TEST_INSTRUCTION("6261BD48C6217B" , vshufpd(zmm28, zmm8, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6221BD48C6A4F0230100007B" , vshufpd(zmm28, zmm8, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6261BD58C6217B" , vshufpd(zmm28, zmm8, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6261BD48C6627F7B" , vshufpd(zmm28, zmm8, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6261BD48C6A2002000007B" , vshufpd(zmm28, zmm8, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6261BD48C662807B" , vshufpd(zmm28, zmm8, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6261BD48C6A2C0DFFFFF7B" , vshufpd(zmm28, zmm8, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6261BD58C6627F7B" , vshufpd(zmm28, zmm8, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6261BD58C6A2000400007B" , vshufpd(zmm28, zmm8, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6261BD58C662807B" , vshufpd(zmm28, zmm8, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6261BD58C6A2F8FBFFFF7B" , vshufpd(zmm28, zmm8, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62D14C48C6E9AB" , vshufps(zmm5, zmm6, zmm9, 171)); + TEST_INSTRUCTION("62D14C4EC6E9AB" , k(k6).vshufps(zmm5, zmm6, zmm9, 171)); + TEST_INSTRUCTION("62D14CCEC6E9AB" , k(k6).z().vshufps(zmm5, zmm6, zmm9, 171)); + TEST_INSTRUCTION("62D14C48C6E97B" , vshufps(zmm5, zmm6, zmm9, 123)); + TEST_INSTRUCTION("62F14C48C6297B" , vshufps(zmm5, zmm6, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B14C48C6ACF0230100007B" , vshufps(zmm5, zmm6, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F14C58C6297B" , vshufps(zmm5, zmm6, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F14C48C66A7F7B" , vshufps(zmm5, zmm6, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F14C48C6AA002000007B" , vshufps(zmm5, zmm6, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F14C48C66A807B" , vshufps(zmm5, zmm6, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F14C48C6AAC0DFFFFF7B" , vshufps(zmm5, zmm6, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F14C58C66A7F7B" , vshufps(zmm5, zmm6, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F14C58C6AA000200007B" , vshufps(zmm5, zmm6, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F14C58C66A807B" , vshufps(zmm5, zmm6, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F14C58C6AAFCFDFFFF7B" , vshufps(zmm5, zmm6, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62A1FD4851DB" , vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62A1FD4D51DB" , k(k5).vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62A1FDCD51DB" , k(k5).z().vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62A1FD1851DB" , rn_sae().vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62A1FD5851DB" , ru_sae().vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62A1FD3851DB" , rd_sae().vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62A1FD7851DB" , rz_sae().vsqrtpd(zmm19, zmm19)); + TEST_INSTRUCTION("62E1FD485119" , vsqrtpd(zmm19, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD48519CF023010000" , vsqrtpd(zmm19, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1FD585119" , vsqrtpd(zmm19, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1FD48515A7F" , vsqrtpd(zmm19, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FD48519A00200000" , vsqrtpd(zmm19, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FD48515A80" , vsqrtpd(zmm19, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FD48519AC0DFFFFF" , vsqrtpd(zmm19, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FD58515A7F" , vsqrtpd(zmm19, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1FD58519A00040000" , vsqrtpd(zmm19, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1FD58515A80" , vsqrtpd(zmm19, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1FD58519AF8FBFFFF" , vsqrtpd(zmm19, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62017C4851E5" , vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62017C4B51E5" , k(k3).vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62017CCB51E5" , k(k3).z().vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62017C1851E5" , rn_sae().vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62017C5851E5" , ru_sae().vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62017C3851E5" , rd_sae().vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62017C7851E5" , rz_sae().vsqrtps(zmm28, zmm29)); + TEST_INSTRUCTION("62617C485121" , vsqrtps(zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62217C4851A4F023010000" , vsqrtps(zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62617C585121" , vsqrtps(zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62617C4851627F" , vsqrtps(zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62617C4851A200200000" , vsqrtps(zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62617C48516280" , vsqrtps(zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62617C4851A2C0DFFFFF" , vsqrtps(zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62617C5851627F" , vsqrtps(zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62617C5851A200020000" , vsqrtps(zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62617C58516280" , vsqrtps(zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62617C5851A2FCFDFFFF" , vsqrtps(zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C4C16B51F4" , vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("62D1EF0F51F4" , k(k7).vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("62D1EF8F51F4" , k(k7).z().vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("62D1EF1851F4" , rn_sae().vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("62D1EF5851F4" , ru_sae().vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("62D1EF3851F4" , rd_sae().vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("62D1EF7851F4" , rz_sae().vsqrtsd(xmm6, xmm2, xmm12)); + TEST_INSTRUCTION("C5EB5131" , vsqrtsd(xmm6, xmm2, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A16B51B4F023010000" , vsqrtsd(xmm6, xmm2, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5EB51B2F8030000" , vsqrtsd(xmm6, xmm2, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C5EB51B200040000" , vsqrtsd(xmm6, xmm2, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C5EB51B200FCFFFF" , vsqrtsd(xmm6, xmm2, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C5EB51B2F8FBFFFF" , vsqrtsd(xmm6, xmm2, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62C1660051F0" , vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62C1660151F0" , k(k1).vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62C1668151F0" , k(k1).z().vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62C1661051F0" , rn_sae().vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62C1665051F0" , ru_sae().vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62C1663051F0" , rd_sae().vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62C1667051F0" , rz_sae().vsqrtss(xmm22, xmm19, xmm8)); + TEST_INSTRUCTION("62E166005131" , vsqrtss(xmm22, xmm19, dword_ptr(rcx))); + TEST_INSTRUCTION("62A1660051B4F023010000" , vsqrtss(xmm22, xmm19, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1660051727F" , vsqrtss(xmm22, xmm19, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E1660051B200020000" , vsqrtss(xmm22, xmm19, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E16600517280" , vsqrtss(xmm22, xmm19, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E1660051B2FCFDFFFF" , vsqrtss(xmm22, xmm19, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62519D485CC9" , vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62519D4F5CC9" , k(k7).vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62519DCF5CC9" , k(k7).z().vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62519D185CC9" , rn_sae().vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62519D585CC9" , ru_sae().vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62519D385CC9" , rd_sae().vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62519D785CC9" , rz_sae().vsubpd(zmm9, zmm12, zmm9)); + TEST_INSTRUCTION("62719D485C09" , vsubpd(zmm9, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62319D485C8CF023010000" , vsubpd(zmm9, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62719D585C09" , vsubpd(zmm9, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62719D485C4A7F" , vsubpd(zmm9, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62719D485C8A00200000" , vsubpd(zmm9, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62719D485C4A80" , vsubpd(zmm9, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62719D485C8AC0DFFFFF" , vsubpd(zmm9, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62719D585C4A7F" , vsubpd(zmm9, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62719D585C8A00040000" , vsubpd(zmm9, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62719D585C4A80" , vsubpd(zmm9, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62719D585C8AF8FBFFFF" , vsubpd(zmm9, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("623124405CF5" , vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("623124455CF5" , k(k5).vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("623124C55CF5" , k(k5).z().vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("623124105CF5" , rn_sae().vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("623124505CF5" , ru_sae().vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("623124305CF5" , rd_sae().vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("623124705CF5" , rz_sae().vsubps(zmm14, zmm27, zmm21)); + TEST_INSTRUCTION("627124405C31" , vsubps(zmm14, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("623124405CB4F023010000" , vsubps(zmm14, zmm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("627124505C31" , vsubps(zmm14, zmm27, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("627124405C727F" , vsubps(zmm14, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("627124405CB200200000" , vsubps(zmm14, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("627124405C7280" , vsubps(zmm14, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("627124405CB2C0DFFFFF" , vsubps(zmm14, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("627124505C727F" , vsubps(zmm14, zmm27, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("627124505CB200020000" , vsubps(zmm14, zmm27, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("627124505C7280" , vsubps(zmm14, zmm27, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("627124505CB2FCFDFFFF" , vsubps(zmm14, zmm27, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C1A7005CE7" , vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62C1A7055CE7" , k(k5).vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62C1A7855CE7" , k(k5).z().vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62C1A7105CE7" , rn_sae().vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62C1A7505CE7" , ru_sae().vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62C1A7305CE7" , rd_sae().vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62C1A7705CE7" , rz_sae().vsubsd(xmm20, xmm27, xmm15)); + TEST_INSTRUCTION("62E1A7005C21" , vsubsd(xmm20, xmm27, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1A7005CA4F023010000" , vsubsd(xmm20, xmm27, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1A7005C627F" , vsubsd(xmm20, xmm27, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1A7005CA200040000" , vsubsd(xmm20, xmm27, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1A7005C6280" , vsubsd(xmm20, xmm27, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1A7005CA2F8FBFFFF" , vsubsd(xmm20, xmm27, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62D136005CE9" , vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62D136035CE9" , k(k3).vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62D136835CE9" , k(k3).z().vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62D136105CE9" , rn_sae().vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62D136505CE9" , ru_sae().vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62D136305CE9" , rd_sae().vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62D136705CE9" , rz_sae().vsubss(xmm5, xmm25, xmm9)); + TEST_INSTRUCTION("62F136005C29" , vsubss(xmm5, xmm25, dword_ptr(rcx))); + TEST_INSTRUCTION("62B136005CACF023010000" , vsubss(xmm5, xmm25, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F136005C6A7F" , vsubss(xmm5, xmm25, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F136005CAA00020000" , vsubss(xmm5, xmm25, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F136005C6A80" , vsubss(xmm5, xmm25, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F136005CAAFCFDFFFF" , vsubss(xmm5, xmm25, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("C441792EDA" , vucomisd(xmm11, xmm10)); + TEST_INSTRUCTION("6251FD182EDA" , sae().vucomisd(xmm11, xmm10)); + TEST_INSTRUCTION("C5792E19" , vucomisd(xmm11, qword_ptr(rcx))); + TEST_INSTRUCTION("C421792E9CF023010000" , vucomisd(xmm11, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5792E9AF8030000" , vucomisd(xmm11, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C5792E9A00040000" , vucomisd(xmm11, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C5792E9A00FCFFFF" , vucomisd(xmm11, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C5792E9AF8FBFFFF" , vucomisd(xmm11, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62C17C082EF3" , vucomiss(xmm22, xmm11)); + TEST_INSTRUCTION("62C17C182EF3" , sae().vucomiss(xmm22, xmm11)); + TEST_INSTRUCTION("62E17C082E31" , vucomiss(xmm22, dword_ptr(rcx))); + TEST_INSTRUCTION("62A17C082EB4F023010000" , vucomiss(xmm22, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E17C082E727F" , vucomiss(xmm22, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E17C082EB200020000" , vucomiss(xmm22, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E17C082E7280" , vucomiss(xmm22, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E17C082EB2FCFDFFFF" , vucomiss(xmm22, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6201E54015CA" , vunpckhpd(zmm25, zmm19, zmm26)); + TEST_INSTRUCTION("6201E54515CA" , k(k5).vunpckhpd(zmm25, zmm19, zmm26)); + TEST_INSTRUCTION("6201E5C515CA" , k(k5).z().vunpckhpd(zmm25, zmm19, zmm26)); + TEST_INSTRUCTION("6261E5401509" , vunpckhpd(zmm25, zmm19, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221E540158CF023010000" , vunpckhpd(zmm25, zmm19, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6261E5501509" , vunpckhpd(zmm25, zmm19, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261E540154A7F" , vunpckhpd(zmm25, zmm19, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261E540158A00200000" , vunpckhpd(zmm25, zmm19, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261E540154A80" , vunpckhpd(zmm25, zmm19, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261E540158AC0DFFFFF" , vunpckhpd(zmm25, zmm19, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261E550154A7F" , vunpckhpd(zmm25, zmm19, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261E550158A00040000" , vunpckhpd(zmm25, zmm19, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261E550154A80" , vunpckhpd(zmm25, zmm19, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261E550158AF8FBFFFF" , vunpckhpd(zmm25, zmm19, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B10C4815E8" , vunpckhps(zmm5, zmm14, zmm16)); + TEST_INSTRUCTION("62B10C4E15E8" , k(k6).vunpckhps(zmm5, zmm14, zmm16)); + TEST_INSTRUCTION("62B10CCE15E8" , k(k6).z().vunpckhps(zmm5, zmm14, zmm16)); + TEST_INSTRUCTION("62F10C481529" , vunpckhps(zmm5, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B10C4815ACF023010000" , vunpckhps(zmm5, zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F10C581529" , vunpckhps(zmm5, zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F10C48156A7F" , vunpckhps(zmm5, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F10C4815AA00200000" , vunpckhps(zmm5, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F10C48156A80" , vunpckhps(zmm5, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F10C4815AAC0DFFFFF" , vunpckhps(zmm5, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F10C58156A7F" , vunpckhps(zmm5, zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F10C5815AA00020000" , vunpckhps(zmm5, zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F10C58156A80" , vunpckhps(zmm5, zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F10C5815AAFCFDFFFF" , vunpckhps(zmm5, zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A1954014D5" , vunpcklpd(zmm18, zmm29, zmm21)); + TEST_INSTRUCTION("62A1954614D5" , k(k6).vunpcklpd(zmm18, zmm29, zmm21)); + TEST_INSTRUCTION("62A195C614D5" , k(k6).z().vunpcklpd(zmm18, zmm29, zmm21)); + TEST_INSTRUCTION("62E195401411" , vunpcklpd(zmm18, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A195401494F023010000" , vunpcklpd(zmm18, zmm29, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E195501411" , vunpcklpd(zmm18, zmm29, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1954014527F" , vunpcklpd(zmm18, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E19540149200200000" , vunpcklpd(zmm18, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E19540145280" , vunpcklpd(zmm18, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E195401492C0DFFFFF" , vunpcklpd(zmm18, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1955014527F" , vunpcklpd(zmm18, zmm29, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E19550149200040000" , vunpcklpd(zmm18, zmm29, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E19550145280" , vunpcklpd(zmm18, zmm29, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E195501492F8FBFFFF" , vunpcklpd(zmm18, zmm29, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F1644814CA" , vunpcklps(zmm1, zmm3, zmm2)); + TEST_INSTRUCTION("62F1644B14CA" , k(k3).vunpcklps(zmm1, zmm3, zmm2)); + TEST_INSTRUCTION("62F164CB14CA" , k(k3).z().vunpcklps(zmm1, zmm3, zmm2)); + TEST_INSTRUCTION("62F164481409" , vunpcklps(zmm1, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B16448148CF023010000" , vunpcklps(zmm1, zmm3, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F164581409" , vunpcklps(zmm1, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F16448144A7F" , vunpcklps(zmm1, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F16448148A00200000" , vunpcklps(zmm1, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F16448144A80" , vunpcklps(zmm1, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F16448148AC0DFFFFF" , vunpcklps(zmm1, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F16458144A7F" , vunpcklps(zmm1, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F16458148A00020000" , vunpcklps(zmm1, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F16458144A80" , vunpcklps(zmm1, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F16458148AFCFDFFFF" , vunpcklps(zmm1, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62330D4825E4AB" , vpternlogd(zmm12, zmm14, zmm20, 171)); + TEST_INSTRUCTION("62330D4F25E4AB" , k(k7).vpternlogd(zmm12, zmm14, zmm20, 171)); + TEST_INSTRUCTION("62330DCF25E4AB" , k(k7).z().vpternlogd(zmm12, zmm14, zmm20, 171)); + TEST_INSTRUCTION("62330D4825E47B" , vpternlogd(zmm12, zmm14, zmm20, 123)); + TEST_INSTRUCTION("62730D4825217B" , vpternlogd(zmm12, zmm14, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62330D4825A4F0230100007B" , vpternlogd(zmm12, zmm14, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62730D5825217B" , vpternlogd(zmm12, zmm14, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62730D4825627F7B" , vpternlogd(zmm12, zmm14, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62730D4825A2002000007B" , vpternlogd(zmm12, zmm14, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62730D482562807B" , vpternlogd(zmm12, zmm14, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62730D4825A2C0DFFFFF7B" , vpternlogd(zmm12, zmm14, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62730D5825627F7B" , vpternlogd(zmm12, zmm14, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62730D5825A2000200007B" , vpternlogd(zmm12, zmm14, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62730D582562807B" , vpternlogd(zmm12, zmm14, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62730D5825A2FCFDFFFF7B" , vpternlogd(zmm12, zmm14, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6233ED4825FDAB" , vpternlogq(zmm15, zmm2, zmm21, 171)); + TEST_INSTRUCTION("6233ED4B25FDAB" , k(k3).vpternlogq(zmm15, zmm2, zmm21, 171)); + TEST_INSTRUCTION("6233EDCB25FDAB" , k(k3).z().vpternlogq(zmm15, zmm2, zmm21, 171)); + TEST_INSTRUCTION("6233ED4825FD7B" , vpternlogq(zmm15, zmm2, zmm21, 123)); + TEST_INSTRUCTION("6273ED4825397B" , vpternlogq(zmm15, zmm2, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233ED4825BCF0230100007B" , vpternlogq(zmm15, zmm2, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6273ED5825397B" , vpternlogq(zmm15, zmm2, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273ED48257A7F7B" , vpternlogq(zmm15, zmm2, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273ED4825BA002000007B" , vpternlogq(zmm15, zmm2, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273ED48257A807B" , vpternlogq(zmm15, zmm2, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273ED4825BAC0DFFFFF7B" , vpternlogq(zmm15, zmm2, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273ED58257A7F7B" , vpternlogq(zmm15, zmm2, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273ED5825BA000400007B" , vpternlogq(zmm15, zmm2, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273ED58257A807B" , vpternlogq(zmm15, zmm2, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273ED5825BAF8FBFFFF7B" , vpternlogq(zmm15, zmm2, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F27E4832D3" , vpmovqb(xmm3, zmm2)); + TEST_INSTRUCTION("62F27E4932D3" , k(k1).vpmovqb(xmm3, zmm2)); + TEST_INSTRUCTION("62F27EC932D3" , k(k1).z().vpmovqb(xmm3, zmm2)); + TEST_INSTRUCTION("62027E4822EE" , vpmovsqb(xmm30, zmm29)); + TEST_INSTRUCTION("62027E4D22EE" , k(k5).vpmovsqb(xmm30, zmm29)); + TEST_INSTRUCTION("62027ECD22EE" , k(k5).z().vpmovsqb(xmm30, zmm29)); + TEST_INSTRUCTION("62027E4812E0" , vpmovusqb(xmm24, zmm28)); + TEST_INSTRUCTION("62027E4F12E0" , k(k7).vpmovusqb(xmm24, zmm28)); + TEST_INSTRUCTION("62027ECF12E0" , k(k7).z().vpmovusqb(xmm24, zmm28)); + TEST_INSTRUCTION("62E27E4834D6" , vpmovqw(xmm6, zmm18)); + TEST_INSTRUCTION("62E27E4934D6" , k(k1).vpmovqw(xmm6, zmm18)); + TEST_INSTRUCTION("62E27EC934D6" , k(k1).z().vpmovqw(xmm6, zmm18)); + TEST_INSTRUCTION("62827E4824DB" , vpmovsqw(xmm27, zmm19)); + TEST_INSTRUCTION("62827E4E24DB" , k(k6).vpmovsqw(xmm27, zmm19)); + TEST_INSTRUCTION("62827ECE24DB" , k(k6).z().vpmovsqw(xmm27, zmm19)); + TEST_INSTRUCTION("62127E4814D4" , vpmovusqw(xmm28, zmm10)); + TEST_INSTRUCTION("62127E4F14D4" , k(k7).vpmovusqw(xmm28, zmm10)); + TEST_INSTRUCTION("62127ECF14D4" , k(k7).z().vpmovusqw(xmm28, zmm10)); + TEST_INSTRUCTION("62627E4835CE" , vpmovqd(ymm6, zmm25)); + TEST_INSTRUCTION("62627E4D35CE" , k(k5).vpmovqd(ymm6, zmm25)); + TEST_INSTRUCTION("62627ECD35CE" , k(k5).z().vpmovqd(ymm6, zmm25)); + TEST_INSTRUCTION("62D27E4825D7" , vpmovsqd(ymm15, zmm2)); + TEST_INSTRUCTION("62D27E4A25D7" , k(k2).vpmovsqd(ymm15, zmm2)); + TEST_INSTRUCTION("62D27ECA25D7" , k(k2).z().vpmovsqd(ymm15, zmm2)); + TEST_INSTRUCTION("62D27E4815E0" , vpmovusqd(ymm8, zmm4)); + TEST_INSTRUCTION("62D27E4C15E0" , k(k4).vpmovusqd(ymm8, zmm4)); + TEST_INSTRUCTION("62D27ECC15E0" , k(k4).z().vpmovusqd(ymm8, zmm4)); + TEST_INSTRUCTION("62F27E4831EA" , vpmovdb(xmm2, zmm5)); + TEST_INSTRUCTION("62F27E4D31EA" , k(k5).vpmovdb(xmm2, zmm5)); + TEST_INSTRUCTION("62F27ECD31EA" , k(k5).z().vpmovdb(xmm2, zmm5)); + TEST_INSTRUCTION("62B27E4821D5" , vpmovsdb(xmm21, zmm2)); + TEST_INSTRUCTION("62B27E4C21D5" , k(k4).vpmovsdb(xmm21, zmm2)); + TEST_INSTRUCTION("62B27ECC21D5" , k(k4).z().vpmovsdb(xmm21, zmm2)); + TEST_INSTRUCTION("62B27E4811D4" , vpmovusdb(xmm20, zmm2)); + TEST_INSTRUCTION("62B27E4B11D4" , k(k3).vpmovusdb(xmm20, zmm2)); + TEST_INSTRUCTION("62B27ECB11D4" , k(k3).z().vpmovusdb(xmm20, zmm2)); + TEST_INSTRUCTION("62227E4833EE" , vpmovdw(ymm22, zmm29)); + TEST_INSTRUCTION("62227E4D33EE" , k(k5).vpmovdw(ymm22, zmm29)); + TEST_INSTRUCTION("62227ECD33EE" , k(k5).z().vpmovdw(ymm22, zmm29)); + TEST_INSTRUCTION("62127E4823F1" , vpmovsdw(ymm25, zmm14)); + TEST_INSTRUCTION("62127E4C23F1" , k(k4).vpmovsdw(ymm25, zmm14)); + TEST_INSTRUCTION("62127ECC23F1" , k(k4).z().vpmovsdw(ymm25, zmm14)); + TEST_INSTRUCTION("62D27E4813F8" , vpmovusdw(ymm8, zmm7)); + TEST_INSTRUCTION("62D27E4913F8" , k(k1).vpmovusdw(ymm8, zmm7)); + TEST_INSTRUCTION("62D27EC913F8" , k(k1).z().vpmovusdw(ymm8, zmm7)); + TEST_INSTRUCTION("62F33D4023F3AB" , vshuff32x4(zmm6, zmm24, zmm3, 171)); + TEST_INSTRUCTION("62F33D4223F3AB" , k(k2).vshuff32x4(zmm6, zmm24, zmm3, 171)); + TEST_INSTRUCTION("62F33DC223F3AB" , k(k2).z().vshuff32x4(zmm6, zmm24, zmm3, 171)); + TEST_INSTRUCTION("62F33D4023F37B" , vshuff32x4(zmm6, zmm24, zmm3, 123)); + TEST_INSTRUCTION("62F33D4023317B" , vshuff32x4(zmm6, zmm24, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B33D4023B4F0230100007B" , vshuff32x4(zmm6, zmm24, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F33D5023317B" , vshuff32x4(zmm6, zmm24, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F33D4023727F7B" , vshuff32x4(zmm6, zmm24, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F33D4023B2002000007B" , vshuff32x4(zmm6, zmm24, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F33D402372807B" , vshuff32x4(zmm6, zmm24, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F33D4023B2C0DFFFFF7B" , vshuff32x4(zmm6, zmm24, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F33D5023727F7B" , vshuff32x4(zmm6, zmm24, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F33D5023B2000200007B" , vshuff32x4(zmm6, zmm24, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F33D502372807B" , vshuff32x4(zmm6, zmm24, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F33D5023B2FCFDFFFF7B" , vshuff32x4(zmm6, zmm24, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6253B54023FBAB" , vshuff64x2(zmm15, zmm25, zmm11, 171)); + TEST_INSTRUCTION("6253B54223FBAB" , k(k2).vshuff64x2(zmm15, zmm25, zmm11, 171)); + TEST_INSTRUCTION("6253B5C223FBAB" , k(k2).z().vshuff64x2(zmm15, zmm25, zmm11, 171)); + TEST_INSTRUCTION("6253B54023FB7B" , vshuff64x2(zmm15, zmm25, zmm11, 123)); + TEST_INSTRUCTION("6273B54023397B" , vshuff64x2(zmm15, zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233B54023BCF0230100007B" , vshuff64x2(zmm15, zmm25, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6273B55023397B" , vshuff64x2(zmm15, zmm25, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273B540237A7F7B" , vshuff64x2(zmm15, zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273B54023BA002000007B" , vshuff64x2(zmm15, zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273B540237A807B" , vshuff64x2(zmm15, zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273B54023BAC0DFFFFF7B" , vshuff64x2(zmm15, zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273B550237A7F7B" , vshuff64x2(zmm15, zmm25, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273B55023BA000400007B" , vshuff64x2(zmm15, zmm25, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273B550237A807B" , vshuff64x2(zmm15, zmm25, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273B55023BAF8FBFFFF7B" , vshuff64x2(zmm15, zmm25, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62931D4043C9AB" , vshufi32x4(zmm1, zmm28, zmm25, 171)); + TEST_INSTRUCTION("62931D4443C9AB" , k(k4).vshufi32x4(zmm1, zmm28, zmm25, 171)); + TEST_INSTRUCTION("62931DC443C9AB" , k(k4).z().vshufi32x4(zmm1, zmm28, zmm25, 171)); + TEST_INSTRUCTION("62931D4043C97B" , vshufi32x4(zmm1, zmm28, zmm25, 123)); + TEST_INSTRUCTION("62F31D4043097B" , vshufi32x4(zmm1, zmm28, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B31D40438CF0230100007B" , vshufi32x4(zmm1, zmm28, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F31D5043097B" , vshufi32x4(zmm1, zmm28, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F31D40434A7F7B" , vshufi32x4(zmm1, zmm28, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F31D40438A002000007B" , vshufi32x4(zmm1, zmm28, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F31D40434A807B" , vshufi32x4(zmm1, zmm28, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F31D40438AC0DFFFFF7B" , vshufi32x4(zmm1, zmm28, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F31D50434A7F7B" , vshufi32x4(zmm1, zmm28, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F31D50438A000200007B" , vshufi32x4(zmm1, zmm28, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F31D50434A807B" , vshufi32x4(zmm1, zmm28, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F31D50438AFCFDFFFF7B" , vshufi32x4(zmm1, zmm28, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62B3FD4043DBAB" , vshufi64x2(zmm3, zmm16, zmm19, 171)); + TEST_INSTRUCTION("62B3FD4743DBAB" , k(k7).vshufi64x2(zmm3, zmm16, zmm19, 171)); + TEST_INSTRUCTION("62B3FDC743DBAB" , k(k7).z().vshufi64x2(zmm3, zmm16, zmm19, 171)); + TEST_INSTRUCTION("62B3FD4043DB7B" , vshufi64x2(zmm3, zmm16, zmm19, 123)); + TEST_INSTRUCTION("62F3FD4043197B" , vshufi64x2(zmm3, zmm16, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3FD40439CF0230100007B" , vshufi64x2(zmm3, zmm16, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F3FD5043197B" , vshufi64x2(zmm3, zmm16, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD40435A7F7B" , vshufi64x2(zmm3, zmm16, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F3FD40439A002000007B" , vshufi64x2(zmm3, zmm16, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F3FD40435A807B" , vshufi64x2(zmm3, zmm16, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F3FD40439AC0DFFFFF7B" , vshufi64x2(zmm3, zmm16, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F3FD50435A7F7B" , vshufi64x2(zmm3, zmm16, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD50439A000400007B" , vshufi64x2(zmm3, zmm16, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD50435A807B" , vshufi64x2(zmm3, zmm16, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3FD50439AF8FBFFFF7B" , vshufi64x2(zmm3, zmm16, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62A2C54036EE" , vpermq(zmm21, zmm23, zmm22)); + TEST_INSTRUCTION("62A2C54136EE" , k(k1).vpermq(zmm21, zmm23, zmm22)); + TEST_INSTRUCTION("62A2C5C136EE" , k(k1).z().vpermq(zmm21, zmm23, zmm22)); + TEST_INSTRUCTION("62E2C5403629" , vpermq(zmm21, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2C54036ACF023010000" , vpermq(zmm21, zmm23, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2C5503629" , vpermq(zmm21, zmm23, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2C540366A7F" , vpermq(zmm21, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2C54036AA00200000" , vpermq(zmm21, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2C540366A80" , vpermq(zmm21, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2C54036AAC0DFFFFF" , vpermq(zmm21, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2C550366A7F" , vpermq(zmm21, zmm23, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2C55036AA00040000" , vpermq(zmm21, zmm23, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2C550366A80" , vpermq(zmm21, zmm23, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2C55036AAF8FBFFFF" , vpermq(zmm21, zmm23, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6222954016D2" , vpermpd(zmm26, zmm29, zmm18)); + TEST_INSTRUCTION("6222954616D2" , k(k6).vpermpd(zmm26, zmm29, zmm18)); + TEST_INSTRUCTION("622295C616D2" , k(k6).z().vpermpd(zmm26, zmm29, zmm18)); + TEST_INSTRUCTION("626295401611" , vpermpd(zmm26, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622295401694F023010000" , vpermpd(zmm26, zmm29, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626295501611" , vpermpd(zmm26, zmm29, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262954016527F" , vpermpd(zmm26, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62629540169200200000" , vpermpd(zmm26, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62629540165280" , vpermpd(zmm26, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626295401692C0DFFFFF" , vpermpd(zmm26, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262955016527F" , vpermpd(zmm26, zmm29, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62629550169200040000" , vpermpd(zmm26, zmm29, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62629550165280" , vpermpd(zmm26, zmm29, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("626295501692F8FBFFFF" , vpermpd(zmm26, zmm29, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62724D487EEE" , vpermt2d(zmm13, zmm6, zmm6)); + TEST_INSTRUCTION("62724D4E7EEE" , k(k6).vpermt2d(zmm13, zmm6, zmm6)); + TEST_INSTRUCTION("62724DCE7EEE" , k(k6).z().vpermt2d(zmm13, zmm6, zmm6)); + TEST_INSTRUCTION("62724D487E29" , vpermt2d(zmm13, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62324D487EACF023010000" , vpermt2d(zmm13, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62724D587E29" , vpermt2d(zmm13, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62724D487E6A7F" , vpermt2d(zmm13, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62724D487EAA00200000" , vpermt2d(zmm13, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62724D487E6A80" , vpermt2d(zmm13, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62724D487EAAC0DFFFFF" , vpermt2d(zmm13, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62724D587E6A7F" , vpermt2d(zmm13, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62724D587EAA00020000" , vpermt2d(zmm13, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62724D587E6A80" , vpermt2d(zmm13, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62724D587EAAFCFDFFFF" , vpermt2d(zmm13, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A29D487EE8" , vpermt2q(zmm21, zmm12, zmm16)); + TEST_INSTRUCTION("62A29D4A7EE8" , k(k2).vpermt2q(zmm21, zmm12, zmm16)); + TEST_INSTRUCTION("62A29DCA7EE8" , k(k2).z().vpermt2q(zmm21, zmm12, zmm16)); + TEST_INSTRUCTION("62E29D487E29" , vpermt2q(zmm21, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A29D487EACF023010000" , vpermt2q(zmm21, zmm12, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E29D587E29" , vpermt2q(zmm21, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E29D487E6A7F" , vpermt2q(zmm21, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E29D487EAA00200000" , vpermt2q(zmm21, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E29D487E6A80" , vpermt2q(zmm21, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E29D487EAAC0DFFFFF" , vpermt2q(zmm21, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E29D587E6A7F" , vpermt2q(zmm21, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E29D587EAA00040000" , vpermt2q(zmm21, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E29D587E6A80" , vpermt2q(zmm21, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E29D587EAAF8FBFFFF" , vpermt2q(zmm21, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62721D407FDA" , vpermt2ps(zmm11, zmm28, zmm2)); + TEST_INSTRUCTION("62721D417FDA" , k(k1).vpermt2ps(zmm11, zmm28, zmm2)); + TEST_INSTRUCTION("62721DC17FDA" , k(k1).z().vpermt2ps(zmm11, zmm28, zmm2)); + TEST_INSTRUCTION("62721D407F19" , vpermt2ps(zmm11, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62321D407F9CF023010000" , vpermt2ps(zmm11, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62721D507F19" , vpermt2ps(zmm11, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62721D407F5A7F" , vpermt2ps(zmm11, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62721D407F9A00200000" , vpermt2ps(zmm11, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62721D407F5A80" , vpermt2ps(zmm11, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62721D407F9AC0DFFFFF" , vpermt2ps(zmm11, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62721D507F5A7F" , vpermt2ps(zmm11, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62721D507F9A00020000" , vpermt2ps(zmm11, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62721D507F5A80" , vpermt2ps(zmm11, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62721D507F9AFCFDFFFF" , vpermt2ps(zmm11, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D2A5407FDB" , vpermt2pd(zmm3, zmm27, zmm11)); + TEST_INSTRUCTION("62D2A5427FDB" , k(k2).vpermt2pd(zmm3, zmm27, zmm11)); + TEST_INSTRUCTION("62D2A5C27FDB" , k(k2).z().vpermt2pd(zmm3, zmm27, zmm11)); + TEST_INSTRUCTION("62F2A5407F19" , vpermt2pd(zmm3, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2A5407F9CF023010000" , vpermt2pd(zmm3, zmm27, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F2A5507F19" , vpermt2pd(zmm3, zmm27, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2A5407F5A7F" , vpermt2pd(zmm3, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2A5407F9A00200000" , vpermt2pd(zmm3, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2A5407F5A80" , vpermt2pd(zmm3, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2A5407F9AC0DFFFFF" , vpermt2pd(zmm3, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2A5507F5A7F" , vpermt2pd(zmm3, zmm27, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2A5507F9A00040000" , vpermt2pd(zmm3, zmm27, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2A5507F5A80" , vpermt2pd(zmm3, zmm27, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2A5507F9AF8FBFFFF" , vpermt2pd(zmm3, zmm27, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6223DD4803E7AB" , valignq(zmm28, zmm4, zmm23, 171)); + TEST_INSTRUCTION("6223DD4B03E7AB" , k(k3).valignq(zmm28, zmm4, zmm23, 171)); + TEST_INSTRUCTION("6223DDCB03E7AB" , k(k3).z().valignq(zmm28, zmm4, zmm23, 171)); + TEST_INSTRUCTION("6223DD4803E77B" , valignq(zmm28, zmm4, zmm23, 123)); + TEST_INSTRUCTION("6263DD4803217B" , valignq(zmm28, zmm4, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223DD4803A4F0230100007B" , valignq(zmm28, zmm4, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6263DD5803217B" , valignq(zmm28, zmm4, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6263DD4803627F7B" , valignq(zmm28, zmm4, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6263DD4803A2002000007B" , valignq(zmm28, zmm4, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6263DD480362807B" , valignq(zmm28, zmm4, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6263DD4803A2C0DFFFFF7B" , valignq(zmm28, zmm4, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6263DD5803627F7B" , valignq(zmm28, zmm4, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6263DD5803A2000400007B" , valignq(zmm28, zmm4, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6263DD580362807B" , valignq(zmm28, zmm4, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6263DD5803A2F8FBFFFF7B" , valignq(zmm28, zmm4, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62917F0879C6" , vcvtsd2usi(eax, xmm30)); + TEST_INSTRUCTION("62917F1879C6" , rn_sae().vcvtsd2usi(eax, xmm30)); + TEST_INSTRUCTION("62917F5879C6" , ru_sae().vcvtsd2usi(eax, xmm30)); + TEST_INSTRUCTION("62917F3879C6" , rd_sae().vcvtsd2usi(eax, xmm30)); + TEST_INSTRUCTION("62917F7879C6" , rz_sae().vcvtsd2usi(eax, xmm30)); + TEST_INSTRUCTION("62F17F087901" , vcvtsd2usi(eax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F087984F023010000" , vcvtsd2usi(eax, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17F0879427F" , vcvtsd2usi(eax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F08798200040000" , vcvtsd2usi(eax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08794280" , vcvtsd2usi(eax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F087982F8FBFFFF" , vcvtsd2usi(eax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62917F0879EE" , vcvtsd2usi(ebp, xmm30)); + TEST_INSTRUCTION("62917F1879EE" , rn_sae().vcvtsd2usi(ebp, xmm30)); + TEST_INSTRUCTION("62917F5879EE" , ru_sae().vcvtsd2usi(ebp, xmm30)); + TEST_INSTRUCTION("62917F3879EE" , rd_sae().vcvtsd2usi(ebp, xmm30)); + TEST_INSTRUCTION("62917F7879EE" , rz_sae().vcvtsd2usi(ebp, xmm30)); + TEST_INSTRUCTION("62F17F087929" , vcvtsd2usi(ebp, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F0879ACF023010000" , vcvtsd2usi(ebp, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17F08796A7F" , vcvtsd2usi(ebp, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F0879AA00040000" , vcvtsd2usi(ebp, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08796A80" , vcvtsd2usi(ebp, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F0879AAF8FBFFFF" , vcvtsd2usi(ebp, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62117F0879EE" , vcvtsd2usi(r13d, xmm30)); + TEST_INSTRUCTION("62117F1879EE" , rn_sae().vcvtsd2usi(r13d, xmm30)); + TEST_INSTRUCTION("62117F5879EE" , ru_sae().vcvtsd2usi(r13d, xmm30)); + TEST_INSTRUCTION("62117F3879EE" , rd_sae().vcvtsd2usi(r13d, xmm30)); + TEST_INSTRUCTION("62117F7879EE" , rz_sae().vcvtsd2usi(r13d, xmm30)); + TEST_INSTRUCTION("62717F087929" , vcvtsd2usi(r13d, qword_ptr(rcx))); + TEST_INSTRUCTION("62317F0879ACF023010000" , vcvtsd2usi(r13d, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717F08796A7F" , vcvtsd2usi(r13d, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62717F0879AA00040000" , vcvtsd2usi(r13d, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62717F08796A80" , vcvtsd2usi(r13d, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62717F0879AAF8FBFFFF" , vcvtsd2usi(r13d, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B1FF0879C2" , vcvtsd2usi(rax, xmm18)); + TEST_INSTRUCTION("62B1FF1879C2" , rn_sae().vcvtsd2usi(rax, xmm18)); + TEST_INSTRUCTION("62B1FF5879C2" , ru_sae().vcvtsd2usi(rax, xmm18)); + TEST_INSTRUCTION("62B1FF3879C2" , rd_sae().vcvtsd2usi(rax, xmm18)); + TEST_INSTRUCTION("62B1FF7879C2" , rz_sae().vcvtsd2usi(rax, xmm18)); + TEST_INSTRUCTION("62F1FF087901" , vcvtsd2usi(rax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF087984F023010000" , vcvtsd2usi(rax, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FF0879427F" , vcvtsd2usi(rax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1FF08798200040000" , vcvtsd2usi(rax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1FF08794280" , vcvtsd2usi(rax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1FF087982F8FBFFFF" , vcvtsd2usi(rax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6231FF0879C2" , vcvtsd2usi(r8, xmm18)); + TEST_INSTRUCTION("6231FF1879C2" , rn_sae().vcvtsd2usi(r8, xmm18)); + TEST_INSTRUCTION("6231FF5879C2" , ru_sae().vcvtsd2usi(r8, xmm18)); + TEST_INSTRUCTION("6231FF3879C2" , rd_sae().vcvtsd2usi(r8, xmm18)); + TEST_INSTRUCTION("6231FF7879C2" , rz_sae().vcvtsd2usi(r8, xmm18)); + TEST_INSTRUCTION("6271FF087901" , vcvtsd2usi(r8, qword_ptr(rcx))); + TEST_INSTRUCTION("6231FF087984F023010000" , vcvtsd2usi(r8, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271FF0879427F" , vcvtsd2usi(r8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271FF08798200040000" , vcvtsd2usi(r8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271FF08794280" , vcvtsd2usi(r8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271FF087982F8FBFFFF" , vcvtsd2usi(r8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62917E0879C4" , vcvtss2usi(eax, xmm28)); + TEST_INSTRUCTION("62917E1879C4" , rn_sae().vcvtss2usi(eax, xmm28)); + TEST_INSTRUCTION("62917E5879C4" , ru_sae().vcvtss2usi(eax, xmm28)); + TEST_INSTRUCTION("62917E3879C4" , rd_sae().vcvtss2usi(eax, xmm28)); + TEST_INSTRUCTION("62917E7879C4" , rz_sae().vcvtss2usi(eax, xmm28)); + TEST_INSTRUCTION("62F17E087901" , vcvtss2usi(eax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E087984F023010000" , vcvtss2usi(eax, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17E0879427F" , vcvtss2usi(eax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E08798200020000" , vcvtss2usi(eax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08794280" , vcvtss2usi(eax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E087982FCFDFFFF" , vcvtss2usi(eax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62917E0879EC" , vcvtss2usi(ebp, xmm28)); + TEST_INSTRUCTION("62917E1879EC" , rn_sae().vcvtss2usi(ebp, xmm28)); + TEST_INSTRUCTION("62917E5879EC" , ru_sae().vcvtss2usi(ebp, xmm28)); + TEST_INSTRUCTION("62917E3879EC" , rd_sae().vcvtss2usi(ebp, xmm28)); + TEST_INSTRUCTION("62917E7879EC" , rz_sae().vcvtss2usi(ebp, xmm28)); + TEST_INSTRUCTION("62F17E087929" , vcvtss2usi(ebp, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E0879ACF023010000" , vcvtss2usi(ebp, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17E08796A7F" , vcvtss2usi(ebp, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E0879AA00020000" , vcvtss2usi(ebp, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08796A80" , vcvtss2usi(ebp, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E0879AAFCFDFFFF" , vcvtss2usi(ebp, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62117E0879EC" , vcvtss2usi(r13d, xmm28)); + TEST_INSTRUCTION("62117E1879EC" , rn_sae().vcvtss2usi(r13d, xmm28)); + TEST_INSTRUCTION("62117E5879EC" , ru_sae().vcvtss2usi(r13d, xmm28)); + TEST_INSTRUCTION("62117E3879EC" , rd_sae().vcvtss2usi(r13d, xmm28)); + TEST_INSTRUCTION("62117E7879EC" , rz_sae().vcvtss2usi(r13d, xmm28)); + TEST_INSTRUCTION("62717E087929" , vcvtss2usi(r13d, dword_ptr(rcx))); + TEST_INSTRUCTION("62317E0879ACF023010000" , vcvtss2usi(r13d, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717E08796A7F" , vcvtss2usi(r13d, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62717E0879AA00020000" , vcvtss2usi(r13d, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62717E08796A80" , vcvtss2usi(r13d, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62717E0879AAFCFDFFFF" , vcvtss2usi(r13d, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B1FE0879C7" , vcvtss2usi(rax, xmm23)); + TEST_INSTRUCTION("62B1FE1879C7" , rn_sae().vcvtss2usi(rax, xmm23)); + TEST_INSTRUCTION("62B1FE5879C7" , ru_sae().vcvtss2usi(rax, xmm23)); + TEST_INSTRUCTION("62B1FE3879C7" , rd_sae().vcvtss2usi(rax, xmm23)); + TEST_INSTRUCTION("62B1FE7879C7" , rz_sae().vcvtss2usi(rax, xmm23)); + TEST_INSTRUCTION("62F1FE087901" , vcvtss2usi(rax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B1FE087984F023010000" , vcvtss2usi(rax, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FE0879427F" , vcvtss2usi(rax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F1FE08798200020000" , vcvtss2usi(rax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F1FE08794280" , vcvtss2usi(rax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F1FE087982FCFDFFFF" , vcvtss2usi(rax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6231FE0879C7" , vcvtss2usi(r8, xmm23)); + TEST_INSTRUCTION("6231FE1879C7" , rn_sae().vcvtss2usi(r8, xmm23)); + TEST_INSTRUCTION("6231FE5879C7" , ru_sae().vcvtss2usi(r8, xmm23)); + TEST_INSTRUCTION("6231FE3879C7" , rd_sae().vcvtss2usi(r8, xmm23)); + TEST_INSTRUCTION("6231FE7879C7" , rz_sae().vcvtss2usi(r8, xmm23)); + TEST_INSTRUCTION("6271FE087901" , vcvtss2usi(r8, dword_ptr(rcx))); + TEST_INSTRUCTION("6231FE087984F023010000" , vcvtss2usi(r8, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271FE0879427F" , vcvtss2usi(r8, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("6271FE08798200020000" , vcvtss2usi(r8, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("6271FE08794280" , vcvtss2usi(r8, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("6271FE087982FCFDFFFF" , vcvtss2usi(r8, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62E177087BD8" , vcvtusi2sd(xmm19, xmm1, eax)); + TEST_INSTRUCTION("62E177087BDD" , vcvtusi2sd(xmm19, xmm1, ebp)); + TEST_INSTRUCTION("62C177087BDD" , vcvtusi2sd(xmm19, xmm1, r13d)); + TEST_INSTRUCTION("62E177087B19" , vcvtusi2sd(xmm19, xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("62A177087B9CF023010000" , vcvtusi2sd(xmm19, xmm1, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E177087B5A7F" , vcvtusi2sd(xmm19, xmm1, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E177087B9A00020000" , vcvtusi2sd(xmm19, xmm1, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E177087B5A80" , vcvtusi2sd(xmm19, xmm1, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E177087B9AFCFDFFFF" , vcvtusi2sd(xmm19, xmm1, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6271AF007BF0" , vcvtusi2sd(xmm14, xmm26, rax)); + TEST_INSTRUCTION("6271AF107BF0" , rn_sae().vcvtusi2sd(xmm14, xmm26, rax)); + TEST_INSTRUCTION("6271AF507BF0" , ru_sae().vcvtusi2sd(xmm14, xmm26, rax)); + TEST_INSTRUCTION("6271AF307BF0" , rd_sae().vcvtusi2sd(xmm14, xmm26, rax)); + TEST_INSTRUCTION("6271AF707BF0" , rz_sae().vcvtusi2sd(xmm14, xmm26, rax)); + TEST_INSTRUCTION("6251AF007BF0" , vcvtusi2sd(xmm14, xmm26, r8)); + TEST_INSTRUCTION("6251AF107BF0" , rn_sae().vcvtusi2sd(xmm14, xmm26, r8)); + TEST_INSTRUCTION("6251AF507BF0" , ru_sae().vcvtusi2sd(xmm14, xmm26, r8)); + TEST_INSTRUCTION("6251AF307BF0" , rd_sae().vcvtusi2sd(xmm14, xmm26, r8)); + TEST_INSTRUCTION("6251AF707BF0" , rz_sae().vcvtusi2sd(xmm14, xmm26, r8)); + TEST_INSTRUCTION("6271AF007B31" , vcvtusi2sd(xmm14, xmm26, qword_ptr(rcx))); + TEST_INSTRUCTION("6231AF007BB4F023010000" , vcvtusi2sd(xmm14, xmm26, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271AF007B727F" , vcvtusi2sd(xmm14, xmm26, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271AF007BB200040000" , vcvtusi2sd(xmm14, xmm26, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271AF007B7280" , vcvtusi2sd(xmm14, xmm26, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271AF007BB2F8FBFFFF" , vcvtusi2sd(xmm14, xmm26, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62F12E007BE8" , vcvtusi2ss(xmm5, xmm26, eax)); + TEST_INSTRUCTION("62F12E107BE8" , rn_sae().vcvtusi2ss(xmm5, xmm26, eax)); + TEST_INSTRUCTION("62F12E507BE8" , ru_sae().vcvtusi2ss(xmm5, xmm26, eax)); + TEST_INSTRUCTION("62F12E307BE8" , rd_sae().vcvtusi2ss(xmm5, xmm26, eax)); + TEST_INSTRUCTION("62F12E707BE8" , rz_sae().vcvtusi2ss(xmm5, xmm26, eax)); + TEST_INSTRUCTION("62F12E007BED" , vcvtusi2ss(xmm5, xmm26, ebp)); + TEST_INSTRUCTION("62F12E107BED" , rn_sae().vcvtusi2ss(xmm5, xmm26, ebp)); + TEST_INSTRUCTION("62F12E507BED" , ru_sae().vcvtusi2ss(xmm5, xmm26, ebp)); + TEST_INSTRUCTION("62F12E307BED" , rd_sae().vcvtusi2ss(xmm5, xmm26, ebp)); + TEST_INSTRUCTION("62F12E707BED" , rz_sae().vcvtusi2ss(xmm5, xmm26, ebp)); + TEST_INSTRUCTION("62D12E007BED" , vcvtusi2ss(xmm5, xmm26, r13d)); + TEST_INSTRUCTION("62D12E107BED" , rn_sae().vcvtusi2ss(xmm5, xmm26, r13d)); + TEST_INSTRUCTION("62D12E507BED" , ru_sae().vcvtusi2ss(xmm5, xmm26, r13d)); + TEST_INSTRUCTION("62D12E307BED" , rd_sae().vcvtusi2ss(xmm5, xmm26, r13d)); + TEST_INSTRUCTION("62D12E707BED" , rz_sae().vcvtusi2ss(xmm5, xmm26, r13d)); + TEST_INSTRUCTION("62F12E007B29" , vcvtusi2ss(xmm5, xmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62B12E007BACF023010000" , vcvtusi2ss(xmm5, xmm26, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F12E007B6A7F" , vcvtusi2ss(xmm5, xmm26, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F12E007BAA00020000" , vcvtusi2ss(xmm5, xmm26, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F12E007B6A80" , vcvtusi2ss(xmm5, xmm26, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F12E007BAAFCFDFFFF" , vcvtusi2ss(xmm5, xmm26, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6271CE007BF0" , vcvtusi2ss(xmm14, xmm22, rax)); + TEST_INSTRUCTION("6271CE107BF0" , rn_sae().vcvtusi2ss(xmm14, xmm22, rax)); + TEST_INSTRUCTION("6271CE507BF0" , ru_sae().vcvtusi2ss(xmm14, xmm22, rax)); + TEST_INSTRUCTION("6271CE307BF0" , rd_sae().vcvtusi2ss(xmm14, xmm22, rax)); + TEST_INSTRUCTION("6271CE707BF0" , rz_sae().vcvtusi2ss(xmm14, xmm22, rax)); + TEST_INSTRUCTION("6251CE007BF0" , vcvtusi2ss(xmm14, xmm22, r8)); + TEST_INSTRUCTION("6251CE107BF0" , rn_sae().vcvtusi2ss(xmm14, xmm22, r8)); + TEST_INSTRUCTION("6251CE507BF0" , ru_sae().vcvtusi2ss(xmm14, xmm22, r8)); + TEST_INSTRUCTION("6251CE307BF0" , rd_sae().vcvtusi2ss(xmm14, xmm22, r8)); + TEST_INSTRUCTION("6251CE707BF0" , rz_sae().vcvtusi2ss(xmm14, xmm22, r8)); + TEST_INSTRUCTION("6271CE007B31" , vcvtusi2ss(xmm14, xmm22, qword_ptr(rcx))); + TEST_INSTRUCTION("6231CE007BB4F023010000" , vcvtusi2ss(xmm14, xmm22, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271CE007B727F" , vcvtusi2ss(xmm14, xmm22, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271CE007BB200040000" , vcvtusi2ss(xmm14, xmm22, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271CE007B7280" , vcvtusi2ss(xmm14, xmm22, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271CE007BB2F8FBFFFF" , vcvtusi2ss(xmm14, xmm22, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6202AD402CD4" , vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6202AD452CD4" , k(k5).vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6202ADC52CD4" , k(k5).z().vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6202AD102CD4" , rn_sae().vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6202AD502CD4" , ru_sae().vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6202AD302CD4" , rd_sae().vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6202AD702CD4" , rz_sae().vscalefpd(zmm26, zmm26, zmm28)); + TEST_INSTRUCTION("6262AD402C11" , vscalefpd(zmm26, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222AD402C94F023010000" , vscalefpd(zmm26, zmm26, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262AD502C11" , vscalefpd(zmm26, zmm26, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262AD402C527F" , vscalefpd(zmm26, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262AD402C9200200000" , vscalefpd(zmm26, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262AD402C5280" , vscalefpd(zmm26, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262AD402C92C0DFFFFF" , vscalefpd(zmm26, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262AD502C527F" , vscalefpd(zmm26, zmm26, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262AD502C9200040000" , vscalefpd(zmm26, zmm26, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262AD502C5280" , vscalefpd(zmm26, zmm26, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262AD502C92F8FBFFFF" , vscalefpd(zmm26, zmm26, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62A24D482CDA" , vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62A24D4E2CDA" , k(k6).vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62A24DCE2CDA" , k(k6).z().vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62A24D182CDA" , rn_sae().vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62A24D582CDA" , ru_sae().vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62A24D382CDA" , rd_sae().vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62A24D782CDA" , rz_sae().vscalefps(zmm19, zmm6, zmm18)); + TEST_INSTRUCTION("62E24D482C19" , vscalefps(zmm19, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A24D482C9CF023010000" , vscalefps(zmm19, zmm6, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E24D582C19" , vscalefps(zmm19, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E24D482C5A7F" , vscalefps(zmm19, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E24D482C9A00200000" , vscalefps(zmm19, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E24D482C5A80" , vscalefps(zmm19, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E24D482C9AC0DFFFFF" , vscalefps(zmm19, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E24D582C5A7F" , vscalefps(zmm19, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E24D582C9A00020000" , vscalefps(zmm19, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E24D582C5A80" , vscalefps(zmm19, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E24D582C9AFCFDFFFF" , vscalefps(zmm19, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A2CD002DED" , vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62A2CD022DED" , k(k2).vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62A2CD822DED" , k(k2).z().vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62A2CD102DED" , rn_sae().vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62A2CD502DED" , ru_sae().vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62A2CD302DED" , rd_sae().vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62A2CD702DED" , rz_sae().vscalefsd(xmm21, xmm22, xmm21)); + TEST_INSTRUCTION("62E2CD002D29" , vscalefsd(xmm21, xmm22, qword_ptr(rcx))); + TEST_INSTRUCTION("62A2CD002DACF023010000" , vscalefsd(xmm21, xmm22, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2CD002D6A7F" , vscalefsd(xmm21, xmm22, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E2CD002DAA00040000" , vscalefsd(xmm21, xmm22, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E2CD002D6A80" , vscalefsd(xmm21, xmm22, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E2CD002DAAF8FBFFFF" , vscalefsd(xmm21, xmm22, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("623205082DEF" , vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("6232050B2DEF" , k(k3).vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("6232058B2DEF" , k(k3).z().vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("623205182DEF" , rn_sae().vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("623205582DEF" , ru_sae().vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("623205382DEF" , rd_sae().vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("623205782DEF" , rz_sae().vscalefss(xmm13, xmm15, xmm23)); + TEST_INSTRUCTION("627205082D29" , vscalefss(xmm13, xmm15, dword_ptr(rcx))); + TEST_INSTRUCTION("623205082DACF023010000" , vscalefss(xmm13, xmm15, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("627205082D6A7F" , vscalefss(xmm13, xmm15, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("627205082DAA00020000" , vscalefss(xmm13, xmm15, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("627205082D6A80" , vscalefss(xmm13, xmm15, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("627205082DAAFCFDFFFF" , vscalefss(xmm13, xmm15, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62732D4054FAAB" , vfixupimmps(zmm15, zmm26, zmm2, 171)); + TEST_INSTRUCTION("62732D4454FAAB" , k(k4).vfixupimmps(zmm15, zmm26, zmm2, 171)); + TEST_INSTRUCTION("62732DC454FAAB" , k(k4).z().vfixupimmps(zmm15, zmm26, zmm2, 171)); + TEST_INSTRUCTION("62732D1054FAAB" , sae().vfixupimmps(zmm15, zmm26, zmm2, 171)); + TEST_INSTRUCTION("62732D4054FA7B" , vfixupimmps(zmm15, zmm26, zmm2, 123)); + TEST_INSTRUCTION("62732D1054FA7B" , sae().vfixupimmps(zmm15, zmm26, zmm2, 123)); + TEST_INSTRUCTION("62732D4054397B" , vfixupimmps(zmm15, zmm26, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62332D4054BCF0230100007B" , vfixupimmps(zmm15, zmm26, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62732D5054397B" , vfixupimmps(zmm15, zmm26, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62732D40547A7F7B" , vfixupimmps(zmm15, zmm26, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62732D4054BA002000007B" , vfixupimmps(zmm15, zmm26, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62732D40547A807B" , vfixupimmps(zmm15, zmm26, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62732D4054BAC0DFFFFF7B" , vfixupimmps(zmm15, zmm26, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62732D50547A7F7B" , vfixupimmps(zmm15, zmm26, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62732D5054BA000200007B" , vfixupimmps(zmm15, zmm26, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62732D50547A807B" , vfixupimmps(zmm15, zmm26, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62732D5054BAFCFDFFFF7B" , vfixupimmps(zmm15, zmm26, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6233D54054CBAB" , vfixupimmpd(zmm9, zmm21, zmm19, 171)); + TEST_INSTRUCTION("6233D54254CBAB" , k(k2).vfixupimmpd(zmm9, zmm21, zmm19, 171)); + TEST_INSTRUCTION("6233D5C254CBAB" , k(k2).z().vfixupimmpd(zmm9, zmm21, zmm19, 171)); + TEST_INSTRUCTION("6233D51054CBAB" , sae().vfixupimmpd(zmm9, zmm21, zmm19, 171)); + TEST_INSTRUCTION("6233D54054CB7B" , vfixupimmpd(zmm9, zmm21, zmm19, 123)); + TEST_INSTRUCTION("6233D51054CB7B" , sae().vfixupimmpd(zmm9, zmm21, zmm19, 123)); + TEST_INSTRUCTION("6273D54054097B" , vfixupimmpd(zmm9, zmm21, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233D540548CF0230100007B" , vfixupimmpd(zmm9, zmm21, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6273D55054097B" , vfixupimmpd(zmm9, zmm21, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273D540544A7F7B" , vfixupimmpd(zmm9, zmm21, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273D540548A002000007B" , vfixupimmpd(zmm9, zmm21, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273D540544A807B" , vfixupimmpd(zmm9, zmm21, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273D540548AC0DFFFFF7B" , vfixupimmpd(zmm9, zmm21, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273D550544A7F7B" , vfixupimmpd(zmm9, zmm21, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273D550548A000400007B" , vfixupimmpd(zmm9, zmm21, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273D550544A807B" , vfixupimmpd(zmm9, zmm21, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273D550548AF8FBFFFF7B" , vfixupimmpd(zmm9, zmm21, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62136D0055FCAB" , vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D0555FCAB" , k(k5).vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D8555FCAB" , k(k5).z().vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D1055FCAB" , sae().vfixupimmss(xmm15, xmm18, xmm28, 171)); + TEST_INSTRUCTION("62136D0055FC7B" , vfixupimmss(xmm15, xmm18, xmm28, 123)); + TEST_INSTRUCTION("62136D1055FC7B" , sae().vfixupimmss(xmm15, xmm18, xmm28, 123)); + TEST_INSTRUCTION("62736D0055397B" , vfixupimmss(xmm15, xmm18, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62336D0055BCF0230100007B" , vfixupimmss(xmm15, xmm18, dword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62736D00557A7F7B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62736D0055BA000200007B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62736D00557A807B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62736D0055BAFCFDFFFF7B" , vfixupimmss(xmm15, xmm18, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("6273AD0055EDAB" , vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD0655EDAB" , k(k6).vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD8655EDAB" , k(k6).z().vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD1055EDAB" , sae().vfixupimmsd(xmm13, xmm26, xmm5, 171)); + TEST_INSTRUCTION("6273AD0055ED7B" , vfixupimmsd(xmm13, xmm26, xmm5, 123)); + TEST_INSTRUCTION("6273AD1055ED7B" , sae().vfixupimmsd(xmm13, xmm26, xmm5, 123)); + TEST_INSTRUCTION("6273AD0055297B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233AD0055ACF0230100007B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("6273AD00556A7F7B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("6273AD0055AA000400007B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("6273AD00556A807B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("6273AD0055AAF8FBFFFF7B" , vfixupimmsd(xmm13, xmm26, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("6291154072F0AB" , vpslld(zmm29, zmm24, 171)); + TEST_INSTRUCTION("6291154672F0AB" , k(k6).vpslld(zmm29, zmm24, 171)); + TEST_INSTRUCTION("629115C672F0AB" , k(k6).z().vpslld(zmm29, zmm24, 171)); + TEST_INSTRUCTION("6291154072F07B" , vpslld(zmm29, zmm24, 123)); + TEST_INSTRUCTION("62F1154072317B" , vpslld(zmm29, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1154072B4F0230100007B" , vpslld(zmm29, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1155072317B" , vpslld(zmm29, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1154072727F7B" , vpslld(zmm29, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1154072B2002000007B" , vpslld(zmm29, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F115407272807B" , vpslld(zmm29, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1154072B2C0DFFFFF7B" , vpslld(zmm29, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1155072727F7B" , vpslld(zmm29, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F1155072B2000200007B" , vpslld(zmm29, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F115507272807B" , vpslld(zmm29, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F1155072B2FCFDFFFF7B" , vpslld(zmm29, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D1CD4873F3AB" , vpsllq(zmm6, zmm11, 171)); + TEST_INSTRUCTION("62D1CD4A73F3AB" , k(k2).vpsllq(zmm6, zmm11, 171)); + TEST_INSTRUCTION("62D1CDCA73F3AB" , k(k2).z().vpsllq(zmm6, zmm11, 171)); + TEST_INSTRUCTION("62D1CD4873F37B" , vpsllq(zmm6, zmm11, 123)); + TEST_INSTRUCTION("62F1CD4873317B" , vpsllq(zmm6, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1CD4873B4F0230100007B" , vpsllq(zmm6, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1CD5873317B" , vpsllq(zmm6, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD4873727F7B" , vpsllq(zmm6, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1CD4873B2002000007B" , vpsllq(zmm6, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1CD487372807B" , vpsllq(zmm6, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1CD4873B2C0DFFFFF7B" , vpsllq(zmm6, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1CD5873727F7B" , vpsllq(zmm6, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD5873B2000400007B" , vpsllq(zmm6, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD587372807B" , vpsllq(zmm6, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD5873B2F8FBFFFF7B" , vpsllq(zmm6, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F1254072E5AB" , vpsrad(zmm27, zmm5, 171)); + TEST_INSTRUCTION("62F1254572E5AB" , k(k5).vpsrad(zmm27, zmm5, 171)); + TEST_INSTRUCTION("62F125C572E5AB" , k(k5).z().vpsrad(zmm27, zmm5, 171)); + TEST_INSTRUCTION("62F1254072E57B" , vpsrad(zmm27, zmm5, 123)); + TEST_INSTRUCTION("62F1254072217B" , vpsrad(zmm27, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1254072A4F0230100007B" , vpsrad(zmm27, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1255072217B" , vpsrad(zmm27, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1254072627F7B" , vpsrad(zmm27, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1254072A2002000007B" , vpsrad(zmm27, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F125407262807B" , vpsrad(zmm27, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1254072A2C0DFFFFF7B" , vpsrad(zmm27, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1255072627F7B" , vpsrad(zmm27, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F1255072A2000200007B" , vpsrad(zmm27, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F125507262807B" , vpsrad(zmm27, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F1255072A2FCFDFFFF7B" , vpsrad(zmm27, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62F1954072E5AB" , vpsraq(zmm29, zmm5, 171)); + TEST_INSTRUCTION("62F1954472E5AB" , k(k4).vpsraq(zmm29, zmm5, 171)); + TEST_INSTRUCTION("62F195C472E5AB" , k(k4).z().vpsraq(zmm29, zmm5, 171)); + TEST_INSTRUCTION("62F1954072E57B" , vpsraq(zmm29, zmm5, 123)); + TEST_INSTRUCTION("62F1954072217B" , vpsraq(zmm29, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1954072A4F0230100007B" , vpsraq(zmm29, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1955072217B" , vpsraq(zmm29, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1954072627F7B" , vpsraq(zmm29, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1954072A2002000007B" , vpsraq(zmm29, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F195407262807B" , vpsraq(zmm29, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1954072A2C0DFFFFF7B" , vpsraq(zmm29, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1955072627F7B" , vpsraq(zmm29, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1955072A2000400007B" , vpsraq(zmm29, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F195507262807B" , vpsraq(zmm29, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1955072A2F8FBFFFF7B" , vpsraq(zmm29, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62B2154015F0" , vprolvd(zmm6, zmm29, zmm16)); + TEST_INSTRUCTION("62B2154215F0" , k(k2).vprolvd(zmm6, zmm29, zmm16)); + TEST_INSTRUCTION("62B215C215F0" , k(k2).z().vprolvd(zmm6, zmm29, zmm16)); + TEST_INSTRUCTION("62F215401531" , vprolvd(zmm6, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2154015B4F023010000" , vprolvd(zmm6, zmm29, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F215501531" , vprolvd(zmm6, zmm29, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F2154015727F" , vprolvd(zmm6, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2154015B200200000" , vprolvd(zmm6, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F21540157280" , vprolvd(zmm6, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2154015B2C0DFFFFF" , vprolvd(zmm6, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2155015727F" , vprolvd(zmm6, zmm29, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F2155015B200020000" , vprolvd(zmm6, zmm29, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F21550157280" , vprolvd(zmm6, zmm29, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F2155015B2FCFDFFFF" , vprolvd(zmm6, zmm29, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F12D4872CDAB" , vprold(zmm10, zmm5, 171)); + TEST_INSTRUCTION("62F12D4F72CDAB" , k(k7).vprold(zmm10, zmm5, 171)); + TEST_INSTRUCTION("62F12DCF72CDAB" , k(k7).z().vprold(zmm10, zmm5, 171)); + TEST_INSTRUCTION("62F12D4872CD7B" , vprold(zmm10, zmm5, 123)); + TEST_INSTRUCTION("62F12D4872097B" , vprold(zmm10, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B12D48728CF0230100007B" , vprold(zmm10, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F12D5872097B" , vprold(zmm10, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F12D48724A7F7B" , vprold(zmm10, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F12D48728A002000007B" , vprold(zmm10, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F12D48724A807B" , vprold(zmm10, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F12D48728AC0DFFFFF7B" , vprold(zmm10, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F12D58724A7F7B" , vprold(zmm10, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F12D58728A000200007B" , vprold(zmm10, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F12D58724A807B" , vprold(zmm10, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F12D58728AFCFDFFFF7B" , vprold(zmm10, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6262DD4815DE" , vprolvq(zmm27, zmm4, zmm6)); + TEST_INSTRUCTION("6262DD4D15DE" , k(k5).vprolvq(zmm27, zmm4, zmm6)); + TEST_INSTRUCTION("6262DDCD15DE" , k(k5).z().vprolvq(zmm27, zmm4, zmm6)); + TEST_INSTRUCTION("6262DD481519" , vprolvq(zmm27, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222DD48159CF023010000" , vprolvq(zmm27, zmm4, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6262DD581519" , vprolvq(zmm27, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262DD48155A7F" , vprolvq(zmm27, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262DD48159A00200000" , vprolvq(zmm27, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262DD48155A80" , vprolvq(zmm27, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262DD48159AC0DFFFFF" , vprolvq(zmm27, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262DD58155A7F" , vprolvq(zmm27, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262DD58159A00040000" , vprolvq(zmm27, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262DD58155A80" , vprolvq(zmm27, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262DD58159AF8FBFFFF" , vprolvq(zmm27, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B1E54072CAAB" , vprolq(zmm19, zmm18, 171)); + TEST_INSTRUCTION("62B1E54372CAAB" , k(k3).vprolq(zmm19, zmm18, 171)); + TEST_INSTRUCTION("62B1E5C372CAAB" , k(k3).z().vprolq(zmm19, zmm18, 171)); + TEST_INSTRUCTION("62B1E54072CA7B" , vprolq(zmm19, zmm18, 123)); + TEST_INSTRUCTION("62F1E54072097B" , vprolq(zmm19, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1E540728CF0230100007B" , vprolq(zmm19, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1E55072097B" , vprolq(zmm19, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1E540724A7F7B" , vprolq(zmm19, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1E540728A002000007B" , vprolq(zmm19, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1E540724A807B" , vprolq(zmm19, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1E540728AC0DFFFFF7B" , vprolq(zmm19, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1E550724A7F7B" , vprolq(zmm19, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1E550728A000400007B" , vprolq(zmm19, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1E550724A807B" , vprolq(zmm19, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1E550728AF8FBFFFF7B" , vprolq(zmm19, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62125D4014DC" , vprorvd(zmm11, zmm20, zmm28)); + TEST_INSTRUCTION("62125D4214DC" , k(k2).vprorvd(zmm11, zmm20, zmm28)); + TEST_INSTRUCTION("62125DC214DC" , k(k2).z().vprorvd(zmm11, zmm20, zmm28)); + TEST_INSTRUCTION("62725D401419" , vprorvd(zmm11, zmm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62325D40149CF023010000" , vprorvd(zmm11, zmm20, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62725D501419" , vprorvd(zmm11, zmm20, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62725D40145A7F" , vprorvd(zmm11, zmm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62725D40149A00200000" , vprorvd(zmm11, zmm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62725D40145A80" , vprorvd(zmm11, zmm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62725D40149AC0DFFFFF" , vprorvd(zmm11, zmm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62725D50145A7F" , vprorvd(zmm11, zmm20, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62725D50149A00020000" , vprorvd(zmm11, zmm20, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62725D50145A80" , vprorvd(zmm11, zmm20, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62725D50149AFCFDFFFF" , vprorvd(zmm11, zmm20, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D1354872C2AB" , vprord(zmm9, zmm10, 171)); + TEST_INSTRUCTION("62D1354F72C2AB" , k(k7).vprord(zmm9, zmm10, 171)); + TEST_INSTRUCTION("62D135CF72C2AB" , k(k7).z().vprord(zmm9, zmm10, 171)); + TEST_INSTRUCTION("62D1354872C27B" , vprord(zmm9, zmm10, 123)); + TEST_INSTRUCTION("62F1354872017B" , vprord(zmm9, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B135487284F0230100007B" , vprord(zmm9, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1355872017B" , vprord(zmm9, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1354872427F7B" , vprord(zmm9, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F135487282002000007B" , vprord(zmm9, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F135487242807B" , vprord(zmm9, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F135487282C0DFFFFF7B" , vprord(zmm9, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1355872427F7B" , vprord(zmm9, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F135587282000200007B" , vprord(zmm9, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F135587242807B" , vprord(zmm9, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F135587282FCFDFFFF7B" , vprord(zmm9, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6272BD4014F1" , vprorvq(zmm14, zmm24, zmm1)); + TEST_INSTRUCTION("6272BD4714F1" , k(k7).vprorvq(zmm14, zmm24, zmm1)); + TEST_INSTRUCTION("6272BDC714F1" , k(k7).z().vprorvq(zmm14, zmm24, zmm1)); + TEST_INSTRUCTION("6272BD401431" , vprorvq(zmm14, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232BD4014B4F023010000" , vprorvq(zmm14, zmm24, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6272BD501431" , vprorvq(zmm14, zmm24, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272BD4014727F" , vprorvq(zmm14, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272BD4014B200200000" , vprorvq(zmm14, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272BD40147280" , vprorvq(zmm14, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272BD4014B2C0DFFFFF" , vprorvq(zmm14, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272BD5014727F" , vprorvq(zmm14, zmm24, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272BD5014B200040000" , vprorvq(zmm14, zmm24, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272BD50147280" , vprorvq(zmm14, zmm24, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272BD5014B2F8FBFFFF" , vprorvq(zmm14, zmm24, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6291D54072C1AB" , vprorq(zmm21, zmm25, 171)); + TEST_INSTRUCTION("6291D54672C1AB" , k(k6).vprorq(zmm21, zmm25, 171)); + TEST_INSTRUCTION("6291D5C672C1AB" , k(k6).z().vprorq(zmm21, zmm25, 171)); + TEST_INSTRUCTION("6291D54072C17B" , vprorq(zmm21, zmm25, 123)); + TEST_INSTRUCTION("62F1D54072017B" , vprorq(zmm21, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1D5407284F0230100007B" , vprorq(zmm21, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62F1D55072017B" , vprorq(zmm21, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1D54072427F7B" , vprorq(zmm21, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1D5407282002000007B" , vprorq(zmm21, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1D5407242807B" , vprorq(zmm21, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1D5407282C0DFFFFF7B" , vprorq(zmm21, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1D55072427F7B" , vprorq(zmm21, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1D5507282000400007B" , vprorq(zmm21, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1D5507242807B" , vprorq(zmm21, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1D5507282F8FBFFFF7B" , vprorq(zmm21, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD4809F7AB" , vrndscalepd(zmm22, zmm7, 171)); + TEST_INSTRUCTION("62E3FD4909F7AB" , k(k1).vrndscalepd(zmm22, zmm7, 171)); + TEST_INSTRUCTION("62E3FDC909F7AB" , k(k1).z().vrndscalepd(zmm22, zmm7, 171)); + TEST_INSTRUCTION("62E3FD1809F7AB" , sae().vrndscalepd(zmm22, zmm7, 171)); + TEST_INSTRUCTION("62E3FD4809F77B" , vrndscalepd(zmm22, zmm7, 123)); + TEST_INSTRUCTION("62E3FD1809F77B" , sae().vrndscalepd(zmm22, zmm7, 123)); + TEST_INSTRUCTION("62E3FD4809317B" , vrndscalepd(zmm22, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A3FD4809B4F0230100007B" , vrndscalepd(zmm22, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62E3FD5809317B" , vrndscalepd(zmm22, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD4809727F7B" , vrndscalepd(zmm22, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62E3FD4809B2002000007B" , vrndscalepd(zmm22, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62E3FD480972807B" , vrndscalepd(zmm22, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62E3FD4809B2C0DFFFFF7B" , vrndscalepd(zmm22, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62E3FD5809727F7B" , vrndscalepd(zmm22, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD5809B2000400007B" , vrndscalepd(zmm22, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD580972807B" , vrndscalepd(zmm22, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62E3FD5809B2F8FBFFFF7B" , vrndscalepd(zmm22, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62737D4808EFAB" , vrndscaleps(zmm13, zmm7, 171)); + TEST_INSTRUCTION("62737D4908EFAB" , k(k1).vrndscaleps(zmm13, zmm7, 171)); + TEST_INSTRUCTION("62737DC908EFAB" , k(k1).z().vrndscaleps(zmm13, zmm7, 171)); + TEST_INSTRUCTION("62737D1808EFAB" , sae().vrndscaleps(zmm13, zmm7, 171)); + TEST_INSTRUCTION("62737D4808EF7B" , vrndscaleps(zmm13, zmm7, 123)); + TEST_INSTRUCTION("62737D1808EF7B" , sae().vrndscaleps(zmm13, zmm7, 123)); + TEST_INSTRUCTION("62737D4808297B" , vrndscaleps(zmm13, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62337D4808ACF0230100007B" , vrndscaleps(zmm13, zmmword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62737D5808297B" , vrndscaleps(zmm13, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62737D48086A7F7B" , vrndscaleps(zmm13, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62737D4808AA002000007B" , vrndscaleps(zmm13, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62737D48086A807B" , vrndscaleps(zmm13, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62737D4808AAC0DFFFFF7B" , vrndscaleps(zmm13, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62737D58086A7F7B" , vrndscaleps(zmm13, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62737D5808AA000200007B" , vrndscaleps(zmm13, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62737D58086A807B" , vrndscaleps(zmm13, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62737D5808AAFCFDFFFF7B" , vrndscaleps(zmm13, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62439D080BCFAB" , vrndscalesd(xmm25, xmm12, xmm15, 171)); + TEST_INSTRUCTION("62439D0E0BCFAB" , k(k6).vrndscalesd(xmm25, xmm12, xmm15, 171)); + TEST_INSTRUCTION("62439D8E0BCFAB" , k(k6).z().vrndscalesd(xmm25, xmm12, xmm15, 171)); + TEST_INSTRUCTION("62439D180BCFAB" , sae().vrndscalesd(xmm25, xmm12, xmm15, 171)); + TEST_INSTRUCTION("62439D080BCF7B" , vrndscalesd(xmm25, xmm12, xmm15, 123)); + TEST_INSTRUCTION("62439D180BCF7B" , sae().vrndscalesd(xmm25, xmm12, xmm15, 123)); + TEST_INSTRUCTION("62639D080B097B" , vrndscalesd(xmm25, xmm12, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("62239D080B8CF0230100007B" , vrndscalesd(xmm25, xmm12, qword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("62639D080B4A7F7B" , vrndscalesd(xmm25, xmm12, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("62639D080B8A000400007B" , vrndscalesd(xmm25, xmm12, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("62639D080B4A807B" , vrndscalesd(xmm25, xmm12, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("62639D080B8AF8FBFFFF7B" , vrndscalesd(xmm25, xmm12, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("623325080AD9AB" , vrndscaless(xmm11, xmm11, xmm17, 171)); + TEST_INSTRUCTION("6233250B0AD9AB" , k(k3).vrndscaless(xmm11, xmm11, xmm17, 171)); + TEST_INSTRUCTION("6233258B0AD9AB" , k(k3).z().vrndscaless(xmm11, xmm11, xmm17, 171)); + TEST_INSTRUCTION("623325180AD9AB" , sae().vrndscaless(xmm11, xmm11, xmm17, 171)); + TEST_INSTRUCTION("623325080AD97B" , vrndscaless(xmm11, xmm11, xmm17, 123)); + TEST_INSTRUCTION("623325180AD97B" , sae().vrndscaless(xmm11, xmm11, xmm17, 123)); + TEST_INSTRUCTION("627325080A197B" , vrndscaless(xmm11, xmm11, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("623325080A9CF0230100007B" , vrndscaless(xmm11, xmm11, dword_ptr(rax, r14, 3, 291), 123)); + TEST_INSTRUCTION("627325080A5A7F7B" , vrndscaless(xmm11, xmm11, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("627325080A9A000200007B" , vrndscaless(xmm11, xmm11, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("627325080A5A807B" , vrndscaless(xmm11, xmm11, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("627325080A9AFCFDFFFF7B" , vrndscaless(xmm11, xmm11, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("6272FD488B19" , vpcompressq(zmmword_ptr(rcx), zmm11)); + TEST_INSTRUCTION("6272FD4F8B19" , k(k7).vpcompressq(zmmword_ptr(rcx), zmm11)); + TEST_INSTRUCTION("6232FD488B9CF023010000" , vpcompressq(zmmword_ptr(rax, r14, 3, 291), zmm11)); + TEST_INSTRUCTION("6272FD488B5A7F" , vpcompressq(zmmword_ptr(rdx, 1016), zmm11)); + TEST_INSTRUCTION("6272FD488B9A00040000" , vpcompressq(zmmword_ptr(rdx, 1024), zmm11)); + TEST_INSTRUCTION("6272FD488B5A80" , vpcompressq(zmmword_ptr(rdx, -1024), zmm11)); + TEST_INSTRUCTION("6272FD488B9AF8FBFFFF" , vpcompressq(zmmword_ptr(rdx, -1032), zmm11)); + TEST_INSTRUCTION("62A2FD488BD9" , vpcompressq(zmm17, zmm19)); + TEST_INSTRUCTION("62A2FD4A8BD9" , k(k2).vpcompressq(zmm17, zmm19)); + TEST_INSTRUCTION("62A2FDCA8BD9" , k(k2).z().vpcompressq(zmm17, zmm19)); + TEST_INSTRUCTION("C5D441D6" , kandw(k2, k5, k6)); + TEST_INSTRUCTION("C5CC42E7" , kandnw(k4, k6, k7)); + TEST_INSTRUCTION("C5CC45E7" , korw(k4, k6, k7)); + TEST_INSTRUCTION("C5D446DD" , kxnorw(k3, k5, k5)); + TEST_INSTRUCTION("C5CC47D7" , kxorw(k2, k6, k7)); + TEST_INSTRUCTION("C5F844DE" , knotw(k3, k6)); + TEST_INSTRUCTION("C5F898D6" , kortestw(k2, k6)); + TEST_INSTRUCTION("C4E3F930E4AB" , kshiftrw(k4, k4, 171)); + TEST_INSTRUCTION("C4E3F930E47B" , kshiftrw(k4, k4, 123)); + TEST_INSTRUCTION("C4E3F932D5AB" , kshiftlw(k2, k5, 171)); + TEST_INSTRUCTION("C4E3F932D57B" , kshiftlw(k2, k5, 123)); + TEST_INSTRUCTION("C5F890E5" , kmovw(k4, k5)); + TEST_INSTRUCTION("C5F89021" , kmovw(k4, word_ptr(rcx))); + TEST_INSTRUCTION("C4A17890A4F023010000" , kmovw(k4, word_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("C5F89121" , kmovw(word_ptr(rcx), k4)); + TEST_INSTRUCTION("C4A17891A4F023010000" , kmovw(word_ptr(rax, r14, 3, 291), k4)); + TEST_INSTRUCTION("C5F892D8" , kmovw(k3, eax)); + TEST_INSTRUCTION("C5F892DD" , kmovw(k3, ebp)); + TEST_INSTRUCTION("C4C17892DD" , kmovw(k3, r13d)); + TEST_INSTRUCTION("C5F893C2" , kmovw(eax, k2)); + TEST_INSTRUCTION("C5F893EA" , kmovw(ebp, k2)); + TEST_INSTRUCTION("C57893EA" , kmovw(r13d, k2)); + TEST_INSTRUCTION("C5D54BEE" , kunpckbw(k5, k5, k6)); + TEST_INSTRUCTION("62E37D481D19AB" , vcvtps2ph(ymmword_ptr(rcx), zmm19, 171)); + TEST_INSTRUCTION("62E37D4E1D19AB" , k(k6).vcvtps2ph(ymmword_ptr(rcx), zmm19, 171)); + TEST_INSTRUCTION("62E37D481D197B" , vcvtps2ph(ymmword_ptr(rcx), zmm19, 123)); + TEST_INSTRUCTION("62A37D481D9CF0230100007B" , vcvtps2ph(ymmword_ptr(rax, r14, 3, 291), zmm19, 123)); + TEST_INSTRUCTION("62E37D481D5A7F7B" , vcvtps2ph(ymmword_ptr(rdx, 4064), zmm19, 123)); + TEST_INSTRUCTION("62E37D481D9A001000007B" , vcvtps2ph(ymmword_ptr(rdx, 4096), zmm19, 123)); + TEST_INSTRUCTION("62E37D481D5A807B" , vcvtps2ph(ymmword_ptr(rdx, -4096), zmm19, 123)); + TEST_INSTRUCTION("62E37D481D9AE0EFFFFF7B" , vcvtps2ph(ymmword_ptr(rdx, -4128), zmm19, 123)); + TEST_INSTRUCTION("62E37D481921AB" , vextractf32x4(xmmword_ptr(rcx), zmm20, 171)); + TEST_INSTRUCTION("62E37D4F1921AB" , k(k7).vextractf32x4(xmmword_ptr(rcx), zmm20, 171)); + TEST_INSTRUCTION("62E37D4819217B" , vextractf32x4(xmmword_ptr(rcx), zmm20, 123)); + TEST_INSTRUCTION("62A37D4819A4F0230100007B" , vextractf32x4(xmmword_ptr(rax, r14, 3, 291), zmm20, 123)); + TEST_INSTRUCTION("62E37D4819627F7B" , vextractf32x4(xmmword_ptr(rdx, 2032), zmm20, 123)); + TEST_INSTRUCTION("62E37D4819A2000800007B" , vextractf32x4(xmmword_ptr(rdx, 2048), zmm20, 123)); + TEST_INSTRUCTION("62E37D481962807B" , vextractf32x4(xmmword_ptr(rdx, -2048), zmm20, 123)); + TEST_INSTRUCTION("62E37D4819A2F0F7FFFF7B" , vextractf32x4(xmmword_ptr(rdx, -2064), zmm20, 123)); + TEST_INSTRUCTION("62F3FD481B29AB" , vextractf64x4(ymmword_ptr(rcx), zmm5, 171)); + TEST_INSTRUCTION("62F3FD4C1B29AB" , k(k4).vextractf64x4(ymmword_ptr(rcx), zmm5, 171)); + TEST_INSTRUCTION("62F3FD481B297B" , vextractf64x4(ymmword_ptr(rcx), zmm5, 123)); + TEST_INSTRUCTION("62B3FD481BACF0230100007B" , vextractf64x4(ymmword_ptr(rax, r14, 3, 291), zmm5, 123)); + TEST_INSTRUCTION("62F3FD481B6A7F7B" , vextractf64x4(ymmword_ptr(rdx, 4064), zmm5, 123)); + TEST_INSTRUCTION("62F3FD481BAA001000007B" , vextractf64x4(ymmword_ptr(rdx, 4096), zmm5, 123)); + TEST_INSTRUCTION("62F3FD481B6A807B" , vextractf64x4(ymmword_ptr(rdx, -4096), zmm5, 123)); + TEST_INSTRUCTION("62F3FD481BAAE0EFFFFF7B" , vextractf64x4(ymmword_ptr(rdx, -4128), zmm5, 123)); + TEST_INSTRUCTION("62637D483929AB" , vextracti32x4(xmmword_ptr(rcx), zmm29, 171)); + TEST_INSTRUCTION("62637D4A3929AB" , k(k2).vextracti32x4(xmmword_ptr(rcx), zmm29, 171)); + TEST_INSTRUCTION("62637D4839297B" , vextracti32x4(xmmword_ptr(rcx), zmm29, 123)); + TEST_INSTRUCTION("62237D4839ACF0230100007B" , vextracti32x4(xmmword_ptr(rax, r14, 3, 291), zmm29, 123)); + TEST_INSTRUCTION("62637D48396A7F7B" , vextracti32x4(xmmword_ptr(rdx, 2032), zmm29, 123)); + TEST_INSTRUCTION("62637D4839AA000800007B" , vextracti32x4(xmmword_ptr(rdx, 2048), zmm29, 123)); + TEST_INSTRUCTION("62637D48396A807B" , vextracti32x4(xmmword_ptr(rdx, -2048), zmm29, 123)); + TEST_INSTRUCTION("62637D4839AAF0F7FFFF7B" , vextracti32x4(xmmword_ptr(rdx, -2064), zmm29, 123)); + TEST_INSTRUCTION("6263FD483B31AB" , vextracti64x4(ymmword_ptr(rcx), zmm30, 171)); + TEST_INSTRUCTION("6263FD4C3B31AB" , k(k4).vextracti64x4(ymmword_ptr(rcx), zmm30, 171)); + TEST_INSTRUCTION("6263FD483B317B" , vextracti64x4(ymmword_ptr(rcx), zmm30, 123)); + TEST_INSTRUCTION("6223FD483BB4F0230100007B" , vextracti64x4(ymmword_ptr(rax, r14, 3, 291), zmm30, 123)); + TEST_INSTRUCTION("6263FD483B727F7B" , vextracti64x4(ymmword_ptr(rdx, 4064), zmm30, 123)); + TEST_INSTRUCTION("6263FD483BB2001000007B" , vextracti64x4(ymmword_ptr(rdx, 4096), zmm30, 123)); + TEST_INSTRUCTION("6263FD483B72807B" , vextracti64x4(ymmword_ptr(rdx, -4096), zmm30, 123)); + TEST_INSTRUCTION("6263FD483BB2E0EFFFFF7B" , vextracti64x4(ymmword_ptr(rdx, -4128), zmm30, 123)); + TEST_INSTRUCTION("62E1FD482911" , vmovapd(zmmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62E1FD4E2911" , k(k6).vmovapd(zmmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62A1FD482994F023010000" , vmovapd(zmmword_ptr(rax, r14, 3, 291), zmm18)); + TEST_INSTRUCTION("62E1FD4829527F" , vmovapd(zmmword_ptr(rdx, 8128), zmm18)); + TEST_INSTRUCTION("62E1FD48299200200000" , vmovapd(zmmword_ptr(rdx, 8192), zmm18)); + TEST_INSTRUCTION("62E1FD48295280" , vmovapd(zmmword_ptr(rdx, -8192), zmm18)); + TEST_INSTRUCTION("62E1FD482992C0DFFFFF" , vmovapd(zmmword_ptr(rdx, -8256), zmm18)); + TEST_INSTRUCTION("62717C482909" , vmovaps(zmmword_ptr(rcx), zmm9)); + TEST_INSTRUCTION("62717C4B2909" , k(k3).vmovaps(zmmword_ptr(rcx), zmm9)); + TEST_INSTRUCTION("62317C48298CF023010000" , vmovaps(zmmword_ptr(rax, r14, 3, 291), zmm9)); + TEST_INSTRUCTION("62717C48294A7F" , vmovaps(zmmword_ptr(rdx, 8128), zmm9)); + TEST_INSTRUCTION("62717C48298A00200000" , vmovaps(zmmword_ptr(rdx, 8192), zmm9)); + TEST_INSTRUCTION("62717C48294A80" , vmovaps(zmmword_ptr(rdx, -8192), zmm9)); + TEST_INSTRUCTION("62717C48298AC0DFFFFF" , vmovaps(zmmword_ptr(rdx, -8256), zmm9)); + TEST_INSTRUCTION("62E17D487F11" , vmovdqa32(zmmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62E17D4C7F11" , k(k4).vmovdqa32(zmmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62A17D487F94F023010000" , vmovdqa32(zmmword_ptr(rax, r14, 3, 291), zmm18)); + TEST_INSTRUCTION("62E17D487F527F" , vmovdqa32(zmmword_ptr(rdx, 8128), zmm18)); + TEST_INSTRUCTION("62E17D487F9200200000" , vmovdqa32(zmmword_ptr(rdx, 8192), zmm18)); + TEST_INSTRUCTION("62E17D487F5280" , vmovdqa32(zmmword_ptr(rdx, -8192), zmm18)); + TEST_INSTRUCTION("62E17D487F92C0DFFFFF" , vmovdqa32(zmmword_ptr(rdx, -8256), zmm18)); + TEST_INSTRUCTION("62E1FD487F19" , vmovdqa64(zmmword_ptr(rcx), zmm19)); + TEST_INSTRUCTION("62E1FD4D7F19" , k(k5).vmovdqa64(zmmword_ptr(rcx), zmm19)); + TEST_INSTRUCTION("62A1FD487F9CF023010000" , vmovdqa64(zmmword_ptr(rax, r14, 3, 291), zmm19)); + TEST_INSTRUCTION("62E1FD487F5A7F" , vmovdqa64(zmmword_ptr(rdx, 8128), zmm19)); + TEST_INSTRUCTION("62E1FD487F9A00200000" , vmovdqa64(zmmword_ptr(rdx, 8192), zmm19)); + TEST_INSTRUCTION("62E1FD487F5A80" , vmovdqa64(zmmword_ptr(rdx, -8192), zmm19)); + TEST_INSTRUCTION("62E1FD487F9AC0DFFFFF" , vmovdqa64(zmmword_ptr(rdx, -8256), zmm19)); + TEST_INSTRUCTION("62E17E487F31" , vmovdqu32(zmmword_ptr(rcx), zmm22)); + TEST_INSTRUCTION("62E17E497F31" , k(k1).vmovdqu32(zmmword_ptr(rcx), zmm22)); + TEST_INSTRUCTION("62A17E487FB4F023010000" , vmovdqu32(zmmword_ptr(rax, r14, 3, 291), zmm22)); + TEST_INSTRUCTION("62E17E487F727F" , vmovdqu32(zmmword_ptr(rdx, 8128), zmm22)); + TEST_INSTRUCTION("62E17E487FB200200000" , vmovdqu32(zmmword_ptr(rdx, 8192), zmm22)); + TEST_INSTRUCTION("62E17E487F7280" , vmovdqu32(zmmword_ptr(rdx, -8192), zmm22)); + TEST_INSTRUCTION("62E17E487FB2C0DFFFFF" , vmovdqu32(zmmword_ptr(rdx, -8256), zmm22)); + TEST_INSTRUCTION("6261FE487F01" , vmovdqu64(zmmword_ptr(rcx), zmm24)); + TEST_INSTRUCTION("6261FE4D7F01" , k(k5).vmovdqu64(zmmword_ptr(rcx), zmm24)); + TEST_INSTRUCTION("6221FE487F84F023010000" , vmovdqu64(zmmword_ptr(rax, r14, 3, 291), zmm24)); + TEST_INSTRUCTION("6261FE487F427F" , vmovdqu64(zmmword_ptr(rdx, 8128), zmm24)); + TEST_INSTRUCTION("6261FE487F8200200000" , vmovdqu64(zmmword_ptr(rdx, 8192), zmm24)); + TEST_INSTRUCTION("6261FE487F4280" , vmovdqu64(zmmword_ptr(rdx, -8192), zmm24)); + TEST_INSTRUCTION("6261FE487F82C0DFFFFF" , vmovdqu64(zmmword_ptr(rdx, -8256), zmm24)); + TEST_INSTRUCTION("6271FD481111" , vmovupd(zmmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("6271FD4F1111" , k(k7).vmovupd(zmmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("6231FD481194F023010000" , vmovupd(zmmword_ptr(rax, r14, 3, 291), zmm10)); + TEST_INSTRUCTION("6271FD4811527F" , vmovupd(zmmword_ptr(rdx, 8128), zmm10)); + TEST_INSTRUCTION("6271FD48119200200000" , vmovupd(zmmword_ptr(rdx, 8192), zmm10)); + TEST_INSTRUCTION("6271FD48115280" , vmovupd(zmmword_ptr(rdx, -8192), zmm10)); + TEST_INSTRUCTION("6271FD481192C0DFFFFF" , vmovupd(zmmword_ptr(rdx, -8256), zmm10)); + TEST_INSTRUCTION("62617C481101" , vmovups(zmmword_ptr(rcx), zmm24)); + TEST_INSTRUCTION("62617C4F1101" , k(k7).vmovups(zmmword_ptr(rcx), zmm24)); + TEST_INSTRUCTION("62217C481184F023010000" , vmovups(zmmword_ptr(rax, r14, 3, 291), zmm24)); + TEST_INSTRUCTION("62617C4811427F" , vmovups(zmmword_ptr(rdx, 8128), zmm24)); + TEST_INSTRUCTION("62617C48118200200000" , vmovups(zmmword_ptr(rdx, 8192), zmm24)); + TEST_INSTRUCTION("62617C48114280" , vmovups(zmmword_ptr(rdx, -8192), zmm24)); + TEST_INSTRUCTION("62617C481182C0DFFFFF" , vmovups(zmmword_ptr(rdx, -8256), zmm24)); + TEST_INSTRUCTION("62F27E483219" , vpmovqb(qword_ptr(rcx), zmm3)); + TEST_INSTRUCTION("62F27E4F3219" , k(k7).vpmovqb(qword_ptr(rcx), zmm3)); + TEST_INSTRUCTION("62B27E48329CF023010000" , vpmovqb(qword_ptr(rax, r14, 3, 291), zmm3)); + TEST_INSTRUCTION("62F27E48325A7F" , vpmovqb(qword_ptr(rdx, 1016), zmm3)); + TEST_INSTRUCTION("62F27E48329A00040000" , vpmovqb(qword_ptr(rdx, 1024), zmm3)); + TEST_INSTRUCTION("62F27E48325A80" , vpmovqb(qword_ptr(rdx, -1024), zmm3)); + TEST_INSTRUCTION("62F27E48329AF8FBFFFF" , vpmovqb(qword_ptr(rdx, -1032), zmm3)); + TEST_INSTRUCTION("62E27E482201" , vpmovsqb(qword_ptr(rcx), zmm16)); + TEST_INSTRUCTION("62E27E4A2201" , k(k2).vpmovsqb(qword_ptr(rcx), zmm16)); + TEST_INSTRUCTION("62A27E482284F023010000" , vpmovsqb(qword_ptr(rax, r14, 3, 291), zmm16)); + TEST_INSTRUCTION("62E27E4822427F" , vpmovsqb(qword_ptr(rdx, 1016), zmm16)); + TEST_INSTRUCTION("62E27E48228200040000" , vpmovsqb(qword_ptr(rdx, 1024), zmm16)); + TEST_INSTRUCTION("62E27E48224280" , vpmovsqb(qword_ptr(rdx, -1024), zmm16)); + TEST_INSTRUCTION("62E27E482282F8FBFFFF" , vpmovsqb(qword_ptr(rdx, -1032), zmm16)); + TEST_INSTRUCTION("62627E481221" , vpmovusqb(qword_ptr(rcx), zmm28)); + TEST_INSTRUCTION("62627E491221" , k(k1).vpmovusqb(qword_ptr(rcx), zmm28)); + TEST_INSTRUCTION("62227E4812A4F023010000" , vpmovusqb(qword_ptr(rax, r14, 3, 291), zmm28)); + TEST_INSTRUCTION("62627E4812627F" , vpmovusqb(qword_ptr(rdx, 1016), zmm28)); + TEST_INSTRUCTION("62627E4812A200040000" , vpmovusqb(qword_ptr(rdx, 1024), zmm28)); + TEST_INSTRUCTION("62627E48126280" , vpmovusqb(qword_ptr(rdx, -1024), zmm28)); + TEST_INSTRUCTION("62627E4812A2F8FBFFFF" , vpmovusqb(qword_ptr(rdx, -1032), zmm28)); + TEST_INSTRUCTION("62F27E483439" , vpmovqw(xmmword_ptr(rcx), zmm7)); + TEST_INSTRUCTION("62F27E4E3439" , k(k6).vpmovqw(xmmword_ptr(rcx), zmm7)); + TEST_INSTRUCTION("62B27E4834BCF023010000" , vpmovqw(xmmword_ptr(rax, r14, 3, 291), zmm7)); + TEST_INSTRUCTION("62F27E48347A7F" , vpmovqw(xmmword_ptr(rdx, 2032), zmm7)); + TEST_INSTRUCTION("62F27E4834BA00080000" , vpmovqw(xmmword_ptr(rdx, 2048), zmm7)); + TEST_INSTRUCTION("62F27E48347A80" , vpmovqw(xmmword_ptr(rdx, -2048), zmm7)); + TEST_INSTRUCTION("62F27E4834BAF0F7FFFF" , vpmovqw(xmmword_ptr(rdx, -2064), zmm7)); + TEST_INSTRUCTION("62F27E482409" , vpmovsqw(xmmword_ptr(rcx), zmm1)); + TEST_INSTRUCTION("62F27E4D2409" , k(k5).vpmovsqw(xmmword_ptr(rcx), zmm1)); + TEST_INSTRUCTION("62B27E48248CF023010000" , vpmovsqw(xmmword_ptr(rax, r14, 3, 291), zmm1)); + TEST_INSTRUCTION("62F27E48244A7F" , vpmovsqw(xmmword_ptr(rdx, 2032), zmm1)); + TEST_INSTRUCTION("62F27E48248A00080000" , vpmovsqw(xmmword_ptr(rdx, 2048), zmm1)); + TEST_INSTRUCTION("62F27E48244A80" , vpmovsqw(xmmword_ptr(rdx, -2048), zmm1)); + TEST_INSTRUCTION("62F27E48248AF0F7FFFF" , vpmovsqw(xmmword_ptr(rdx, -2064), zmm1)); + TEST_INSTRUCTION("62627E481409" , vpmovusqw(xmmword_ptr(rcx), zmm25)); + TEST_INSTRUCTION("62627E4B1409" , k(k3).vpmovusqw(xmmword_ptr(rcx), zmm25)); + TEST_INSTRUCTION("62227E48148CF023010000" , vpmovusqw(xmmword_ptr(rax, r14, 3, 291), zmm25)); + TEST_INSTRUCTION("62627E48144A7F" , vpmovusqw(xmmword_ptr(rdx, 2032), zmm25)); + TEST_INSTRUCTION("62627E48148A00080000" , vpmovusqw(xmmword_ptr(rdx, 2048), zmm25)); + TEST_INSTRUCTION("62627E48144A80" , vpmovusqw(xmmword_ptr(rdx, -2048), zmm25)); + TEST_INSTRUCTION("62627E48148AF0F7FFFF" , vpmovusqw(xmmword_ptr(rdx, -2064), zmm25)); + TEST_INSTRUCTION("62627E483521" , vpmovqd(ymmword_ptr(rcx), zmm28)); + TEST_INSTRUCTION("62627E4D3521" , k(k5).vpmovqd(ymmword_ptr(rcx), zmm28)); + TEST_INSTRUCTION("62227E4835A4F023010000" , vpmovqd(ymmword_ptr(rax, r14, 3, 291), zmm28)); + TEST_INSTRUCTION("62627E4835627F" , vpmovqd(ymmword_ptr(rdx, 4064), zmm28)); + TEST_INSTRUCTION("62627E4835A200100000" , vpmovqd(ymmword_ptr(rdx, 4096), zmm28)); + TEST_INSTRUCTION("62627E48356280" , vpmovqd(ymmword_ptr(rdx, -4096), zmm28)); + TEST_INSTRUCTION("62627E4835A2E0EFFFFF" , vpmovqd(ymmword_ptr(rdx, -4128), zmm28)); + TEST_INSTRUCTION("62727E482509" , vpmovsqd(ymmword_ptr(rcx), zmm9)); + TEST_INSTRUCTION("62727E4F2509" , k(k7).vpmovsqd(ymmword_ptr(rcx), zmm9)); + TEST_INSTRUCTION("62327E48258CF023010000" , vpmovsqd(ymmword_ptr(rax, r14, 3, 291), zmm9)); + TEST_INSTRUCTION("62727E48254A7F" , vpmovsqd(ymmword_ptr(rdx, 4064), zmm9)); + TEST_INSTRUCTION("62727E48258A00100000" , vpmovsqd(ymmword_ptr(rdx, 4096), zmm9)); + TEST_INSTRUCTION("62727E48254A80" , vpmovsqd(ymmword_ptr(rdx, -4096), zmm9)); + TEST_INSTRUCTION("62727E48258AE0EFFFFF" , vpmovsqd(ymmword_ptr(rdx, -4128), zmm9)); + TEST_INSTRUCTION("62E27E481531" , vpmovusqd(ymmword_ptr(rcx), zmm22)); + TEST_INSTRUCTION("62E27E491531" , k(k1).vpmovusqd(ymmword_ptr(rcx), zmm22)); + TEST_INSTRUCTION("62A27E4815B4F023010000" , vpmovusqd(ymmword_ptr(rax, r14, 3, 291), zmm22)); + TEST_INSTRUCTION("62E27E4815727F" , vpmovusqd(ymmword_ptr(rdx, 4064), zmm22)); + TEST_INSTRUCTION("62E27E4815B200100000" , vpmovusqd(ymmword_ptr(rdx, 4096), zmm22)); + TEST_INSTRUCTION("62E27E48157280" , vpmovusqd(ymmword_ptr(rdx, -4096), zmm22)); + TEST_INSTRUCTION("62E27E4815B2E0EFFFFF" , vpmovusqd(ymmword_ptr(rdx, -4128), zmm22)); + TEST_INSTRUCTION("62727E483121" , vpmovdb(xmmword_ptr(rcx), zmm12)); + TEST_INSTRUCTION("62727E4B3121" , k(k3).vpmovdb(xmmword_ptr(rcx), zmm12)); + TEST_INSTRUCTION("62327E4831A4F023010000" , vpmovdb(xmmword_ptr(rax, r14, 3, 291), zmm12)); + TEST_INSTRUCTION("62727E4831627F" , vpmovdb(xmmword_ptr(rdx, 2032), zmm12)); + TEST_INSTRUCTION("62727E4831A200080000" , vpmovdb(xmmword_ptr(rdx, 2048), zmm12)); + TEST_INSTRUCTION("62727E48316280" , vpmovdb(xmmword_ptr(rdx, -2048), zmm12)); + TEST_INSTRUCTION("62727E4831A2F0F7FFFF" , vpmovdb(xmmword_ptr(rdx, -2064), zmm12)); + TEST_INSTRUCTION("62F27E482131" , vpmovsdb(xmmword_ptr(rcx), zmm6)); + TEST_INSTRUCTION("62F27E492131" , k(k1).vpmovsdb(xmmword_ptr(rcx), zmm6)); + TEST_INSTRUCTION("62B27E4821B4F023010000" , vpmovsdb(xmmword_ptr(rax, r14, 3, 291), zmm6)); + TEST_INSTRUCTION("62F27E4821727F" , vpmovsdb(xmmword_ptr(rdx, 2032), zmm6)); + TEST_INSTRUCTION("62F27E4821B200080000" , vpmovsdb(xmmword_ptr(rdx, 2048), zmm6)); + TEST_INSTRUCTION("62F27E48217280" , vpmovsdb(xmmword_ptr(rdx, -2048), zmm6)); + TEST_INSTRUCTION("62F27E4821B2F0F7FFFF" , vpmovsdb(xmmword_ptr(rdx, -2064), zmm6)); + TEST_INSTRUCTION("62E27E481139" , vpmovusdb(xmmword_ptr(rcx), zmm23)); + TEST_INSTRUCTION("62E27E4B1139" , k(k3).vpmovusdb(xmmword_ptr(rcx), zmm23)); + TEST_INSTRUCTION("62A27E4811BCF023010000" , vpmovusdb(xmmword_ptr(rax, r14, 3, 291), zmm23)); + TEST_INSTRUCTION("62E27E48117A7F" , vpmovusdb(xmmword_ptr(rdx, 2032), zmm23)); + TEST_INSTRUCTION("62E27E4811BA00080000" , vpmovusdb(xmmword_ptr(rdx, 2048), zmm23)); + TEST_INSTRUCTION("62E27E48117A80" , vpmovusdb(xmmword_ptr(rdx, -2048), zmm23)); + TEST_INSTRUCTION("62E27E4811BAF0F7FFFF" , vpmovusdb(xmmword_ptr(rdx, -2064), zmm23)); + TEST_INSTRUCTION("62F27E483339" , vpmovdw(ymmword_ptr(rcx), zmm7)); + TEST_INSTRUCTION("62F27E4F3339" , k(k7).vpmovdw(ymmword_ptr(rcx), zmm7)); + TEST_INSTRUCTION("62B27E4833BCF023010000" , vpmovdw(ymmword_ptr(rax, r14, 3, 291), zmm7)); + TEST_INSTRUCTION("62F27E48337A7F" , vpmovdw(ymmword_ptr(rdx, 4064), zmm7)); + TEST_INSTRUCTION("62F27E4833BA00100000" , vpmovdw(ymmword_ptr(rdx, 4096), zmm7)); + TEST_INSTRUCTION("62F27E48337A80" , vpmovdw(ymmword_ptr(rdx, -4096), zmm7)); + TEST_INSTRUCTION("62F27E4833BAE0EFFFFF" , vpmovdw(ymmword_ptr(rdx, -4128), zmm7)); + TEST_INSTRUCTION("62727E482331" , vpmovsdw(ymmword_ptr(rcx), zmm14)); + TEST_INSTRUCTION("62727E4E2331" , k(k6).vpmovsdw(ymmword_ptr(rcx), zmm14)); + TEST_INSTRUCTION("62327E4823B4F023010000" , vpmovsdw(ymmword_ptr(rax, r14, 3, 291), zmm14)); + TEST_INSTRUCTION("62727E4823727F" , vpmovsdw(ymmword_ptr(rdx, 4064), zmm14)); + TEST_INSTRUCTION("62727E4823B200100000" , vpmovsdw(ymmword_ptr(rdx, 4096), zmm14)); + TEST_INSTRUCTION("62727E48237280" , vpmovsdw(ymmword_ptr(rdx, -4096), zmm14)); + TEST_INSTRUCTION("62727E4823B2E0EFFFFF" , vpmovsdw(ymmword_ptr(rdx, -4128), zmm14)); + TEST_INSTRUCTION("62F27E481329" , vpmovusdw(ymmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62F27E4B1329" , k(k3).vpmovusdw(ymmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62B27E4813ACF023010000" , vpmovusdw(ymmword_ptr(rax, r14, 3, 291), zmm5)); + TEST_INSTRUCTION("62F27E48136A7F" , vpmovusdw(ymmword_ptr(rdx, 4064), zmm5)); + TEST_INSTRUCTION("62F27E4813AA00100000" , vpmovusdw(ymmword_ptr(rdx, 4096), zmm5)); + TEST_INSTRUCTION("62F27E48136A80" , vpmovusdw(ymmword_ptr(rdx, -4096), zmm5)); + TEST_INSTRUCTION("62F27E4813AAE0EFFFFF" , vpmovusdw(ymmword_ptr(rdx, -4128), zmm5)); + TEST_INSTRUCTION("62A1FC4878C4" , vcvttpd2udq(ymm16, zmm20)); + TEST_INSTRUCTION("62A1FC4F78C4" , k(k7).vcvttpd2udq(ymm16, zmm20)); + TEST_INSTRUCTION("62A1FCCF78C4" , k(k7).z().vcvttpd2udq(ymm16, zmm20)); + TEST_INSTRUCTION("62A1FC1878C4" , sae().vcvttpd2udq(ymm16, zmm20)); + TEST_INSTRUCTION("62E1FC487801" , vcvttpd2udq(ymm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FC487884F023010000" , vcvttpd2udq(ymm16, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E1FC587801" , vcvttpd2udq(ymm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1FC4878427F" , vcvttpd2udq(ymm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FC48788200200000" , vcvttpd2udq(ymm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FC48784280" , vcvttpd2udq(ymm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FC487882C0DFFFFF" , vcvttpd2udq(ymm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FC5878427F" , vcvttpd2udq(ymm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1FC58788200040000" , vcvttpd2udq(ymm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1FC58784280" , vcvttpd2udq(ymm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1FC587882F8FBFFFF" , vcvttpd2udq(ymm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62117C4878F4" , vcvttps2udq(zmm14, zmm28)); + TEST_INSTRUCTION("62117C4978F4" , k(k1).vcvttps2udq(zmm14, zmm28)); + TEST_INSTRUCTION("62117CC978F4" , k(k1).z().vcvttps2udq(zmm14, zmm28)); + TEST_INSTRUCTION("62117C1878F4" , sae().vcvttps2udq(zmm14, zmm28)); + TEST_INSTRUCTION("62717C487831" , vcvttps2udq(zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62317C4878B4F023010000" , vcvttps2udq(zmm14, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717C587831" , vcvttps2udq(zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62717C4878727F" , vcvttps2udq(zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62717C4878B200200000" , vcvttps2udq(zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62717C48787280" , vcvttps2udq(zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62717C4878B2C0DFFFFF" , vcvttps2udq(zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62717C5878727F" , vcvttps2udq(zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62717C5878B200020000" , vcvttps2udq(zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62717C58787280" , vcvttps2udq(zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62717C5878B2FCFDFFFF" , vcvttps2udq(zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B17F0878C5" , vcvttsd2usi(eax, xmm21)); + TEST_INSTRUCTION("62B17F1878C5" , sae().vcvttsd2usi(eax, xmm21)); + TEST_INSTRUCTION("62F17F087801" , vcvttsd2usi(eax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F087884F023010000" , vcvttsd2usi(eax, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17F0878427F" , vcvttsd2usi(eax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F08788200040000" , vcvttsd2usi(eax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08784280" , vcvttsd2usi(eax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F087882F8FBFFFF" , vcvttsd2usi(eax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B17F0878ED" , vcvttsd2usi(ebp, xmm21)); + TEST_INSTRUCTION("62B17F1878ED" , sae().vcvttsd2usi(ebp, xmm21)); + TEST_INSTRUCTION("62F17F087829" , vcvttsd2usi(ebp, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F0878ACF023010000" , vcvttsd2usi(ebp, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17F08786A7F" , vcvttsd2usi(ebp, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F0878AA00040000" , vcvttsd2usi(ebp, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08786A80" , vcvttsd2usi(ebp, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F0878AAF8FBFFFF" , vcvttsd2usi(ebp, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62317F0878ED" , vcvttsd2usi(r13d, xmm21)); + TEST_INSTRUCTION("62317F1878ED" , sae().vcvttsd2usi(r13d, xmm21)); + TEST_INSTRUCTION("62717F087829" , vcvttsd2usi(r13d, qword_ptr(rcx))); + TEST_INSTRUCTION("62317F0878ACF023010000" , vcvttsd2usi(r13d, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717F08786A7F" , vcvttsd2usi(r13d, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62717F0878AA00040000" , vcvttsd2usi(r13d, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62717F08786A80" , vcvttsd2usi(r13d, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62717F0878AAF8FBFFFF" , vcvttsd2usi(r13d, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62F1FF0878C7" , vcvttsd2usi(rax, xmm7)); + TEST_INSTRUCTION("62F1FF1878C7" , sae().vcvttsd2usi(rax, xmm7)); + TEST_INSTRUCTION("62F1FF087801" , vcvttsd2usi(rax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF087884F023010000" , vcvttsd2usi(rax, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FF0878427F" , vcvttsd2usi(rax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1FF08788200040000" , vcvttsd2usi(rax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1FF08784280" , vcvttsd2usi(rax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1FF087882F8FBFFFF" , vcvttsd2usi(rax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6271FF0878C7" , vcvttsd2usi(r8, xmm7)); + TEST_INSTRUCTION("6271FF1878C7" , sae().vcvttsd2usi(r8, xmm7)); + TEST_INSTRUCTION("6271FF087801" , vcvttsd2usi(r8, qword_ptr(rcx))); + TEST_INSTRUCTION("6231FF087884F023010000" , vcvttsd2usi(r8, qword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271FF0878427F" , vcvttsd2usi(r8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271FF08788200040000" , vcvttsd2usi(r8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271FF08784280" , vcvttsd2usi(r8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271FF087882F8FBFFFF" , vcvttsd2usi(r8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B17E0878C2" , vcvttss2usi(eax, xmm18)); + TEST_INSTRUCTION("62B17E1878C2" , sae().vcvttss2usi(eax, xmm18)); + TEST_INSTRUCTION("62F17E087801" , vcvttss2usi(eax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E087884F023010000" , vcvttss2usi(eax, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17E0878427F" , vcvttss2usi(eax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E08788200020000" , vcvttss2usi(eax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08784280" , vcvttss2usi(eax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E087882FCFDFFFF" , vcvttss2usi(eax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B17E0878EA" , vcvttss2usi(ebp, xmm18)); + TEST_INSTRUCTION("62B17E1878EA" , sae().vcvttss2usi(ebp, xmm18)); + TEST_INSTRUCTION("62F17E087829" , vcvttss2usi(ebp, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E0878ACF023010000" , vcvttss2usi(ebp, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F17E08786A7F" , vcvttss2usi(ebp, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E0878AA00020000" , vcvttss2usi(ebp, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08786A80" , vcvttss2usi(ebp, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E0878AAFCFDFFFF" , vcvttss2usi(ebp, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62317E0878EA" , vcvttss2usi(r13d, xmm18)); + TEST_INSTRUCTION("62317E1878EA" , sae().vcvttss2usi(r13d, xmm18)); + TEST_INSTRUCTION("62717E087829" , vcvttss2usi(r13d, dword_ptr(rcx))); + TEST_INSTRUCTION("62317E0878ACF023010000" , vcvttss2usi(r13d, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62717E08786A7F" , vcvttss2usi(r13d, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62717E0878AA00020000" , vcvttss2usi(r13d, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62717E08786A80" , vcvttss2usi(r13d, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62717E0878AAFCFDFFFF" , vcvttss2usi(r13d, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6291FE0878C3" , vcvttss2usi(rax, xmm27)); + TEST_INSTRUCTION("6291FE1878C3" , sae().vcvttss2usi(rax, xmm27)); + TEST_INSTRUCTION("62F1FE087801" , vcvttss2usi(rax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B1FE087884F023010000" , vcvttss2usi(rax, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62F1FE0878427F" , vcvttss2usi(rax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F1FE08788200020000" , vcvttss2usi(rax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F1FE08784280" , vcvttss2usi(rax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F1FE087882FCFDFFFF" , vcvttss2usi(rax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6211FE0878C3" , vcvttss2usi(r8, xmm27)); + TEST_INSTRUCTION("6211FE1878C3" , sae().vcvttss2usi(r8, xmm27)); + TEST_INSTRUCTION("6271FE087801" , vcvttss2usi(r8, dword_ptr(rcx))); + TEST_INSTRUCTION("6231FE087884F023010000" , vcvttss2usi(r8, dword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("6271FE0878427F" , vcvttss2usi(r8, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("6271FE08788200020000" , vcvttss2usi(r8, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("6271FE08784280" , vcvttss2usi(r8, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("6271FE087882FCFDFFFF" , vcvttss2usi(r8, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62721D4076D4" , vpermi2d(zmm10, zmm28, zmm4)); + TEST_INSTRUCTION("62721D4576D4" , k(k5).vpermi2d(zmm10, zmm28, zmm4)); + TEST_INSTRUCTION("62721DC576D4" , k(k5).z().vpermi2d(zmm10, zmm28, zmm4)); + TEST_INSTRUCTION("62721D407611" , vpermi2d(zmm10, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62321D407694F023010000" , vpermi2d(zmm10, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62721D507611" , vpermi2d(zmm10, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62721D4076527F" , vpermi2d(zmm10, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62721D40769200200000" , vpermi2d(zmm10, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62721D40765280" , vpermi2d(zmm10, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62721D407692C0DFFFFF" , vpermi2d(zmm10, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62721D5076527F" , vpermi2d(zmm10, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62721D50769200020000" , vpermi2d(zmm10, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62721D50765280" , vpermi2d(zmm10, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62721D507692FCFDFFFF" , vpermi2d(zmm10, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62829D4076D4" , vpermi2q(zmm18, zmm28, zmm28)); + TEST_INSTRUCTION("62829D4276D4" , k(k2).vpermi2q(zmm18, zmm28, zmm28)); + TEST_INSTRUCTION("62829DC276D4" , k(k2).z().vpermi2q(zmm18, zmm28, zmm28)); + TEST_INSTRUCTION("62E29D407611" , vpermi2q(zmm18, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A29D407694F023010000" , vpermi2q(zmm18, zmm28, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E29D507611" , vpermi2q(zmm18, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E29D4076527F" , vpermi2q(zmm18, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E29D40769200200000" , vpermi2q(zmm18, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E29D40765280" , vpermi2q(zmm18, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E29D407692C0DFFFFF" , vpermi2q(zmm18, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E29D5076527F" , vpermi2q(zmm18, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E29D50769200040000" , vpermi2q(zmm18, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E29D50765280" , vpermi2q(zmm18, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E29D507692F8FBFFFF" , vpermi2q(zmm18, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6242454077C0" , vpermi2ps(zmm24, zmm23, zmm8)); + TEST_INSTRUCTION("6242454277C0" , k(k2).vpermi2ps(zmm24, zmm23, zmm8)); + TEST_INSTRUCTION("624245C277C0" , k(k2).z().vpermi2ps(zmm24, zmm23, zmm8)); + TEST_INSTRUCTION("626245407701" , vpermi2ps(zmm24, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622245407784F023010000" , vpermi2ps(zmm24, zmm23, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("626245507701" , vpermi2ps(zmm24, zmm23, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("6262454077427F" , vpermi2ps(zmm24, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62624540778200200000" , vpermi2ps(zmm24, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62624540774280" , vpermi2ps(zmm24, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626245407782C0DFFFFF" , vpermi2ps(zmm24, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262455077427F" , vpermi2ps(zmm24, zmm23, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62624550778200020000" , vpermi2ps(zmm24, zmm23, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62624550774280" , vpermi2ps(zmm24, zmm23, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("626245507782FCFDFFFF" , vpermi2ps(zmm24, zmm23, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A2D54877E4" , vpermi2pd(zmm20, zmm5, zmm20)); + TEST_INSTRUCTION("62A2D54B77E4" , k(k3).vpermi2pd(zmm20, zmm5, zmm20)); + TEST_INSTRUCTION("62A2D5CB77E4" , k(k3).z().vpermi2pd(zmm20, zmm5, zmm20)); + TEST_INSTRUCTION("62E2D5487721" , vpermi2pd(zmm20, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2D54877A4F023010000" , vpermi2pd(zmm20, zmm5, zmmword_ptr(rax, r14, 3, 291))); + TEST_INSTRUCTION("62E2D5587721" , vpermi2pd(zmm20, zmm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2D54877627F" , vpermi2pd(zmm20, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2D54877A200200000" , vpermi2pd(zmm20, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2D548776280" , vpermi2pd(zmm20, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2D54877A2C0DFFFFF" , vpermi2pd(zmm20, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2D55877627F" , vpermi2pd(zmm20, zmm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2D55877A200040000" , vpermi2pd(zmm20, zmm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2D558776280" , vpermi2pd(zmm20, zmm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2D55877A2F8FBFFFF" , vpermi2pd(zmm20, zmm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E1A54858CA" , vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A54958CA" , k(k1).vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A5C958CA" , k(k1).z().vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A51858CA" , rn_sae().vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A55858CA" , ru_sae().vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A53858CA" , rd_sae().vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A57858CA" , rz_sae().vaddpd(zmm17, zmm11, zmm2)); + TEST_INSTRUCTION("62E1A5485809" , vaddpd(zmm17, zmm11, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1A548588CF034120000" , vaddpd(zmm17, zmm11, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1A5585809" , vaddpd(zmm17, zmm11, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1A548584A7F" , vaddpd(zmm17, zmm11, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1A548588A00200000" , vaddpd(zmm17, zmm11, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1A548584A80" , vaddpd(zmm17, zmm11, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1A548588AC0DFFFFF" , vaddpd(zmm17, zmm11, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1A558584A7F" , vaddpd(zmm17, zmm11, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1A558588A00040000" , vaddpd(zmm17, zmm11, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1A558584A80" , vaddpd(zmm17, zmm11, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1A558588AF8FBFFFF" , vaddpd(zmm17, zmm11, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F14C4858DD" , vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14C4958DD" , k(k1).vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14CC958DD" , k(k1).z().vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14C1858DD" , rn_sae().vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14C5858DD" , ru_sae().vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14C3858DD" , rd_sae().vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14C7858DD" , rz_sae().vaddps(zmm3, zmm6, zmm5)); + TEST_INSTRUCTION("62F14C485819" , vaddps(zmm3, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B14C48589CF034120000" , vaddps(zmm3, zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F14C585819" , vaddps(zmm3, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F14C48585A7F" , vaddps(zmm3, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F14C48589A00200000" , vaddps(zmm3, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F14C48585A80" , vaddps(zmm3, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F14C48589AC0DFFFFF" , vaddps(zmm3, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F14C58585A7F" , vaddps(zmm3, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F14C58589A00020000" , vaddps(zmm3, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F14C58585A80" , vaddps(zmm3, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F14C58589AFCFDFFFF" , vaddps(zmm3, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6291EF0058CB" , vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("6291EF0358CB" , k(k3).vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("6291EF8358CB" , k(k3).z().vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("6291EF1058CB" , rn_sae().vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("6291EF5058CB" , ru_sae().vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("6291EF3058CB" , rd_sae().vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("6291EF7058CB" , rz_sae().vaddsd(xmm1, xmm18, xmm27)); + TEST_INSTRUCTION("62F1EF005809" , vaddsd(xmm1, xmm18, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1EF00588CF034120000" , vaddsd(xmm1, xmm18, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1EF00584A7F" , vaddsd(xmm1, xmm18, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1EF00588A00040000" , vaddsd(xmm1, xmm18, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1EF00584A80" , vaddsd(xmm1, xmm18, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1EF00588AF8FBFFFF" , vaddsd(xmm1, xmm18, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62C10E0858CF" , vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62C10E0C58CF" , k(k4).vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62C10E8C58CF" , k(k4).z().vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62C10E1858CF" , rn_sae().vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62C10E5858CF" , ru_sae().vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62C10E3858CF" , rd_sae().vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62C10E7858CF" , rz_sae().vaddss(xmm17, xmm14, xmm15)); + TEST_INSTRUCTION("62E10E085809" , vaddss(xmm17, xmm14, dword_ptr(rcx))); + TEST_INSTRUCTION("62A10E08588CF034120000" , vaddss(xmm17, xmm14, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E10E08584A7F" , vaddss(xmm17, xmm14, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E10E08588A00020000" , vaddss(xmm17, xmm14, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E10E08584A80" , vaddss(xmm17, xmm14, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E10E08588AFCFDFFFF" , vaddss(xmm17, xmm14, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6273454803FDAB" , valignd(zmm15, zmm7, zmm5, 171)); + TEST_INSTRUCTION("6273454A03FDAB" , k(k2).valignd(zmm15, zmm7, zmm5, 171)); + TEST_INSTRUCTION("627345CA03FDAB" , k(k2).z().valignd(zmm15, zmm7, zmm5, 171)); + TEST_INSTRUCTION("6273454803FD7B" , valignd(zmm15, zmm7, zmm5, 123)); + TEST_INSTRUCTION("6273454803397B" , valignd(zmm15, zmm7, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233454803BCF0341200007B" , valignd(zmm15, zmm7, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6273455803397B" , valignd(zmm15, zmm7, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62734548037A7F7B" , valignd(zmm15, zmm7, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273454803BA002000007B" , valignd(zmm15, zmm7, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62734548037A807B" , valignd(zmm15, zmm7, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273454803BAC0DFFFFF7B" , valignd(zmm15, zmm7, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62734558037A7F7B" , valignd(zmm15, zmm7, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("6273455803BA000200007B" , valignd(zmm15, zmm7, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62734558037A807B" , valignd(zmm15, zmm7, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("6273455803BAFCFDFFFF7B" , valignd(zmm15, zmm7, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62C2ED4865F8" , vblendmpd(zmm23, zmm2, zmm8)); + TEST_INSTRUCTION("62C2ED4F65F8" , k(k7).vblendmpd(zmm23, zmm2, zmm8)); + TEST_INSTRUCTION("62C2EDCF65F8" , k(k7).z().vblendmpd(zmm23, zmm2, zmm8)); + TEST_INSTRUCTION("62E2ED486539" , vblendmpd(zmm23, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2ED4865BCF034120000" , vblendmpd(zmm23, zmm2, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2ED586539" , vblendmpd(zmm23, zmm2, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2ED48657A7F" , vblendmpd(zmm23, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2ED4865BA00200000" , vblendmpd(zmm23, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2ED48657A80" , vblendmpd(zmm23, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2ED4865BAC0DFFFFF" , vblendmpd(zmm23, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2ED58657A7F" , vblendmpd(zmm23, zmm2, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2ED5865BA00040000" , vblendmpd(zmm23, zmm2, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2ED58657A80" , vblendmpd(zmm23, zmm2, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2ED5865BAF8FBFFFF" , vblendmpd(zmm23, zmm2, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E2354865FF" , vblendmps(zmm23, zmm9, zmm7)); + TEST_INSTRUCTION("62E2354F65FF" , k(k7).vblendmps(zmm23, zmm9, zmm7)); + TEST_INSTRUCTION("62E235CF65FF" , k(k7).z().vblendmps(zmm23, zmm9, zmm7)); + TEST_INSTRUCTION("62E235486539" , vblendmps(zmm23, zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2354865BCF034120000" , vblendmps(zmm23, zmm9, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E235586539" , vblendmps(zmm23, zmm9, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E23548657A7F" , vblendmps(zmm23, zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2354865BA00200000" , vblendmps(zmm23, zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E23548657A80" , vblendmps(zmm23, zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2354865BAC0DFFFFF" , vblendmps(zmm23, zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E23558657A7F" , vblendmps(zmm23, zmm9, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E2355865BA00020000" , vblendmps(zmm23, zmm9, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E23558657A80" , vblendmps(zmm23, zmm9, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E2355865BAFCFDFFFF" , vblendmps(zmm23, zmm9, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62727D481A39" , vbroadcastf32x4(zmm15, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62727D4B1A39" , k(k3).vbroadcastf32x4(zmm15, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62727DCB1A39" , k(k3).z().vbroadcastf32x4(zmm15, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D481ABCF034120000" , vbroadcastf32x4(zmm15, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D481A7A7F" , vbroadcastf32x4(zmm15, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62727D481ABA00080000" , vbroadcastf32x4(zmm15, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62727D481A7A80" , vbroadcastf32x4(zmm15, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62727D481ABAF0F7FFFF" , vbroadcastf32x4(zmm15, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6262FD481B11" , vbroadcastf64x4(zmm26, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6262FD491B11" , k(k1).vbroadcastf64x4(zmm26, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6262FDC91B11" , k(k1).z().vbroadcastf64x4(zmm26, ymmword_ptr(rcx))); + TEST_INSTRUCTION("6222FD481B94F034120000" , vbroadcastf64x4(zmm26, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262FD481B527F" , vbroadcastf64x4(zmm26, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("6262FD481B9200100000" , vbroadcastf64x4(zmm26, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("6262FD481B5280" , vbroadcastf64x4(zmm26, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("6262FD481B92E0EFFFFF" , vbroadcastf64x4(zmm26, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62F27D485A11" , vbroadcasti32x4(zmm2, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27D4D5A11" , k(k5).vbroadcasti32x4(zmm2, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62F27DCD5A11" , k(k5).z().vbroadcasti32x4(zmm2, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D485A94F034120000" , vbroadcasti32x4(zmm2, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D485A527F" , vbroadcasti32x4(zmm2, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62F27D485A9200080000" , vbroadcasti32x4(zmm2, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62F27D485A5280" , vbroadcasti32x4(zmm2, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62F27D485A92F0F7FFFF" , vbroadcasti32x4(zmm2, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62E2FD485B09" , vbroadcasti64x4(zmm17, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62E2FD4A5B09" , k(k2).vbroadcasti64x4(zmm17, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62E2FDCA5B09" , k(k2).z().vbroadcasti64x4(zmm17, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62A2FD485B8CF034120000" , vbroadcasti64x4(zmm17, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2FD485B4A7F" , vbroadcasti64x4(zmm17, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62E2FD485B8A00100000" , vbroadcasti64x4(zmm17, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62E2FD485B4A80" , vbroadcasti64x4(zmm17, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62E2FD485B8AE0EFFFFF" , vbroadcasti64x4(zmm17, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("6262FD481919" , vbroadcastsd(zmm27, qword_ptr(rcx))); + TEST_INSTRUCTION("6262FD4F1919" , k(k7).vbroadcastsd(zmm27, qword_ptr(rcx))); + TEST_INSTRUCTION("6262FDCF1919" , k(k7).z().vbroadcastsd(zmm27, qword_ptr(rcx))); + TEST_INSTRUCTION("6222FD48199CF034120000" , vbroadcastsd(zmm27, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262FD48195A7F" , vbroadcastsd(zmm27, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262FD48199A00040000" , vbroadcastsd(zmm27, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262FD48195A80" , vbroadcastsd(zmm27, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262FD48199AF8FBFFFF" , vbroadcastsd(zmm27, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6282FD4819D9" , vbroadcastsd(zmm19, xmm25)); + TEST_INSTRUCTION("6282FD4B19D9" , k(k3).vbroadcastsd(zmm19, xmm25)); + TEST_INSTRUCTION("6282FDCB19D9" , k(k3).z().vbroadcastsd(zmm19, xmm25)); + TEST_INSTRUCTION("62F27D481811" , vbroadcastss(zmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62F27D491811" , k(k1).vbroadcastss(zmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62F27DC91811" , k(k1).z().vbroadcastss(zmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62B27D481894F034120000" , vbroadcastss(zmm2, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D4818527F" , vbroadcastss(zmm2, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F27D48189200020000" , vbroadcastss(zmm2, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F27D48185280" , vbroadcastss(zmm2, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F27D481892FCFDFFFF" , vbroadcastss(zmm2, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C27D4818FF" , vbroadcastss(zmm23, xmm15)); + TEST_INSTRUCTION("62C27D4C18FF" , k(k4).vbroadcastss(zmm23, xmm15)); + TEST_INSTRUCTION("62C27DCC18FF" , k(k4).z().vbroadcastss(zmm23, xmm15)); + TEST_INSTRUCTION("62B18548C2E8AB" , vcmppd(k5, zmm15, zmm16, 171)); + TEST_INSTRUCTION("62B1854DC2E8AB" , k(k5).vcmppd(k5, zmm15, zmm16, 171)); + TEST_INSTRUCTION("62B18518C2E8AB" , sae().vcmppd(k5, zmm15, zmm16, 171)); + TEST_INSTRUCTION("62B18548C2E87B" , vcmppd(k5, zmm15, zmm16, 123)); + TEST_INSTRUCTION("62B18518C2E87B" , sae().vcmppd(k5, zmm15, zmm16, 123)); + TEST_INSTRUCTION("62F18548C2297B" , vcmppd(k5, zmm15, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B18548C2ACF0341200007B" , vcmppd(k5, zmm15, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F18558C2297B" , vcmppd(k5, zmm15, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F18548C26A7F7B" , vcmppd(k5, zmm15, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F18548C2AA002000007B" , vcmppd(k5, zmm15, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F18548C26A807B" , vcmppd(k5, zmm15, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F18548C2AAC0DFFFFF7B" , vcmppd(k5, zmm15, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F18558C26A7F7B" , vcmppd(k5, zmm15, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F18558C2AA000400007B" , vcmppd(k5, zmm15, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F18558C26A807B" , vcmppd(k5, zmm15, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F18558C2AAF8FBFFFF7B" , vcmppd(k5, zmm15, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62916448C2D5AB" , vcmpps(k2, zmm3, zmm29, 171)); + TEST_INSTRUCTION("6291644DC2D5AB" , k(k5).vcmpps(k2, zmm3, zmm29, 171)); + TEST_INSTRUCTION("62916418C2D5AB" , sae().vcmpps(k2, zmm3, zmm29, 171)); + TEST_INSTRUCTION("62916448C2D57B" , vcmpps(k2, zmm3, zmm29, 123)); + TEST_INSTRUCTION("62916418C2D57B" , sae().vcmpps(k2, zmm3, zmm29, 123)); + TEST_INSTRUCTION("62F16448C2117B" , vcmpps(k2, zmm3, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B16448C294F0341200007B" , vcmpps(k2, zmm3, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F16458C2117B" , vcmpps(k2, zmm3, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F16448C2527F7B" , vcmpps(k2, zmm3, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F16448C292002000007B" , vcmpps(k2, zmm3, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F16448C252807B" , vcmpps(k2, zmm3, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F16448C292C0DFFFFF7B" , vcmpps(k2, zmm3, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F16458C2527F7B" , vcmpps(k2, zmm3, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F16458C292000200007B" , vcmpps(k2, zmm3, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F16458C252807B" , vcmpps(k2, zmm3, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F16458C292FCFDFFFF7B" , vcmpps(k2, zmm3, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62F1D708C2E6AB" , vcmpsd(k4, xmm5, xmm6, 171)); + TEST_INSTRUCTION("62F1D70DC2E6AB" , k(k5).vcmpsd(k4, xmm5, xmm6, 171)); + TEST_INSTRUCTION("62F1D718C2E6AB" , sae().vcmpsd(k4, xmm5, xmm6, 171)); + TEST_INSTRUCTION("62F1D708C2E67B" , vcmpsd(k4, xmm5, xmm6, 123)); + TEST_INSTRUCTION("62F1D718C2E67B" , sae().vcmpsd(k4, xmm5, xmm6, 123)); + TEST_INSTRUCTION("62F1D708C2217B" , vcmpsd(k4, xmm5, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1D708C2A4F0341200007B" , vcmpsd(k4, xmm5, qword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1D708C2627F7B" , vcmpsd(k4, xmm5, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("62F1D708C2A2000400007B" , vcmpsd(k4, xmm5, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("62F1D708C262807B" , vcmpsd(k4, xmm5, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("62F1D708C2A2F8FBFFFF7B" , vcmpsd(k4, xmm5, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62916600C2D0AB" , vcmpss(k2, xmm19, xmm24, 171)); + TEST_INSTRUCTION("62916601C2D0AB" , k(k1).vcmpss(k2, xmm19, xmm24, 171)); + TEST_INSTRUCTION("62916610C2D0AB" , sae().vcmpss(k2, xmm19, xmm24, 171)); + TEST_INSTRUCTION("62916600C2D07B" , vcmpss(k2, xmm19, xmm24, 123)); + TEST_INSTRUCTION("62916610C2D07B" , sae().vcmpss(k2, xmm19, xmm24, 123)); + TEST_INSTRUCTION("62F16600C2117B" , vcmpss(k2, xmm19, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B16600C294F0341200007B" , vcmpss(k2, xmm19, dword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F16600C2527F7B" , vcmpss(k2, xmm19, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62F16600C292000200007B" , vcmpss(k2, xmm19, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62F16600C252807B" , vcmpss(k2, xmm19, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62F16600C292FCFDFFFF7B" , vcmpss(k2, xmm19, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("C441792FEB" , vcomisd(xmm13, xmm11)); + TEST_INSTRUCTION("6251FD182FEB" , sae().vcomisd(xmm13, xmm11)); + TEST_INSTRUCTION("C5792F29" , vcomisd(xmm13, qword_ptr(rcx))); + TEST_INSTRUCTION("C421792FACF034120000" , vcomisd(xmm13, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5792FAAF8030000" , vcomisd(xmm13, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C5792FAA00040000" , vcomisd(xmm13, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C5792FAA00FCFFFF" , vcomisd(xmm13, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C5792FAAF8FBFFFF" , vcomisd(xmm13, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C441782FC7" , vcomiss(xmm8, xmm15)); + TEST_INSTRUCTION("62517C182FC7" , sae().vcomiss(xmm8, xmm15)); + TEST_INSTRUCTION("C5782F01" , vcomiss(xmm8, dword_ptr(rcx))); + TEST_INSTRUCTION("C421782F84F034120000" , vcomiss(xmm8, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5782F82FC010000" , vcomiss(xmm8, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5782F8200020000" , vcomiss(xmm8, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5782F8200FEFFFF" , vcomiss(xmm8, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5782F82FCFDFFFF" , vcomiss(xmm8, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6262FD488A31" , vcompresspd(zmmword_ptr(rcx), zmm30)); + TEST_INSTRUCTION("6262FD4F8A31" , k(k7).vcompresspd(zmmword_ptr(rcx), zmm30)); + TEST_INSTRUCTION("6222FD488AB4F034120000" , vcompresspd(zmmword_ptr(rax, r14, 3, 4660), zmm30)); + TEST_INSTRUCTION("6262FD488A727F" , vcompresspd(zmmword_ptr(rdx, 1016), zmm30)); + TEST_INSTRUCTION("6262FD488AB200040000" , vcompresspd(zmmword_ptr(rdx, 1024), zmm30)); + TEST_INSTRUCTION("6262FD488A7280" , vcompresspd(zmmword_ptr(rdx, -1024), zmm30)); + TEST_INSTRUCTION("6262FD488AB2F8FBFFFF" , vcompresspd(zmmword_ptr(rdx, -1032), zmm30)); + TEST_INSTRUCTION("6262FD488AC9" , vcompresspd(zmm1, zmm25)); + TEST_INSTRUCTION("6262FD4C8AC9" , k(k4).vcompresspd(zmm1, zmm25)); + TEST_INSTRUCTION("6262FDCC8AC9" , k(k4).z().vcompresspd(zmm1, zmm25)); + TEST_INSTRUCTION("62727D488A11" , vcompressps(zmmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("62727D4C8A11" , k(k4).vcompressps(zmmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("62327D488A94F034120000" , vcompressps(zmmword_ptr(rax, r14, 3, 4660), zmm10)); + TEST_INSTRUCTION("62727D488A527F" , vcompressps(zmmword_ptr(rdx, 508), zmm10)); + TEST_INSTRUCTION("62727D488A9200020000" , vcompressps(zmmword_ptr(rdx, 512), zmm10)); + TEST_INSTRUCTION("62727D488A5280" , vcompressps(zmmword_ptr(rdx, -512), zmm10)); + TEST_INSTRUCTION("62727D488A92FCFDFFFF" , vcompressps(zmmword_ptr(rdx, -516), zmm10)); + TEST_INSTRUCTION("62B27D488AFB" , vcompressps(zmm19, zmm7)); + TEST_INSTRUCTION("62B27D4B8AFB" , k(k3).vcompressps(zmm19, zmm7)); + TEST_INSTRUCTION("62B27DCB8AFB" , k(k3).z().vcompressps(zmm19, zmm7)); + TEST_INSTRUCTION("62217E48E6E4" , vcvtdq2pd(zmm28, ymm20)); + TEST_INSTRUCTION("62217E4AE6E4" , k(k2).vcvtdq2pd(zmm28, ymm20)); + TEST_INSTRUCTION("62217ECAE6E4" , k(k2).z().vcvtdq2pd(zmm28, ymm20)); + TEST_INSTRUCTION("62617E48E621" , vcvtdq2pd(zmm28, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62217E48E6A4F034120000" , vcvtdq2pd(zmm28, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62617E58E621" , vcvtdq2pd(zmm28, dword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62617E48E6627F" , vcvtdq2pd(zmm28, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62617E48E6A200100000" , vcvtdq2pd(zmm28, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62617E48E66280" , vcvtdq2pd(zmm28, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62617E48E6A2E0EFFFFF" , vcvtdq2pd(zmm28, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62617E58E6627F" , vcvtdq2pd(zmm28, dword_ptr(rdx, 508)._1to8())); + TEST_INSTRUCTION("62617E58E6A200020000" , vcvtdq2pd(zmm28, dword_ptr(rdx, 512)._1to8())); + TEST_INSTRUCTION("62617E58E66280" , vcvtdq2pd(zmm28, dword_ptr(rdx, -512)._1to8())); + TEST_INSTRUCTION("62617E58E6A2FCFDFFFF" , vcvtdq2pd(zmm28, dword_ptr(rdx, -516)._1to8())); + TEST_INSTRUCTION("62E17C485BDC" , vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17C4D5BDC" , k(k5).vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17CCD5BDC" , k(k5).z().vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17C185BDC" , rn_sae().vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17C585BDC" , ru_sae().vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17C385BDC" , rd_sae().vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17C785BDC" , rz_sae().vcvtdq2ps(zmm19, zmm4)); + TEST_INSTRUCTION("62E17C485B19" , vcvtdq2ps(zmm19, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17C485B9CF034120000" , vcvtdq2ps(zmm19, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17C585B19" , vcvtdq2ps(zmm19, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E17C485B5A7F" , vcvtdq2ps(zmm19, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17C485B9A00200000" , vcvtdq2ps(zmm19, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17C485B5A80" , vcvtdq2ps(zmm19, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17C485B9AC0DFFFFF" , vcvtdq2ps(zmm19, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E17C585B5A7F" , vcvtdq2ps(zmm19, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E17C585B9A00020000" , vcvtdq2ps(zmm19, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E17C585B5A80" , vcvtdq2ps(zmm19, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E17C585B9AFCFDFFFF" , vcvtdq2ps(zmm19, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F1FF48E6F2" , vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FF4EE6F2" , k(k6).vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FFCEE6F2" , k(k6).z().vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FF18E6F2" , rn_sae().vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FF58E6F2" , ru_sae().vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FF38E6F2" , rd_sae().vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FF78E6F2" , rz_sae().vcvtpd2dq(ymm6, zmm2)); + TEST_INSTRUCTION("62F1FF48E631" , vcvtpd2dq(ymm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF48E6B4F034120000" , vcvtpd2dq(ymm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FF58E631" , vcvtpd2dq(ymm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1FF48E6727F" , vcvtpd2dq(ymm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FF48E6B200200000" , vcvtpd2dq(ymm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FF48E67280" , vcvtpd2dq(ymm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FF48E6B2C0DFFFFF" , vcvtpd2dq(ymm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1FF58E6727F" , vcvtpd2dq(ymm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1FF58E6B200040000" , vcvtpd2dq(ymm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1FF58E67280" , vcvtpd2dq(ymm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1FF58E6B2F8FBFFFF" , vcvtpd2dq(ymm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C1FD485AC2" , vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62C1FD4A5AC2" , k(k2).vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62C1FDCA5AC2" , k(k2).z().vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62C1FD185AC2" , rn_sae().vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62C1FD585AC2" , ru_sae().vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62C1FD385AC2" , rd_sae().vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62C1FD785AC2" , rz_sae().vcvtpd2ps(ymm16, zmm10)); + TEST_INSTRUCTION("62E1FD485A01" , vcvtpd2ps(ymm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD485A84F034120000" , vcvtpd2ps(ymm16, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1FD585A01" , vcvtpd2ps(ymm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1FD485A427F" , vcvtpd2ps(ymm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FD485A8200200000" , vcvtpd2ps(ymm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FD485A4280" , vcvtpd2ps(ymm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FD485A82C0DFFFFF" , vcvtpd2ps(ymm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FD585A427F" , vcvtpd2ps(ymm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1FD585A8200040000" , vcvtpd2ps(ymm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1FD585A4280" , vcvtpd2ps(ymm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1FD585A82F8FBFFFF" , vcvtpd2ps(ymm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6201FC4879C9" , vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6201FC4979C9" , k(k1).vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6201FCC979C9" , k(k1).z().vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6201FC1879C9" , rn_sae().vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6201FC5879C9" , ru_sae().vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6201FC3879C9" , rd_sae().vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6201FC7879C9" , rz_sae().vcvtpd2udq(ymm25, zmm25)); + TEST_INSTRUCTION("6261FC487909" , vcvtpd2udq(ymm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221FC48798CF034120000" , vcvtpd2udq(ymm25, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261FC587909" , vcvtpd2udq(ymm25, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261FC48794A7F" , vcvtpd2udq(ymm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261FC48798A00200000" , vcvtpd2udq(ymm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261FC48794A80" , vcvtpd2udq(ymm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261FC48798AC0DFFFFF" , vcvtpd2udq(ymm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261FC58794A7F" , vcvtpd2udq(ymm25, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261FC58798A00040000" , vcvtpd2udq(ymm25, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261FC58794A80" , vcvtpd2udq(ymm25, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261FC58798AF8FBFFFF" , vcvtpd2udq(ymm25, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62327D4813CD" , vcvtph2ps(zmm9, ymm21)); + TEST_INSTRUCTION("62327D4B13CD" , k(k3).vcvtph2ps(zmm9, ymm21)); + TEST_INSTRUCTION("62327DCB13CD" , k(k3).z().vcvtph2ps(zmm9, ymm21)); + TEST_INSTRUCTION("62327D1813CD" , sae().vcvtph2ps(zmm9, ymm21)); + TEST_INSTRUCTION("62727D481309" , vcvtph2ps(zmm9, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62327D48138CF034120000" , vcvtph2ps(zmm9, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D48134A7F" , vcvtph2ps(zmm9, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62727D48138A00100000" , vcvtph2ps(zmm9, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62727D48134A80" , vcvtph2ps(zmm9, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62727D48138AE0EFFFFF" , vcvtph2ps(zmm9, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62E17D485BC6" , vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17D4A5BC6" , k(k2).vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17DCA5BC6" , k(k2).z().vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17D185BC6" , rn_sae().vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17D585BC6" , ru_sae().vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17D385BC6" , rd_sae().vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17D785BC6" , rz_sae().vcvtps2dq(zmm16, zmm6)); + TEST_INSTRUCTION("62E17D485B01" , vcvtps2dq(zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17D485B84F034120000" , vcvtps2dq(zmm16, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17D585B01" , vcvtps2dq(zmm16, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E17D485B427F" , vcvtps2dq(zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17D485B8200200000" , vcvtps2dq(zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17D485B4280" , vcvtps2dq(zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17D485B82C0DFFFFF" , vcvtps2dq(zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E17D585B427F" , vcvtps2dq(zmm16, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E17D585B8200020000" , vcvtps2dq(zmm16, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E17D585B4280" , vcvtps2dq(zmm16, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E17D585B82FCFDFFFF" , vcvtps2dq(zmm16, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62117C485AD8" , vcvtps2pd(zmm11, ymm24)); + TEST_INSTRUCTION("62117C4B5AD8" , k(k3).vcvtps2pd(zmm11, ymm24)); + TEST_INSTRUCTION("62117CCB5AD8" , k(k3).z().vcvtps2pd(zmm11, ymm24)); + TEST_INSTRUCTION("62117C185AD8" , sae().vcvtps2pd(zmm11, ymm24)); + TEST_INSTRUCTION("62717C485A19" , vcvtps2pd(zmm11, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62317C485A9CF034120000" , vcvtps2pd(zmm11, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62717C585A19" , vcvtps2pd(zmm11, dword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62717C485A5A7F" , vcvtps2pd(zmm11, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62717C485A9A00100000" , vcvtps2pd(zmm11, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62717C485A5A80" , vcvtps2pd(zmm11, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62717C485A9AE0EFFFFF" , vcvtps2pd(zmm11, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62717C585A5A7F" , vcvtps2pd(zmm11, dword_ptr(rdx, 508)._1to8())); + TEST_INSTRUCTION("62717C585A9A00020000" , vcvtps2pd(zmm11, dword_ptr(rdx, 512)._1to8())); + TEST_INSTRUCTION("62717C585A5A80" , vcvtps2pd(zmm11, dword_ptr(rdx, -512)._1to8())); + TEST_INSTRUCTION("62717C585A9AFCFDFFFF" , vcvtps2pd(zmm11, dword_ptr(rdx, -516)._1to8())); + TEST_INSTRUCTION("62C37D481DF1AB" , vcvtps2ph(ymm9, zmm22, 171)); + TEST_INSTRUCTION("62C37D4F1DF1AB" , k(k7).vcvtps2ph(ymm9, zmm22, 171)); + TEST_INSTRUCTION("62C37DCF1DF1AB" , k(k7).z().vcvtps2ph(ymm9, zmm22, 171)); + TEST_INSTRUCTION("62C37D181DF1AB" , sae().vcvtps2ph(ymm9, zmm22, 171)); + TEST_INSTRUCTION("62C37D481DF17B" , vcvtps2ph(ymm9, zmm22, 123)); + TEST_INSTRUCTION("62C37D181DF17B" , sae().vcvtps2ph(ymm9, zmm22, 123)); + TEST_INSTRUCTION("62F17C4879EC" , vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17C4D79EC" , k(k5).vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17CCD79EC" , k(k5).z().vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17C1879EC" , rn_sae().vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17C5879EC" , ru_sae().vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17C3879EC" , rd_sae().vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17C7879EC" , rz_sae().vcvtps2udq(zmm5, zmm4)); + TEST_INSTRUCTION("62F17C487929" , vcvtps2udq(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17C4879ACF034120000" , vcvtps2udq(zmm5, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17C587929" , vcvtps2udq(zmm5, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F17C48796A7F" , vcvtps2udq(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17C4879AA00200000" , vcvtps2udq(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17C48796A80" , vcvtps2udq(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17C4879AAC0DFFFFF" , vcvtps2udq(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F17C58796A7F" , vcvtps2udq(zmm5, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F17C5879AA00020000" , vcvtps2udq(zmm5, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F17C58796A80" , vcvtps2udq(zmm5, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F17C5879AAFCFDFFFF" , vcvtps2udq(zmm5, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F17F182DC4" , rn_sae().vcvtsd2si(eax, xmm4)); + TEST_INSTRUCTION("62F17F582DC4" , ru_sae().vcvtsd2si(eax, xmm4)); + TEST_INSTRUCTION("62F17F382DC4" , rd_sae().vcvtsd2si(eax, xmm4)); + TEST_INSTRUCTION("62F17F782DC4" , rz_sae().vcvtsd2si(eax, xmm4)); + TEST_INSTRUCTION("62F17F182DEC" , rn_sae().vcvtsd2si(ebp, xmm4)); + TEST_INSTRUCTION("62F17F582DEC" , ru_sae().vcvtsd2si(ebp, xmm4)); + TEST_INSTRUCTION("62F17F382DEC" , rd_sae().vcvtsd2si(ebp, xmm4)); + TEST_INSTRUCTION("62F17F782DEC" , rz_sae().vcvtsd2si(ebp, xmm4)); + TEST_INSTRUCTION("62717F182DEC" , rn_sae().vcvtsd2si(r13d, xmm4)); + TEST_INSTRUCTION("62717F582DEC" , ru_sae().vcvtsd2si(r13d, xmm4)); + TEST_INSTRUCTION("62717F382DEC" , rd_sae().vcvtsd2si(r13d, xmm4)); + TEST_INSTRUCTION("62717F782DEC" , rz_sae().vcvtsd2si(r13d, xmm4)); + TEST_INSTRUCTION("6291FF182DC3" , rn_sae().vcvtsd2si(rax, xmm27)); + TEST_INSTRUCTION("6291FF582DC3" , ru_sae().vcvtsd2si(rax, xmm27)); + TEST_INSTRUCTION("6291FF382DC3" , rd_sae().vcvtsd2si(rax, xmm27)); + TEST_INSTRUCTION("6291FF782DC3" , rz_sae().vcvtsd2si(rax, xmm27)); + TEST_INSTRUCTION("6211FF182DC3" , rn_sae().vcvtsd2si(r8, xmm27)); + TEST_INSTRUCTION("6211FF582DC3" , ru_sae().vcvtsd2si(r8, xmm27)); + TEST_INSTRUCTION("6211FF382DC3" , rd_sae().vcvtsd2si(r8, xmm27)); + TEST_INSTRUCTION("6211FF782DC3" , rz_sae().vcvtsd2si(r8, xmm27)); + TEST_INSTRUCTION("C5B32AE0" , vcvtsi2sd(xmm4, xmm9, eax)); + TEST_INSTRUCTION("C5B32AE5" , vcvtsi2sd(xmm4, xmm9, ebp)); + TEST_INSTRUCTION("C4C1332AE5" , vcvtsi2sd(xmm4, xmm9, r13d)); + TEST_INSTRUCTION("C5B32A21" , vcvtsi2sd(xmm4, xmm9, dword_ptr(rcx))); + TEST_INSTRUCTION("C4A1332AA4F034120000" , vcvtsi2sd(xmm4, xmm9, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5B32AA2FC010000" , vcvtsi2sd(xmm4, xmm9, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5B32AA200020000" , vcvtsi2sd(xmm4, xmm9, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5B32AA200FEFFFF" , vcvtsi2sd(xmm4, xmm9, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5B32AA2FCFDFFFF" , vcvtsi2sd(xmm4, xmm9, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6261F7002AC0" , vcvtsi2sd(xmm24, xmm17, rax)); + TEST_INSTRUCTION("6261F7102AC0" , rn_sae().vcvtsi2sd(xmm24, xmm17, rax)); + TEST_INSTRUCTION("6261F7502AC0" , ru_sae().vcvtsi2sd(xmm24, xmm17, rax)); + TEST_INSTRUCTION("6261F7302AC0" , rd_sae().vcvtsi2sd(xmm24, xmm17, rax)); + TEST_INSTRUCTION("6261F7702AC0" , rz_sae().vcvtsi2sd(xmm24, xmm17, rax)); + TEST_INSTRUCTION("6241F7002AC0" , vcvtsi2sd(xmm24, xmm17, r8)); + TEST_INSTRUCTION("6241F7102AC0" , rn_sae().vcvtsi2sd(xmm24, xmm17, r8)); + TEST_INSTRUCTION("6241F7502AC0" , ru_sae().vcvtsi2sd(xmm24, xmm17, r8)); + TEST_INSTRUCTION("6241F7302AC0" , rd_sae().vcvtsi2sd(xmm24, xmm17, r8)); + TEST_INSTRUCTION("6241F7702AC0" , rz_sae().vcvtsi2sd(xmm24, xmm17, r8)); + TEST_INSTRUCTION("6261F7002A01" , vcvtsi2sd(xmm24, xmm17, qword_ptr(rcx))); + TEST_INSTRUCTION("6221F7002A84F034120000" , vcvtsi2sd(xmm24, xmm17, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261F7002A427F" , vcvtsi2sd(xmm24, xmm17, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261F7002A8200040000" , vcvtsi2sd(xmm24, xmm17, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6261F7002A4280" , vcvtsi2sd(xmm24, xmm17, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261F7002A82F8FBFFFF" , vcvtsi2sd(xmm24, xmm17, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62611E002AC8" , vcvtsi2ss(xmm25, xmm28, eax)); + TEST_INSTRUCTION("62611E102AC8" , rn_sae().vcvtsi2ss(xmm25, xmm28, eax)); + TEST_INSTRUCTION("62611E502AC8" , ru_sae().vcvtsi2ss(xmm25, xmm28, eax)); + TEST_INSTRUCTION("62611E302AC8" , rd_sae().vcvtsi2ss(xmm25, xmm28, eax)); + TEST_INSTRUCTION("62611E702AC8" , rz_sae().vcvtsi2ss(xmm25, xmm28, eax)); + TEST_INSTRUCTION("62611E002ACD" , vcvtsi2ss(xmm25, xmm28, ebp)); + TEST_INSTRUCTION("62611E102ACD" , rn_sae().vcvtsi2ss(xmm25, xmm28, ebp)); + TEST_INSTRUCTION("62611E502ACD" , ru_sae().vcvtsi2ss(xmm25, xmm28, ebp)); + TEST_INSTRUCTION("62611E302ACD" , rd_sae().vcvtsi2ss(xmm25, xmm28, ebp)); + TEST_INSTRUCTION("62611E702ACD" , rz_sae().vcvtsi2ss(xmm25, xmm28, ebp)); + TEST_INSTRUCTION("62411E002ACD" , vcvtsi2ss(xmm25, xmm28, r13d)); + TEST_INSTRUCTION("62411E102ACD" , rn_sae().vcvtsi2ss(xmm25, xmm28, r13d)); + TEST_INSTRUCTION("62411E502ACD" , ru_sae().vcvtsi2ss(xmm25, xmm28, r13d)); + TEST_INSTRUCTION("62411E302ACD" , rd_sae().vcvtsi2ss(xmm25, xmm28, r13d)); + TEST_INSTRUCTION("62411E702ACD" , rz_sae().vcvtsi2ss(xmm25, xmm28, r13d)); + TEST_INSTRUCTION("62611E002A09" , vcvtsi2ss(xmm25, xmm28, dword_ptr(rcx))); + TEST_INSTRUCTION("62211E002A8CF034120000" , vcvtsi2ss(xmm25, xmm28, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62611E002A4A7F" , vcvtsi2ss(xmm25, xmm28, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62611E002A8A00020000" , vcvtsi2ss(xmm25, xmm28, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62611E002A4A80" , vcvtsi2ss(xmm25, xmm28, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62611E002A8AFCFDFFFF" , vcvtsi2ss(xmm25, xmm28, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("C4E1BA2AE0" , vcvtsi2ss(xmm4, xmm8, rax)); + TEST_INSTRUCTION("62F1BE182AE0" , rn_sae().vcvtsi2ss(xmm4, xmm8, rax)); + TEST_INSTRUCTION("62F1BE582AE0" , ru_sae().vcvtsi2ss(xmm4, xmm8, rax)); + TEST_INSTRUCTION("62F1BE382AE0" , rd_sae().vcvtsi2ss(xmm4, xmm8, rax)); + TEST_INSTRUCTION("62F1BE782AE0" , rz_sae().vcvtsi2ss(xmm4, xmm8, rax)); + TEST_INSTRUCTION("C4C1BA2AE0" , vcvtsi2ss(xmm4, xmm8, r8)); + TEST_INSTRUCTION("62D1BE182AE0" , rn_sae().vcvtsi2ss(xmm4, xmm8, r8)); + TEST_INSTRUCTION("62D1BE582AE0" , ru_sae().vcvtsi2ss(xmm4, xmm8, r8)); + TEST_INSTRUCTION("62D1BE382AE0" , rd_sae().vcvtsi2ss(xmm4, xmm8, r8)); + TEST_INSTRUCTION("62D1BE782AE0" , rz_sae().vcvtsi2ss(xmm4, xmm8, r8)); + TEST_INSTRUCTION("C4E1BA2A21" , vcvtsi2ss(xmm4, xmm8, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A1BA2AA4F034120000" , vcvtsi2ss(xmm4, xmm8, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C4E1BA2AA2F8030000" , vcvtsi2ss(xmm4, xmm8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E1BA2AA200040000" , vcvtsi2ss(xmm4, xmm8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E1BA2AA200FCFFFF" , vcvtsi2ss(xmm4, xmm8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E1BA2AA2F8FBFFFF" , vcvtsi2ss(xmm4, xmm8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62D17E182DC0" , rn_sae().vcvtss2si(eax, xmm8)); + TEST_INSTRUCTION("62D17E582DC0" , ru_sae().vcvtss2si(eax, xmm8)); + TEST_INSTRUCTION("62D17E382DC0" , rd_sae().vcvtss2si(eax, xmm8)); + TEST_INSTRUCTION("62D17E782DC0" , rz_sae().vcvtss2si(eax, xmm8)); + TEST_INSTRUCTION("62D17E182DE8" , rn_sae().vcvtss2si(ebp, xmm8)); + TEST_INSTRUCTION("62D17E582DE8" , ru_sae().vcvtss2si(ebp, xmm8)); + TEST_INSTRUCTION("62D17E382DE8" , rd_sae().vcvtss2si(ebp, xmm8)); + TEST_INSTRUCTION("62D17E782DE8" , rz_sae().vcvtss2si(ebp, xmm8)); + TEST_INSTRUCTION("62517E182DE8" , rn_sae().vcvtss2si(r13d, xmm8)); + TEST_INSTRUCTION("62517E582DE8" , ru_sae().vcvtss2si(r13d, xmm8)); + TEST_INSTRUCTION("62517E382DE8" , rd_sae().vcvtss2si(r13d, xmm8)); + TEST_INSTRUCTION("62517E782DE8" , rz_sae().vcvtss2si(r13d, xmm8)); + TEST_INSTRUCTION("62F1FE182DC6" , rn_sae().vcvtss2si(rax, xmm6)); + TEST_INSTRUCTION("62F1FE582DC6" , ru_sae().vcvtss2si(rax, xmm6)); + TEST_INSTRUCTION("62F1FE382DC6" , rd_sae().vcvtss2si(rax, xmm6)); + TEST_INSTRUCTION("62F1FE782DC6" , rz_sae().vcvtss2si(rax, xmm6)); + TEST_INSTRUCTION("6271FE182DC6" , rn_sae().vcvtss2si(r8, xmm6)); + TEST_INSTRUCTION("6271FE582DC6" , ru_sae().vcvtss2si(r8, xmm6)); + TEST_INSTRUCTION("6271FE382DC6" , rd_sae().vcvtss2si(r8, xmm6)); + TEST_INSTRUCTION("6271FE782DC6" , rz_sae().vcvtss2si(r8, xmm6)); + TEST_INSTRUCTION("62F1FD48E6E1" , vcvttpd2dq(ymm4, zmm1)); + TEST_INSTRUCTION("62F1FD4EE6E1" , k(k6).vcvttpd2dq(ymm4, zmm1)); + TEST_INSTRUCTION("62F1FDCEE6E1" , k(k6).z().vcvttpd2dq(ymm4, zmm1)); + TEST_INSTRUCTION("62F1FD18E6E1" , sae().vcvttpd2dq(ymm4, zmm1)); + TEST_INSTRUCTION("62F1FD48E621" , vcvttpd2dq(ymm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FD48E6A4F034120000" , vcvttpd2dq(ymm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FD58E621" , vcvttpd2dq(ymm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1FD48E6627F" , vcvttpd2dq(ymm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FD48E6A200200000" , vcvttpd2dq(ymm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FD48E66280" , vcvttpd2dq(ymm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FD48E6A2C0DFFFFF" , vcvttpd2dq(ymm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1FD58E6627F" , vcvttpd2dq(ymm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1FD58E6A200040000" , vcvttpd2dq(ymm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1FD58E66280" , vcvttpd2dq(ymm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1FD58E6A2F8FBFFFF" , vcvttpd2dq(ymm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62817E485BFC" , vcvttps2dq(zmm23, zmm28)); + TEST_INSTRUCTION("62817E4B5BFC" , k(k3).vcvttps2dq(zmm23, zmm28)); + TEST_INSTRUCTION("62817ECB5BFC" , k(k3).z().vcvttps2dq(zmm23, zmm28)); + TEST_INSTRUCTION("62817E185BFC" , sae().vcvttps2dq(zmm23, zmm28)); + TEST_INSTRUCTION("62E17E485B39" , vcvttps2dq(zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17E485BBCF034120000" , vcvttps2dq(zmm23, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17E585B39" , vcvttps2dq(zmm23, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E17E485B7A7F" , vcvttps2dq(zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17E485BBA00200000" , vcvttps2dq(zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17E485B7A80" , vcvttps2dq(zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17E485BBAC0DFFFFF" , vcvttps2dq(zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E17E585B7A7F" , vcvttps2dq(zmm23, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E17E585BBA00020000" , vcvttps2dq(zmm23, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E17E585B7A80" , vcvttps2dq(zmm23, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E17E585BBAFCFDFFFF" , vcvttps2dq(zmm23, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F17F182CC5" , sae().vcvttsd2si(eax, xmm5)); + TEST_INSTRUCTION("62F17F182CED" , sae().vcvttsd2si(ebp, xmm5)); + TEST_INSTRUCTION("62717F182CED" , sae().vcvttsd2si(r13d, xmm5)); + TEST_INSTRUCTION("62F1FF182CC7" , sae().vcvttsd2si(rax, xmm7)); + TEST_INSTRUCTION("6271FF182CC7" , sae().vcvttsd2si(r8, xmm7)); + TEST_INSTRUCTION("62F17E182CC4" , sae().vcvttss2si(eax, xmm4)); + TEST_INSTRUCTION("62F17E182CEC" , sae().vcvttss2si(ebp, xmm4)); + TEST_INSTRUCTION("62717E182CEC" , sae().vcvttss2si(r13d, xmm4)); + TEST_INSTRUCTION("6291FE182CC3" , sae().vcvttss2si(rax, xmm27)); + TEST_INSTRUCTION("6211FE182CC3" , sae().vcvttss2si(r8, xmm27)); + TEST_INSTRUCTION("62817E487AD4" , vcvtudq2pd(zmm18, ymm28)); + TEST_INSTRUCTION("62817E497AD4" , k(k1).vcvtudq2pd(zmm18, ymm28)); + TEST_INSTRUCTION("62817EC97AD4" , k(k1).z().vcvtudq2pd(zmm18, ymm28)); + TEST_INSTRUCTION("62E17E487A11" , vcvtudq2pd(zmm18, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62A17E487A94F034120000" , vcvtudq2pd(zmm18, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17E587A11" , vcvtudq2pd(zmm18, dword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E17E487A527F" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62E17E487A9200100000" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62E17E487A5280" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62E17E487A92E0EFFFFF" , vcvtudq2pd(zmm18, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62E17E587A527F" , vcvtudq2pd(zmm18, dword_ptr(rdx, 508)._1to8())); + TEST_INSTRUCTION("62E17E587A9200020000" , vcvtudq2pd(zmm18, dword_ptr(rdx, 512)._1to8())); + TEST_INSTRUCTION("62E17E587A5280" , vcvtudq2pd(zmm18, dword_ptr(rdx, -512)._1to8())); + TEST_INSTRUCTION("62E17E587A92FCFDFFFF" , vcvtudq2pd(zmm18, dword_ptr(rdx, -516)._1to8())); + TEST_INSTRUCTION("62917F487AF8" , vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62917F4F7AF8" , k(k7).vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62917FCF7AF8" , k(k7).z().vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62917F187AF8" , rn_sae().vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62917F587AF8" , ru_sae().vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62917F387AF8" , rd_sae().vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62917F787AF8" , rz_sae().vcvtudq2ps(zmm7, zmm24)); + TEST_INSTRUCTION("62F17F487A39" , vcvtudq2ps(zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17F487ABCF034120000" , vcvtudq2ps(zmm7, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17F587A39" , vcvtudq2ps(zmm7, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F17F487A7A7F" , vcvtudq2ps(zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17F487ABA00200000" , vcvtudq2ps(zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17F487A7A80" , vcvtudq2ps(zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17F487ABAC0DFFFFF" , vcvtudq2ps(zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F17F587A7A7F" , vcvtudq2ps(zmm7, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F17F587ABA00020000" , vcvtudq2ps(zmm7, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F17F587A7A80" , vcvtudq2ps(zmm7, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F17F587ABAFCFDFFFF" , vcvtudq2ps(zmm7, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A1DD485ED3" , vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62A1DD4D5ED3" , k(k5).vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62A1DDCD5ED3" , k(k5).z().vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62A1DD185ED3" , rn_sae().vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62A1DD585ED3" , ru_sae().vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62A1DD385ED3" , rd_sae().vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62A1DD785ED3" , rz_sae().vdivpd(zmm18, zmm4, zmm19)); + TEST_INSTRUCTION("62E1DD485E11" , vdivpd(zmm18, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1DD485E94F034120000" , vdivpd(zmm18, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1DD585E11" , vdivpd(zmm18, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1DD485E527F" , vdivpd(zmm18, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1DD485E9200200000" , vdivpd(zmm18, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1DD485E5280" , vdivpd(zmm18, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1DD485E92C0DFFFFF" , vdivpd(zmm18, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1DD585E527F" , vdivpd(zmm18, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1DD585E9200040000" , vdivpd(zmm18, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1DD585E5280" , vdivpd(zmm18, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1DD585E92F8FBFFFF" , vdivpd(zmm18, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F114405EF4" , vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114465EF4" , k(k6).vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114C65EF4" , k(k6).z().vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114105EF4" , rn_sae().vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114505EF4" , ru_sae().vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114305EF4" , rd_sae().vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114705EF4" , rz_sae().vdivps(zmm6, zmm29, zmm4)); + TEST_INSTRUCTION("62F114405E31" , vdivps(zmm6, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B114405EB4F034120000" , vdivps(zmm6, zmm29, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F114505E31" , vdivps(zmm6, zmm29, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F114405E727F" , vdivps(zmm6, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F114405EB200200000" , vdivps(zmm6, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F114405E7280" , vdivps(zmm6, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F114405EB2C0DFFFFF" , vdivps(zmm6, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F114505E727F" , vdivps(zmm6, zmm29, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F114505EB200020000" , vdivps(zmm6, zmm29, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F114505E7280" , vdivps(zmm6, zmm29, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F114505EB2FCFDFFFF" , vdivps(zmm6, zmm29, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6231DF085EFE" , vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("6231DF0B5EFE" , k(k3).vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("6231DF8B5EFE" , k(k3).z().vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("6231DF185EFE" , rn_sae().vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("6231DF585EFE" , ru_sae().vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("6231DF385EFE" , rd_sae().vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("6231DF785EFE" , rz_sae().vdivsd(xmm15, xmm4, xmm22)); + TEST_INSTRUCTION("C55B5E39" , vdivsd(xmm15, xmm4, qword_ptr(rcx))); + TEST_INSTRUCTION("C4215B5EBCF034120000" , vdivsd(xmm15, xmm4, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C55B5EBAF8030000" , vdivsd(xmm15, xmm4, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C55B5EBA00040000" , vdivsd(xmm15, xmm4, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C55B5EBA00FCFFFF" , vdivsd(xmm15, xmm4, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C55B5EBAF8FBFFFF" , vdivsd(xmm15, xmm4, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62216E085EDC" , vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62216E0D5EDC" , k(k5).vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62216E8D5EDC" , k(k5).z().vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62216E185EDC" , rn_sae().vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62216E585EDC" , ru_sae().vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62216E385EDC" , rd_sae().vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62216E785EDC" , rz_sae().vdivss(xmm27, xmm2, xmm20)); + TEST_INSTRUCTION("62616E085E19" , vdivss(xmm27, xmm2, dword_ptr(rcx))); + TEST_INSTRUCTION("62216E085E9CF034120000" , vdivss(xmm27, xmm2, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62616E085E5A7F" , vdivss(xmm27, xmm2, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62616E085E9A00020000" , vdivss(xmm27, xmm2, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62616E085E5A80" , vdivss(xmm27, xmm2, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62616E085E9AFCFDFFFF" , vdivss(xmm27, xmm2, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F2FD488821" , vexpandpd(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F2FD4F8821" , k(k7).vexpandpd(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F2FDCF8821" , k(k7).z().vexpandpd(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2FD4888A4F034120000" , vexpandpd(zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2FD4888627F" , vexpandpd(zmm4, zmmword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F2FD4888A200040000" , vexpandpd(zmm4, zmmword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F2FD48886280" , vexpandpd(zmm4, zmmword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F2FD4888A2F8FBFFFF" , vexpandpd(zmm4, zmmword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62C2FD4888D1" , vexpandpd(zmm18, zmm9)); + TEST_INSTRUCTION("62C2FD4A88D1" , k(k2).vexpandpd(zmm18, zmm9)); + TEST_INSTRUCTION("62C2FDCA88D1" , k(k2).z().vexpandpd(zmm18, zmm9)); + TEST_INSTRUCTION("62627D488821" , vexpandps(zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62627D4F8821" , k(k7).vexpandps(zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62627DCF8821" , k(k7).z().vexpandps(zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62227D4888A4F034120000" , vexpandps(zmm28, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62627D4888627F" , vexpandps(zmm28, zmmword_ptr(rdx, 508))); + TEST_INSTRUCTION("62627D4888A200020000" , vexpandps(zmm28, zmmword_ptr(rdx, 512))); + TEST_INSTRUCTION("62627D48886280" , vexpandps(zmm28, zmmword_ptr(rdx, -512))); + TEST_INSTRUCTION("62627D4888A2FCFDFFFF" , vexpandps(zmm28, zmmword_ptr(rdx, -516))); + TEST_INSTRUCTION("62A27D4888CA" , vexpandps(zmm17, zmm18)); + TEST_INSTRUCTION("62A27D4988CA" , k(k1).vexpandps(zmm17, zmm18)); + TEST_INSTRUCTION("62A27DC988CA" , k(k1).z().vexpandps(zmm17, zmm18)); + TEST_INSTRUCTION("62337D4819D5AB" , vextractf32x4(xmm21, zmm10, 171)); + TEST_INSTRUCTION("62337D4A19D5AB" , k(k2).vextractf32x4(xmm21, zmm10, 171)); + TEST_INSTRUCTION("62337DCA19D5AB" , k(k2).z().vextractf32x4(xmm21, zmm10, 171)); + TEST_INSTRUCTION("62337D4819D57B" , vextractf32x4(xmm21, zmm10, 123)); + TEST_INSTRUCTION("62D3FD481BEEAB" , vextractf64x4(ymm14, zmm5, 171)); + TEST_INSTRUCTION("62D3FD4B1BEEAB" , k(k3).vextractf64x4(ymm14, zmm5, 171)); + TEST_INSTRUCTION("62D3FDCB1BEEAB" , k(k3).z().vextractf64x4(ymm14, zmm5, 171)); + TEST_INSTRUCTION("62D3FD481BEE7B" , vextractf64x4(ymm14, zmm5, 123)); + TEST_INSTRUCTION("62137D4839E5AB" , vextracti32x4(xmm29, zmm12, 171)); + TEST_INSTRUCTION("62137D4D39E5AB" , k(k5).vextracti32x4(xmm29, zmm12, 171)); + TEST_INSTRUCTION("62137DCD39E5AB" , k(k5).z().vextracti32x4(xmm29, zmm12, 171)); + TEST_INSTRUCTION("62137D4839E57B" , vextracti32x4(xmm29, zmm12, 123)); + TEST_INSTRUCTION("62E3FD483BF5AB" , vextracti64x4(ymm5, zmm22, 171)); + TEST_INSTRUCTION("62E3FD4E3BF5AB" , k(k6).vextracti64x4(ymm5, zmm22, 171)); + TEST_INSTRUCTION("62E3FDCE3BF5AB" , k(k6).z().vextracti64x4(ymm5, zmm22, 171)); + TEST_INSTRUCTION("62E3FD483BF57B" , vextracti64x4(ymm5, zmm22, 123)); + TEST_INSTRUCTION("62C2854898FB" , vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62C2854F98FB" , k(k7).vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62C285CF98FB" , k(k7).z().vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62C2851898FB" , rn_sae().vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62C2855898FB" , ru_sae().vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62C2853898FB" , rd_sae().vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62C2857898FB" , rz_sae().vfmadd132pd(zmm23, zmm15, zmm11)); + TEST_INSTRUCTION("62E285489839" , vfmadd132pd(zmm23, zmm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2854898BCF034120000" , vfmadd132pd(zmm23, zmm15, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E285589839" , vfmadd132pd(zmm23, zmm15, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E28548987A7F" , vfmadd132pd(zmm23, zmm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2854898BA00200000" , vfmadd132pd(zmm23, zmm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E28548987A80" , vfmadd132pd(zmm23, zmm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2854898BAC0DFFFFF" , vfmadd132pd(zmm23, zmm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E28558987A7F" , vfmadd132pd(zmm23, zmm15, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2855898BA00040000" , vfmadd132pd(zmm23, zmm15, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E28558987A80" , vfmadd132pd(zmm23, zmm15, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2855898BAF8FBFFFF" , vfmadd132pd(zmm23, zmm15, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62A2354098D9" , vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62A2354698D9" , k(k6).vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62A235C698D9" , k(k6).z().vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62A2351098D9" , rn_sae().vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62A2355098D9" , ru_sae().vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62A2353098D9" , rd_sae().vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62A2357098D9" , rz_sae().vfmadd132ps(zmm19, zmm25, zmm17)); + TEST_INSTRUCTION("62E235409819" , vfmadd132ps(zmm19, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A23540989CF034120000" , vfmadd132ps(zmm19, zmm25, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E235509819" , vfmadd132ps(zmm19, zmm25, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E23540985A7F" , vfmadd132ps(zmm19, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E23540989A00200000" , vfmadd132ps(zmm19, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E23540985A80" , vfmadd132ps(zmm19, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E23540989AC0DFFFFF" , vfmadd132ps(zmm19, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E23550985A7F" , vfmadd132ps(zmm19, zmm25, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E23550989A00020000" , vfmadd132ps(zmm19, zmm25, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E23550985A80" , vfmadd132ps(zmm19, zmm25, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E23550989AFCFDFFFF" , vfmadd132ps(zmm19, zmm25, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C2CD0099D3" , vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62C2CD0699D3" , k(k6).vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62C2CD8699D3" , k(k6).z().vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62C2CD1099D3" , rn_sae().vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62C2CD5099D3" , ru_sae().vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62C2CD3099D3" , rd_sae().vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62C2CD7099D3" , rz_sae().vfmadd132sd(xmm18, xmm22, xmm11)); + TEST_INSTRUCTION("62E2CD009911" , vfmadd132sd(xmm18, xmm22, qword_ptr(rcx))); + TEST_INSTRUCTION("62A2CD009994F034120000" , vfmadd132sd(xmm18, xmm22, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2CD0099527F" , vfmadd132sd(xmm18, xmm22, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E2CD00999200040000" , vfmadd132sd(xmm18, xmm22, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E2CD00995280" , vfmadd132sd(xmm18, xmm22, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E2CD009992F8FBFFFF" , vfmadd132sd(xmm18, xmm22, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62625D0099D7" , vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D0799D7" , k(k7).vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D8799D7" , k(k7).z().vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D1099D7" , rn_sae().vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D5099D7" , ru_sae().vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D3099D7" , rd_sae().vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D7099D7" , rz_sae().vfmadd132ss(xmm26, xmm20, xmm7)); + TEST_INSTRUCTION("62625D009911" , vfmadd132ss(xmm26, xmm20, dword_ptr(rcx))); + TEST_INSTRUCTION("62225D009994F034120000" , vfmadd132ss(xmm26, xmm20, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62625D0099527F" , vfmadd132ss(xmm26, xmm20, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62625D00999200020000" , vfmadd132ss(xmm26, xmm20, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62625D00995280" , vfmadd132ss(xmm26, xmm20, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62625D009992FCFDFFFF" , vfmadd132ss(xmm26, xmm20, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F2F540A8F1" , vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F546A8F1" , k(k6).vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F5C6A8F1" , k(k6).z().vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F510A8F1" , rn_sae().vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F550A8F1" , ru_sae().vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F530A8F1" , rd_sae().vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F570A8F1" , rz_sae().vfmadd213pd(zmm6, zmm17, zmm1)); + TEST_INSTRUCTION("62F2F540A831" , vfmadd213pd(zmm6, zmm17, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2F540A8B4F034120000" , vfmadd213pd(zmm6, zmm17, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2F550A831" , vfmadd213pd(zmm6, zmm17, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2F540A8727F" , vfmadd213pd(zmm6, zmm17, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2F540A8B200200000" , vfmadd213pd(zmm6, zmm17, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2F540A87280" , vfmadd213pd(zmm6, zmm17, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2F540A8B2C0DFFFFF" , vfmadd213pd(zmm6, zmm17, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2F550A8727F" , vfmadd213pd(zmm6, zmm17, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2F550A8B200040000" , vfmadd213pd(zmm6, zmm17, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2F550A87280" , vfmadd213pd(zmm6, zmm17, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2F550A8B2F8FBFFFF" , vfmadd213pd(zmm6, zmm17, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62923D40A8E8" , vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62923D46A8E8" , k(k6).vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62923DC6A8E8" , k(k6).z().vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62923D10A8E8" , rn_sae().vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62923D50A8E8" , ru_sae().vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62923D30A8E8" , rd_sae().vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62923D70A8E8" , rz_sae().vfmadd213ps(zmm5, zmm24, zmm24)); + TEST_INSTRUCTION("62F23D40A829" , vfmadd213ps(zmm5, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B23D40A8ACF034120000" , vfmadd213ps(zmm5, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F23D50A829" , vfmadd213ps(zmm5, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F23D40A86A7F" , vfmadd213ps(zmm5, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F23D40A8AA00200000" , vfmadd213ps(zmm5, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F23D40A86A80" , vfmadd213ps(zmm5, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F23D40A8AAC0DFFFFF" , vfmadd213ps(zmm5, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F23D50A86A7F" , vfmadd213ps(zmm5, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F23D50A8AA00020000" , vfmadd213ps(zmm5, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F23D50A86A80" , vfmadd213ps(zmm5, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F23D50A8AAFCFDFFFF" , vfmadd213ps(zmm5, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62028D08A9F4" , vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62028D0DA9F4" , k(k5).vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62028D8DA9F4" , k(k5).z().vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62028D18A9F4" , rn_sae().vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62028D58A9F4" , ru_sae().vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62028D38A9F4" , rd_sae().vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62028D78A9F4" , rz_sae().vfmadd213sd(xmm30, xmm14, xmm28)); + TEST_INSTRUCTION("62628D08A931" , vfmadd213sd(xmm30, xmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("62228D08A9B4F034120000" , vfmadd213sd(xmm30, xmm14, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62628D08A9727F" , vfmadd213sd(xmm30, xmm14, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62628D08A9B200040000" , vfmadd213sd(xmm30, xmm14, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62628D08A97280" , vfmadd213sd(xmm30, xmm14, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62628D08A9B2F8FBFFFF" , vfmadd213sd(xmm30, xmm14, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62823500A9D1" , vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62823501A9D1" , k(k1).vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62823581A9D1" , k(k1).z().vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62823510A9D1" , rn_sae().vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62823550A9D1" , ru_sae().vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62823530A9D1" , rd_sae().vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62823570A9D1" , rz_sae().vfmadd213ss(xmm18, xmm25, xmm25)); + TEST_INSTRUCTION("62E23500A911" , vfmadd213ss(xmm18, xmm25, dword_ptr(rcx))); + TEST_INSTRUCTION("62A23500A994F034120000" , vfmadd213ss(xmm18, xmm25, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E23500A9527F" , vfmadd213ss(xmm18, xmm25, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E23500A99200020000" , vfmadd213ss(xmm18, xmm25, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E23500A95280" , vfmadd213ss(xmm18, xmm25, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E23500A992FCFDFFFF" , vfmadd213ss(xmm18, xmm25, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B29548B8EB" , vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62B29549B8EB" , k(k1).vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62B295C9B8EB" , k(k1).z().vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62B29518B8EB" , rn_sae().vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62B29558B8EB" , ru_sae().vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62B29538B8EB" , rd_sae().vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62B29578B8EB" , rz_sae().vfmadd231pd(zmm5, zmm13, zmm19)); + TEST_INSTRUCTION("62F29548B829" , vfmadd231pd(zmm5, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B29548B8ACF034120000" , vfmadd231pd(zmm5, zmm13, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F29558B829" , vfmadd231pd(zmm5, zmm13, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F29548B86A7F" , vfmadd231pd(zmm5, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F29548B8AA00200000" , vfmadd231pd(zmm5, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F29548B86A80" , vfmadd231pd(zmm5, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F29548B8AAC0DFFFFF" , vfmadd231pd(zmm5, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F29558B86A7F" , vfmadd231pd(zmm5, zmm13, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F29558B8AA00040000" , vfmadd231pd(zmm5, zmm13, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F29558B86A80" , vfmadd231pd(zmm5, zmm13, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F29558B8AAF8FBFFFF" , vfmadd231pd(zmm5, zmm13, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B27548B8D2" , vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62B2754AB8D2" , k(k2).vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62B275CAB8D2" , k(k2).z().vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62B27518B8D2" , rn_sae().vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62B27558B8D2" , ru_sae().vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62B27538B8D2" , rd_sae().vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62B27578B8D2" , rz_sae().vfmadd231ps(zmm2, zmm1, zmm18)); + TEST_INSTRUCTION("62F27548B811" , vfmadd231ps(zmm2, zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27548B894F034120000" , vfmadd231ps(zmm2, zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27558B811" , vfmadd231ps(zmm2, zmm1, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27548B8527F" , vfmadd231ps(zmm2, zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27548B89200200000" , vfmadd231ps(zmm2, zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27548B85280" , vfmadd231ps(zmm2, zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27548B892C0DFFFFF" , vfmadd231ps(zmm2, zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27558B8527F" , vfmadd231ps(zmm2, zmm1, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27558B89200020000" , vfmadd231ps(zmm2, zmm1, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27558B85280" , vfmadd231ps(zmm2, zmm1, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27558B892FCFDFFFF" , vfmadd231ps(zmm2, zmm1, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C4C289B9F6" , vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("62D28D0AB9F6" , k(k2).vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("62D28D8AB9F6" , k(k2).z().vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("62D28D18B9F6" , rn_sae().vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("62D28D58B9F6" , ru_sae().vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("62D28D38B9F6" , rd_sae().vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("62D28D78B9F6" , rz_sae().vfmadd231sd(xmm6, xmm14, xmm14)); + TEST_INSTRUCTION("C4E289B931" , vfmadd231sd(xmm6, xmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A289B9B4F034120000" , vfmadd231sd(xmm6, xmm14, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C4E289B9B2F8030000" , vfmadd231sd(xmm6, xmm14, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E289B9B200040000" , vfmadd231sd(xmm6, xmm14, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E289B9B200FCFFFF" , vfmadd231sd(xmm6, xmm14, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E289B9B2F8FBFFFF" , vfmadd231sd(xmm6, xmm14, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62220D08B9D3" , vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62220D0CB9D3" , k(k4).vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62220D8CB9D3" , k(k4).z().vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62220D18B9D3" , rn_sae().vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62220D58B9D3" , ru_sae().vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62220D38B9D3" , rd_sae().vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62220D78B9D3" , rz_sae().vfmadd231ss(xmm26, xmm14, xmm19)); + TEST_INSTRUCTION("62620D08B911" , vfmadd231ss(xmm26, xmm14, dword_ptr(rcx))); + TEST_INSTRUCTION("62220D08B994F034120000" , vfmadd231ss(xmm26, xmm14, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62620D08B9527F" , vfmadd231ss(xmm26, xmm14, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62620D08B99200020000" , vfmadd231ss(xmm26, xmm14, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62620D08B95280" , vfmadd231ss(xmm26, xmm14, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62620D08B992FCFDFFFF" , vfmadd231ss(xmm26, xmm14, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62E2CD4896E2" , vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CD4E96E2" , k(k6).vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CDCE96E2" , k(k6).z().vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CD1896E2" , rn_sae().vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CD5896E2" , ru_sae().vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CD3896E2" , rd_sae().vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CD7896E2" , rz_sae().vfmaddsub132pd(zmm20, zmm6, zmm2)); + TEST_INSTRUCTION("62E2CD489621" , vfmaddsub132pd(zmm20, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2CD4896A4F034120000" , vfmaddsub132pd(zmm20, zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2CD589621" , vfmaddsub132pd(zmm20, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2CD4896627F" , vfmaddsub132pd(zmm20, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2CD4896A200200000" , vfmaddsub132pd(zmm20, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2CD48966280" , vfmaddsub132pd(zmm20, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2CD4896A2C0DFFFFF" , vfmaddsub132pd(zmm20, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2CD5896627F" , vfmaddsub132pd(zmm20, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2CD5896A200040000" , vfmaddsub132pd(zmm20, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2CD58966280" , vfmaddsub132pd(zmm20, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2CD5896A2F8FBFFFF" , vfmaddsub132pd(zmm20, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6242454896EC" , vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("6242454F96EC" , k(k7).vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("624245CF96EC" , k(k7).z().vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("6242451896EC" , rn_sae().vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("6242455896EC" , ru_sae().vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("6242453896EC" , rd_sae().vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("6242457896EC" , rz_sae().vfmaddsub132ps(zmm29, zmm7, zmm12)); + TEST_INSTRUCTION("626245489629" , vfmaddsub132ps(zmm29, zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222454896ACF034120000" , vfmaddsub132ps(zmm29, zmm7, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626245589629" , vfmaddsub132ps(zmm29, zmm7, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62624548966A7F" , vfmaddsub132ps(zmm29, zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262454896AA00200000" , vfmaddsub132ps(zmm29, zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62624548966A80" , vfmaddsub132ps(zmm29, zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262454896AAC0DFFFFF" , vfmaddsub132ps(zmm29, zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62624558966A7F" , vfmaddsub132ps(zmm29, zmm7, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("6262455896AA00020000" , vfmaddsub132ps(zmm29, zmm7, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62624558966A80" , vfmaddsub132ps(zmm29, zmm7, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("6262455896AAFCFDFFFF" , vfmaddsub132ps(zmm29, zmm7, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6242DD40A6DF" , vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6242DD43A6DF" , k(k3).vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6242DDC3A6DF" , k(k3).z().vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6242DD10A6DF" , rn_sae().vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6242DD50A6DF" , ru_sae().vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6242DD30A6DF" , rd_sae().vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6242DD70A6DF" , rz_sae().vfmaddsub213pd(zmm27, zmm20, zmm15)); + TEST_INSTRUCTION("6262DD40A619" , vfmaddsub213pd(zmm27, zmm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222DD40A69CF034120000" , vfmaddsub213pd(zmm27, zmm20, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262DD50A619" , vfmaddsub213pd(zmm27, zmm20, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262DD40A65A7F" , vfmaddsub213pd(zmm27, zmm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262DD40A69A00200000" , vfmaddsub213pd(zmm27, zmm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262DD40A65A80" , vfmaddsub213pd(zmm27, zmm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262DD40A69AC0DFFFFF" , vfmaddsub213pd(zmm27, zmm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262DD50A65A7F" , vfmaddsub213pd(zmm27, zmm20, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262DD50A69A00040000" , vfmaddsub213pd(zmm27, zmm20, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262DD50A65A80" , vfmaddsub213pd(zmm27, zmm20, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262DD50A69AF8FBFFFF" , vfmaddsub213pd(zmm27, zmm20, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C21548A6F2" , vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62C2154DA6F2" , k(k5).vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62C215CDA6F2" , k(k5).z().vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62C21518A6F2" , rn_sae().vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62C21558A6F2" , ru_sae().vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62C21538A6F2" , rd_sae().vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62C21578A6F2" , rz_sae().vfmaddsub213ps(zmm22, zmm13, zmm10)); + TEST_INSTRUCTION("62E21548A631" , vfmaddsub213ps(zmm22, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A21548A6B4F034120000" , vfmaddsub213ps(zmm22, zmm13, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E21558A631" , vfmaddsub213ps(zmm22, zmm13, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E21548A6727F" , vfmaddsub213ps(zmm22, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E21548A6B200200000" , vfmaddsub213ps(zmm22, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E21548A67280" , vfmaddsub213ps(zmm22, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E21548A6B2C0DFFFFF" , vfmaddsub213ps(zmm22, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E21558A6727F" , vfmaddsub213ps(zmm22, zmm13, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E21558A6B200020000" , vfmaddsub213ps(zmm22, zmm13, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E21558A67280" , vfmaddsub213ps(zmm22, zmm13, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E21558A6B2FCFDFFFF" , vfmaddsub213ps(zmm22, zmm13, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6292B540B6E4" , vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("6292B546B6E4" , k(k6).vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("6292B5C6B6E4" , k(k6).z().vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("6292B510B6E4" , rn_sae().vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("6292B550B6E4" , ru_sae().vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("6292B530B6E4" , rd_sae().vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("6292B570B6E4" , rz_sae().vfmaddsub231pd(zmm4, zmm25, zmm28)); + TEST_INSTRUCTION("62F2B540B621" , vfmaddsub231pd(zmm4, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2B540B6A4F034120000" , vfmaddsub231pd(zmm4, zmm25, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2B550B621" , vfmaddsub231pd(zmm4, zmm25, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2B540B6627F" , vfmaddsub231pd(zmm4, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2B540B6A200200000" , vfmaddsub231pd(zmm4, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2B540B66280" , vfmaddsub231pd(zmm4, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2B540B6A2C0DFFFFF" , vfmaddsub231pd(zmm4, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2B550B6627F" , vfmaddsub231pd(zmm4, zmm25, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2B550B6A200040000" , vfmaddsub231pd(zmm4, zmm25, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2B550B66280" , vfmaddsub231pd(zmm4, zmm25, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2B550B6A2F8FBFFFF" , vfmaddsub231pd(zmm4, zmm25, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D24D40B6FA" , vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D24D46B6FA" , k(k6).vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D24DC6B6FA" , k(k6).z().vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D24D10B6FA" , rn_sae().vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D24D50B6FA" , ru_sae().vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D24D30B6FA" , rd_sae().vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62D24D70B6FA" , rz_sae().vfmaddsub231ps(zmm7, zmm22, zmm10)); + TEST_INSTRUCTION("62F24D40B639" , vfmaddsub231ps(zmm7, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B24D40B6BCF034120000" , vfmaddsub231ps(zmm7, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F24D50B639" , vfmaddsub231ps(zmm7, zmm22, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F24D40B67A7F" , vfmaddsub231ps(zmm7, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F24D40B6BA00200000" , vfmaddsub231ps(zmm7, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F24D40B67A80" , vfmaddsub231ps(zmm7, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F24D40B6BAC0DFFFFF" , vfmaddsub231ps(zmm7, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F24D50B67A7F" , vfmaddsub231ps(zmm7, zmm22, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F24D50B6BA00020000" , vfmaddsub231ps(zmm7, zmm22, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F24D50B67A80" , vfmaddsub231ps(zmm7, zmm22, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F24D50B6BAFCFDFFFF" , vfmaddsub231ps(zmm7, zmm22, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("622295409ACB" , vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("622295449ACB" , k(k4).vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("622295C49ACB" , k(k4).z().vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("622295109ACB" , rn_sae().vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("622295509ACB" , ru_sae().vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("622295309ACB" , rd_sae().vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("622295709ACB" , rz_sae().vfmsub132pd(zmm25, zmm29, zmm19)); + TEST_INSTRUCTION("626295409A09" , vfmsub132pd(zmm25, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622295409A8CF034120000" , vfmsub132pd(zmm25, zmm29, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626295509A09" , vfmsub132pd(zmm25, zmm29, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("626295409A4A7F" , vfmsub132pd(zmm25, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("626295409A8A00200000" , vfmsub132pd(zmm25, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("626295409A4A80" , vfmsub132pd(zmm25, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626295409A8AC0DFFFFF" , vfmsub132pd(zmm25, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("626295509A4A7F" , vfmsub132pd(zmm25, zmm29, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("626295509A8A00040000" , vfmsub132pd(zmm25, zmm29, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("626295509A4A80" , vfmsub132pd(zmm25, zmm29, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("626295509A8AF8FBFFFF" , vfmsub132pd(zmm25, zmm29, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62224D489ADA" , vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62224D4C9ADA" , k(k4).vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62224DCC9ADA" , k(k4).z().vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62224D189ADA" , rn_sae().vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62224D589ADA" , ru_sae().vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62224D389ADA" , rd_sae().vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62224D789ADA" , rz_sae().vfmsub132ps(zmm27, zmm6, zmm18)); + TEST_INSTRUCTION("62624D489A19" , vfmsub132ps(zmm27, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62224D489A9CF034120000" , vfmsub132ps(zmm27, zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62624D589A19" , vfmsub132ps(zmm27, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62624D489A5A7F" , vfmsub132ps(zmm27, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62624D489A9A00200000" , vfmsub132ps(zmm27, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62624D489A5A80" , vfmsub132ps(zmm27, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62624D489A9AC0DFFFFF" , vfmsub132ps(zmm27, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62624D589A5A7F" , vfmsub132ps(zmm27, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62624D589A9A00020000" , vfmsub132ps(zmm27, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62624D589A5A80" , vfmsub132ps(zmm27, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62624D589A9AFCFDFFFF" , vfmsub132ps(zmm27, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6282DD009BFC" , vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("6282DD019BFC" , k(k1).vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("6282DD819BFC" , k(k1).z().vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("6282DD109BFC" , rn_sae().vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("6282DD509BFC" , ru_sae().vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("6282DD309BFC" , rd_sae().vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("6282DD709BFC" , rz_sae().vfmsub132sd(xmm23, xmm20, xmm28)); + TEST_INSTRUCTION("62E2DD009B39" , vfmsub132sd(xmm23, xmm20, qword_ptr(rcx))); + TEST_INSTRUCTION("62A2DD009BBCF034120000" , vfmsub132sd(xmm23, xmm20, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2DD009B7A7F" , vfmsub132sd(xmm23, xmm20, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E2DD009BBA00040000" , vfmsub132sd(xmm23, xmm20, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E2DD009B7A80" , vfmsub132sd(xmm23, xmm20, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E2DD009BBAF8FBFFFF" , vfmsub132sd(xmm23, xmm20, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("620235089BD1" , vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("6202350F9BD1" , k(k7).vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("6202358F9BD1" , k(k7).z().vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("620235189BD1" , rn_sae().vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("620235589BD1" , ru_sae().vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("620235389BD1" , rd_sae().vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("620235789BD1" , rz_sae().vfmsub132ss(xmm26, xmm9, xmm25)); + TEST_INSTRUCTION("626235089B11" , vfmsub132ss(xmm26, xmm9, dword_ptr(rcx))); + TEST_INSTRUCTION("622235089B94F034120000" , vfmsub132ss(xmm26, xmm9, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626235089B527F" , vfmsub132ss(xmm26, xmm9, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("626235089B9200020000" , vfmsub132ss(xmm26, xmm9, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("626235089B5280" , vfmsub132ss(xmm26, xmm9, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("626235089B92FCFDFFFF" , vfmsub132ss(xmm26, xmm9, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B2ED40AAFB" , vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62B2ED44AAFB" , k(k4).vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62B2EDC4AAFB" , k(k4).z().vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62B2ED10AAFB" , rn_sae().vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62B2ED50AAFB" , ru_sae().vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62B2ED30AAFB" , rd_sae().vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62B2ED70AAFB" , rz_sae().vfmsub213pd(zmm7, zmm18, zmm19)); + TEST_INSTRUCTION("62F2ED40AA39" , vfmsub213pd(zmm7, zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2ED40AABCF034120000" , vfmsub213pd(zmm7, zmm18, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2ED50AA39" , vfmsub213pd(zmm7, zmm18, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2ED40AA7A7F" , vfmsub213pd(zmm7, zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2ED40AABA00200000" , vfmsub213pd(zmm7, zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2ED40AA7A80" , vfmsub213pd(zmm7, zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2ED40AABAC0DFFFFF" , vfmsub213pd(zmm7, zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2ED50AA7A7F" , vfmsub213pd(zmm7, zmm18, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2ED50AABA00040000" , vfmsub213pd(zmm7, zmm18, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2ED50AA7A80" , vfmsub213pd(zmm7, zmm18, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2ED50AABAF8FBFFFF" , vfmsub213pd(zmm7, zmm18, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62727D40AACE" , vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727D46AACE" , k(k6).vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727DC6AACE" , k(k6).z().vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727D10AACE" , rn_sae().vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727D50AACE" , ru_sae().vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727D30AACE" , rd_sae().vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727D70AACE" , rz_sae().vfmsub213ps(zmm9, zmm16, zmm6)); + TEST_INSTRUCTION("62727D40AA09" , vfmsub213ps(zmm9, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D40AA8CF034120000" , vfmsub213ps(zmm9, zmm16, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D50AA09" , vfmsub213ps(zmm9, zmm16, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62727D40AA4A7F" , vfmsub213ps(zmm9, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62727D40AA8A00200000" , vfmsub213ps(zmm9, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62727D40AA4A80" , vfmsub213ps(zmm9, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62727D40AA8AC0DFFFFF" , vfmsub213ps(zmm9, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62727D50AA4A7F" , vfmsub213ps(zmm9, zmm16, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62727D50AA8A00020000" , vfmsub213ps(zmm9, zmm16, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62727D50AA4A80" , vfmsub213ps(zmm9, zmm16, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62727D50AA8AFCFDFFFF" , vfmsub213ps(zmm9, zmm16, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6232ED00ABE4" , vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6232ED04ABE4" , k(k4).vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6232ED84ABE4" , k(k4).z().vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6232ED10ABE4" , rn_sae().vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6232ED50ABE4" , ru_sae().vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6232ED30ABE4" , rd_sae().vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6232ED70ABE4" , rz_sae().vfmsub213sd(xmm12, xmm18, xmm20)); + TEST_INSTRUCTION("6272ED00AB21" , vfmsub213sd(xmm12, xmm18, qword_ptr(rcx))); + TEST_INSTRUCTION("6232ED00ABA4F034120000" , vfmsub213sd(xmm12, xmm18, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272ED00AB627F" , vfmsub213sd(xmm12, xmm18, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6272ED00ABA200040000" , vfmsub213sd(xmm12, xmm18, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6272ED00AB6280" , vfmsub213sd(xmm12, xmm18, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6272ED00ABA2F8FBFFFF" , vfmsub213sd(xmm12, xmm18, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C4C271ABD1" , vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("62D2750FABD1" , k(k7).vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("62D2758FABD1" , k(k7).z().vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("62D27518ABD1" , rn_sae().vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("62D27558ABD1" , ru_sae().vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("62D27538ABD1" , rd_sae().vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("62D27578ABD1" , rz_sae().vfmsub213ss(xmm2, xmm1, xmm9)); + TEST_INSTRUCTION("C4E271AB11" , vfmsub213ss(xmm2, xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("C4A271AB94F034120000" , vfmsub213ss(xmm2, xmm1, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C4E271AB92FC010000" , vfmsub213ss(xmm2, xmm1, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C4E271AB9200020000" , vfmsub213ss(xmm2, xmm1, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C4E271AB9200FEFFFF" , vfmsub213ss(xmm2, xmm1, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C4E271AB92FCFDFFFF" , vfmsub213ss(xmm2, xmm1, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C2ED48BACE" , vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62C2ED4ABACE" , k(k2).vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62C2EDCABACE" , k(k2).z().vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62C2ED18BACE" , rn_sae().vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62C2ED58BACE" , ru_sae().vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62C2ED38BACE" , rd_sae().vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62C2ED78BACE" , rz_sae().vfmsub231pd(zmm17, zmm2, zmm14)); + TEST_INSTRUCTION("62E2ED48BA09" , vfmsub231pd(zmm17, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2ED48BA8CF034120000" , vfmsub231pd(zmm17, zmm2, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2ED58BA09" , vfmsub231pd(zmm17, zmm2, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2ED48BA4A7F" , vfmsub231pd(zmm17, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2ED48BA8A00200000" , vfmsub231pd(zmm17, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2ED48BA4A80" , vfmsub231pd(zmm17, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2ED48BA8AC0DFFFFF" , vfmsub231pd(zmm17, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2ED58BA4A7F" , vfmsub231pd(zmm17, zmm2, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2ED58BA8A00040000" , vfmsub231pd(zmm17, zmm2, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2ED58BA4A80" , vfmsub231pd(zmm17, zmm2, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2ED58BA8AF8FBFFFF" , vfmsub231pd(zmm17, zmm2, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B25D48BAEC" , vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62B25D49BAEC" , k(k1).vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62B25DC9BAEC" , k(k1).z().vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62B25D18BAEC" , rn_sae().vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62B25D58BAEC" , ru_sae().vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62B25D38BAEC" , rd_sae().vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62B25D78BAEC" , rz_sae().vfmsub231ps(zmm5, zmm4, zmm20)); + TEST_INSTRUCTION("62F25D48BA29" , vfmsub231ps(zmm5, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B25D48BAACF034120000" , vfmsub231ps(zmm5, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F25D58BA29" , vfmsub231ps(zmm5, zmm4, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F25D48BA6A7F" , vfmsub231ps(zmm5, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F25D48BAAA00200000" , vfmsub231ps(zmm5, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F25D48BA6A80" , vfmsub231ps(zmm5, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F25D48BAAAC0DFFFFF" , vfmsub231ps(zmm5, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F25D58BA6A7F" , vfmsub231ps(zmm5, zmm4, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F25D58BAAA00020000" , vfmsub231ps(zmm5, zmm4, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F25D58BA6A80" , vfmsub231ps(zmm5, zmm4, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F25D58BAAAFCFDFFFF" , vfmsub231ps(zmm5, zmm4, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C4E2E9BBFE" , vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("62F2ED0CBBFE" , k(k4).vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("62F2ED8CBBFE" , k(k4).z().vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("62F2ED18BBFE" , rn_sae().vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("62F2ED58BBFE" , ru_sae().vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("62F2ED38BBFE" , rd_sae().vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("62F2ED78BBFE" , rz_sae().vfmsub231sd(xmm7, xmm2, xmm6)); + TEST_INSTRUCTION("C4E2E9BB39" , vfmsub231sd(xmm7, xmm2, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A2E9BBBCF034120000" , vfmsub231sd(xmm7, xmm2, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C4E2E9BBBAF8030000" , vfmsub231sd(xmm7, xmm2, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E2E9BBBA00040000" , vfmsub231sd(xmm7, xmm2, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E2E9BBBA00FCFFFF" , vfmsub231sd(xmm7, xmm2, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E2E9BBBAF8FBFFFF" , vfmsub231sd(xmm7, xmm2, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62A26D00BBD2" , vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62A26D07BBD2" , k(k7).vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62A26D87BBD2" , k(k7).z().vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62A26D10BBD2" , rn_sae().vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62A26D50BBD2" , ru_sae().vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62A26D30BBD2" , rd_sae().vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62A26D70BBD2" , rz_sae().vfmsub231ss(xmm18, xmm18, xmm18)); + TEST_INSTRUCTION("62E26D00BB11" , vfmsub231ss(xmm18, xmm18, dword_ptr(rcx))); + TEST_INSTRUCTION("62A26D00BB94F034120000" , vfmsub231ss(xmm18, xmm18, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E26D00BB527F" , vfmsub231ss(xmm18, xmm18, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E26D00BB9200020000" , vfmsub231ss(xmm18, xmm18, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E26D00BB5280" , vfmsub231ss(xmm18, xmm18, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E26D00BB92FCFDFFFF" , vfmsub231ss(xmm18, xmm18, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62E2DD4897EF" , vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DD4D97EF" , k(k5).vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DDCD97EF" , k(k5).z().vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DD1897EF" , rn_sae().vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DD5897EF" , ru_sae().vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DD3897EF" , rd_sae().vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DD7897EF" , rz_sae().vfmsubadd132pd(zmm21, zmm4, zmm7)); + TEST_INSTRUCTION("62E2DD489729" , vfmsubadd132pd(zmm21, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2DD4897ACF034120000" , vfmsubadd132pd(zmm21, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2DD589729" , vfmsubadd132pd(zmm21, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2DD48976A7F" , vfmsubadd132pd(zmm21, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2DD4897AA00200000" , vfmsubadd132pd(zmm21, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2DD48976A80" , vfmsubadd132pd(zmm21, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2DD4897AAC0DFFFFF" , vfmsubadd132pd(zmm21, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2DD58976A7F" , vfmsubadd132pd(zmm21, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2DD5897AA00040000" , vfmsubadd132pd(zmm21, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2DD58976A80" , vfmsubadd132pd(zmm21, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2DD5897AAF8FBFFFF" , vfmsubadd132pd(zmm21, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B23D4097F0" , vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62B23D4797F0" , k(k7).vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62B23DC797F0" , k(k7).z().vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62B23D1097F0" , rn_sae().vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62B23D5097F0" , ru_sae().vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62B23D3097F0" , rd_sae().vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62B23D7097F0" , rz_sae().vfmsubadd132ps(zmm6, zmm24, zmm16)); + TEST_INSTRUCTION("62F23D409731" , vfmsubadd132ps(zmm6, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B23D4097B4F034120000" , vfmsubadd132ps(zmm6, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F23D509731" , vfmsubadd132ps(zmm6, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F23D4097727F" , vfmsubadd132ps(zmm6, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F23D4097B200200000" , vfmsubadd132ps(zmm6, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F23D40977280" , vfmsubadd132ps(zmm6, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F23D4097B2C0DFFFFF" , vfmsubadd132ps(zmm6, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F23D5097727F" , vfmsubadd132ps(zmm6, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F23D5097B200020000" , vfmsubadd132ps(zmm6, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F23D50977280" , vfmsubadd132ps(zmm6, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F23D5097B2FCFDFFFF" , vfmsubadd132ps(zmm6, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6252CD40A7DB" , vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6252CD44A7DB" , k(k4).vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6252CDC4A7DB" , k(k4).z().vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6252CD10A7DB" , rn_sae().vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6252CD50A7DB" , ru_sae().vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6252CD30A7DB" , rd_sae().vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6252CD70A7DB" , rz_sae().vfmsubadd213pd(zmm11, zmm22, zmm11)); + TEST_INSTRUCTION("6272CD40A719" , vfmsubadd213pd(zmm11, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232CD40A79CF034120000" , vfmsubadd213pd(zmm11, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272CD50A719" , vfmsubadd213pd(zmm11, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272CD40A75A7F" , vfmsubadd213pd(zmm11, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272CD40A79A00200000" , vfmsubadd213pd(zmm11, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272CD40A75A80" , vfmsubadd213pd(zmm11, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272CD40A79AC0DFFFFF" , vfmsubadd213pd(zmm11, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272CD50A75A7F" , vfmsubadd213pd(zmm11, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272CD50A79A00040000" , vfmsubadd213pd(zmm11, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272CD50A75A80" , vfmsubadd213pd(zmm11, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272CD50A79AF8FBFFFF" , vfmsubadd213pd(zmm11, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62523548A7E2" , vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("6252354FA7E2" , k(k7).vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("625235CFA7E2" , k(k7).z().vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("62523518A7E2" , rn_sae().vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("62523558A7E2" , ru_sae().vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("62523538A7E2" , rd_sae().vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("62523578A7E2" , rz_sae().vfmsubadd213ps(zmm12, zmm9, zmm10)); + TEST_INSTRUCTION("62723548A721" , vfmsubadd213ps(zmm12, zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62323548A7A4F034120000" , vfmsubadd213ps(zmm12, zmm9, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62723558A721" , vfmsubadd213ps(zmm12, zmm9, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62723548A7627F" , vfmsubadd213ps(zmm12, zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62723548A7A200200000" , vfmsubadd213ps(zmm12, zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62723548A76280" , vfmsubadd213ps(zmm12, zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62723548A7A2C0DFFFFF" , vfmsubadd213ps(zmm12, zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62723558A7627F" , vfmsubadd213ps(zmm12, zmm9, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62723558A7A200020000" , vfmsubadd213ps(zmm12, zmm9, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62723558A76280" , vfmsubadd213ps(zmm12, zmm9, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62723558A7A2FCFDFFFF" , vfmsubadd213ps(zmm12, zmm9, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C2ED48B7E9" , vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62C2ED4EB7E9" , k(k6).vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62C2EDCEB7E9" , k(k6).z().vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62C2ED18B7E9" , rn_sae().vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62C2ED58B7E9" , ru_sae().vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62C2ED38B7E9" , rd_sae().vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62C2ED78B7E9" , rz_sae().vfmsubadd231pd(zmm21, zmm2, zmm9)); + TEST_INSTRUCTION("62E2ED48B729" , vfmsubadd231pd(zmm21, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2ED48B7ACF034120000" , vfmsubadd231pd(zmm21, zmm2, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2ED58B729" , vfmsubadd231pd(zmm21, zmm2, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2ED48B76A7F" , vfmsubadd231pd(zmm21, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2ED48B7AA00200000" , vfmsubadd231pd(zmm21, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2ED48B76A80" , vfmsubadd231pd(zmm21, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2ED48B7AAC0DFFFFF" , vfmsubadd231pd(zmm21, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2ED58B76A7F" , vfmsubadd231pd(zmm21, zmm2, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2ED58B7AA00040000" , vfmsubadd231pd(zmm21, zmm2, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2ED58B76A80" , vfmsubadd231pd(zmm21, zmm2, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2ED58B7AAF8FBFFFF" , vfmsubadd231pd(zmm21, zmm2, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62025540B7D8" , vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("62025546B7D8" , k(k6).vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("620255C6B7D8" , k(k6).z().vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("62025510B7D8" , rn_sae().vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("62025550B7D8" , ru_sae().vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("62025530B7D8" , rd_sae().vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("62025570B7D8" , rz_sae().vfmsubadd231ps(zmm27, zmm21, zmm24)); + TEST_INSTRUCTION("62625540B719" , vfmsubadd231ps(zmm27, zmm21, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62225540B79CF034120000" , vfmsubadd231ps(zmm27, zmm21, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62625550B719" , vfmsubadd231ps(zmm27, zmm21, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62625540B75A7F" , vfmsubadd231ps(zmm27, zmm21, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62625540B79A00200000" , vfmsubadd231ps(zmm27, zmm21, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62625540B75A80" , vfmsubadd231ps(zmm27, zmm21, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62625540B79AC0DFFFFF" , vfmsubadd231ps(zmm27, zmm21, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62625550B75A7F" , vfmsubadd231ps(zmm27, zmm21, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62625550B79A00020000" , vfmsubadd231ps(zmm27, zmm21, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62625550B75A80" , vfmsubadd231ps(zmm27, zmm21, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62625550B79AFCFDFFFF" , vfmsubadd231ps(zmm27, zmm21, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("623295409CDB" , vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("623295429CDB" , k(k2).vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("623295C29CDB" , k(k2).z().vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("623295109CDB" , rn_sae().vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("623295509CDB" , ru_sae().vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("623295309CDB" , rd_sae().vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("623295709CDB" , rz_sae().vfnmadd132pd(zmm11, zmm29, zmm19)); + TEST_INSTRUCTION("627295409C19" , vfnmadd132pd(zmm11, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("623295409C9CF034120000" , vfnmadd132pd(zmm11, zmm29, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("627295509C19" , vfnmadd132pd(zmm11, zmm29, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("627295409C5A7F" , vfnmadd132pd(zmm11, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("627295409C9A00200000" , vfnmadd132pd(zmm11, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("627295409C5A80" , vfnmadd132pd(zmm11, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("627295409C9AC0DFFFFF" , vfnmadd132pd(zmm11, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("627295509C5A7F" , vfnmadd132pd(zmm11, zmm29, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("627295509C9A00040000" , vfnmadd132pd(zmm11, zmm29, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("627295509C5A80" , vfnmadd132pd(zmm11, zmm29, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("627295509C9AF8FBFFFF" , vfnmadd132pd(zmm11, zmm29, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C265489CCF" , vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62C2654D9CCF" , k(k5).vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62C265CD9CCF" , k(k5).z().vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62C265189CCF" , rn_sae().vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62C265589CCF" , ru_sae().vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62C265389CCF" , rd_sae().vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62C265789CCF" , rz_sae().vfnmadd132ps(zmm17, zmm3, zmm15)); + TEST_INSTRUCTION("62E265489C09" , vfnmadd132ps(zmm17, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A265489C8CF034120000" , vfnmadd132ps(zmm17, zmm3, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E265589C09" , vfnmadd132ps(zmm17, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E265489C4A7F" , vfnmadd132ps(zmm17, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E265489C8A00200000" , vfnmadd132ps(zmm17, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E265489C4A80" , vfnmadd132ps(zmm17, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E265489C8AC0DFFFFF" , vfnmadd132ps(zmm17, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E265589C4A7F" , vfnmadd132ps(zmm17, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E265589C8A00020000" , vfnmadd132ps(zmm17, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E265589C4A80" , vfnmadd132ps(zmm17, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E265589C8AFCFDFFFF" , vfnmadd132ps(zmm17, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2BD009DD1" , vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD049DD1" , k(k4).vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD849DD1" , k(k4).z().vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD109DD1" , rn_sae().vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD509DD1" , ru_sae().vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD309DD1" , rd_sae().vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD709DD1" , rz_sae().vfnmadd132sd(xmm2, xmm24, xmm1)); + TEST_INSTRUCTION("62F2BD009D11" , vfnmadd132sd(xmm2, xmm24, qword_ptr(rcx))); + TEST_INSTRUCTION("62B2BD009D94F034120000" , vfnmadd132sd(xmm2, xmm24, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2BD009D527F" , vfnmadd132sd(xmm2, xmm24, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F2BD009D9200040000" , vfnmadd132sd(xmm2, xmm24, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F2BD009D5280" , vfnmadd132sd(xmm2, xmm24, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F2BD009D92F8FBFFFF" , vfnmadd132sd(xmm2, xmm24, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("625265009DED" , vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("625265049DED" , k(k4).vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("625265849DED" , k(k4).z().vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("625265109DED" , rn_sae().vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("625265509DED" , ru_sae().vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("625265309DED" , rd_sae().vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("625265709DED" , rz_sae().vfnmadd132ss(xmm13, xmm19, xmm13)); + TEST_INSTRUCTION("627265009D29" , vfnmadd132ss(xmm13, xmm19, dword_ptr(rcx))); + TEST_INSTRUCTION("623265009DACF034120000" , vfnmadd132ss(xmm13, xmm19, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("627265009D6A7F" , vfnmadd132ss(xmm13, xmm19, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("627265009DAA00020000" , vfnmadd132ss(xmm13, xmm19, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("627265009D6A80" , vfnmadd132ss(xmm13, xmm19, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("627265009DAAFCFDFFFF" , vfnmadd132ss(xmm13, xmm19, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6232F548ACFE" , vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6232F54BACFE" , k(k3).vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6232F5CBACFE" , k(k3).z().vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6232F518ACFE" , rn_sae().vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6232F558ACFE" , ru_sae().vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6232F538ACFE" , rd_sae().vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6232F578ACFE" , rz_sae().vfnmadd213pd(zmm15, zmm1, zmm22)); + TEST_INSTRUCTION("6272F548AC39" , vfnmadd213pd(zmm15, zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232F548ACBCF034120000" , vfnmadd213pd(zmm15, zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272F558AC39" , vfnmadd213pd(zmm15, zmm1, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272F548AC7A7F" , vfnmadd213pd(zmm15, zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272F548ACBA00200000" , vfnmadd213pd(zmm15, zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272F548AC7A80" , vfnmadd213pd(zmm15, zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272F548ACBAC0DFFFFF" , vfnmadd213pd(zmm15, zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272F558AC7A7F" , vfnmadd213pd(zmm15, zmm1, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272F558ACBA00040000" , vfnmadd213pd(zmm15, zmm1, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272F558AC7A80" , vfnmadd213pd(zmm15, zmm1, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272F558ACBAF8FBFFFF" , vfnmadd213pd(zmm15, zmm1, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62725D48ACDC" , vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725D4CACDC" , k(k4).vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725DCCACDC" , k(k4).z().vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725D18ACDC" , rn_sae().vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725D58ACDC" , ru_sae().vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725D38ACDC" , rd_sae().vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725D78ACDC" , rz_sae().vfnmadd213ps(zmm11, zmm4, zmm4)); + TEST_INSTRUCTION("62725D48AC19" , vfnmadd213ps(zmm11, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62325D48AC9CF034120000" , vfnmadd213ps(zmm11, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62725D58AC19" , vfnmadd213ps(zmm11, zmm4, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62725D48AC5A7F" , vfnmadd213ps(zmm11, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62725D48AC9A00200000" , vfnmadd213ps(zmm11, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62725D48AC5A80" , vfnmadd213ps(zmm11, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62725D48AC9AC0DFFFFF" , vfnmadd213ps(zmm11, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62725D58AC5A7F" , vfnmadd213ps(zmm11, zmm4, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62725D58AC9A00020000" , vfnmadd213ps(zmm11, zmm4, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62725D58AC5A80" , vfnmadd213ps(zmm11, zmm4, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62725D58AC9AFCFDFFFF" , vfnmadd213ps(zmm11, zmm4, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62428D08ADF3" , vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62428D0CADF3" , k(k4).vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62428D8CADF3" , k(k4).z().vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62428D18ADF3" , rn_sae().vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62428D58ADF3" , ru_sae().vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62428D38ADF3" , rd_sae().vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62428D78ADF3" , rz_sae().vfnmadd213sd(xmm30, xmm14, xmm11)); + TEST_INSTRUCTION("62628D08AD31" , vfnmadd213sd(xmm30, xmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("62228D08ADB4F034120000" , vfnmadd213sd(xmm30, xmm14, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62628D08AD727F" , vfnmadd213sd(xmm30, xmm14, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62628D08ADB200040000" , vfnmadd213sd(xmm30, xmm14, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62628D08AD7280" , vfnmadd213sd(xmm30, xmm14, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62628D08ADB2F8FBFFFF" , vfnmadd213sd(xmm30, xmm14, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62226508ADE4" , vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("6222650BADE4" , k(k3).vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("6222658BADE4" , k(k3).z().vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("62226518ADE4" , rn_sae().vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("62226558ADE4" , ru_sae().vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("62226538ADE4" , rd_sae().vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("62226578ADE4" , rz_sae().vfnmadd213ss(xmm28, xmm3, xmm20)); + TEST_INSTRUCTION("62626508AD21" , vfnmadd213ss(xmm28, xmm3, dword_ptr(rcx))); + TEST_INSTRUCTION("62226508ADA4F034120000" , vfnmadd213ss(xmm28, xmm3, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62626508AD627F" , vfnmadd213ss(xmm28, xmm3, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62626508ADA200020000" , vfnmadd213ss(xmm28, xmm3, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62626508AD6280" , vfnmadd213ss(xmm28, xmm3, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62626508ADA2FCFDFFFF" , vfnmadd213ss(xmm28, xmm3, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6232D548BCFE" , vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6232D54FBCFE" , k(k7).vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6232D5CFBCFE" , k(k7).z().vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6232D518BCFE" , rn_sae().vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6232D558BCFE" , ru_sae().vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6232D538BCFE" , rd_sae().vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6232D578BCFE" , rz_sae().vfnmadd231pd(zmm15, zmm5, zmm22)); + TEST_INSTRUCTION("6272D548BC39" , vfnmadd231pd(zmm15, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232D548BCBCF034120000" , vfnmadd231pd(zmm15, zmm5, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272D558BC39" , vfnmadd231pd(zmm15, zmm5, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272D548BC7A7F" , vfnmadd231pd(zmm15, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272D548BCBA00200000" , vfnmadd231pd(zmm15, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272D548BC7A80" , vfnmadd231pd(zmm15, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272D548BCBAC0DFFFFF" , vfnmadd231pd(zmm15, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272D558BC7A7F" , vfnmadd231pd(zmm15, zmm5, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272D558BCBA00040000" , vfnmadd231pd(zmm15, zmm5, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272D558BC7A80" , vfnmadd231pd(zmm15, zmm5, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272D558BCBAF8FBFFFF" , vfnmadd231pd(zmm15, zmm5, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62521D40BCE9" , vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62521D43BCE9" , k(k3).vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62521DC3BCE9" , k(k3).z().vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62521D10BCE9" , rn_sae().vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62521D50BCE9" , ru_sae().vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62521D30BCE9" , rd_sae().vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62521D70BCE9" , rz_sae().vfnmadd231ps(zmm13, zmm28, zmm9)); + TEST_INSTRUCTION("62721D40BC29" , vfnmadd231ps(zmm13, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62321D40BCACF034120000" , vfnmadd231ps(zmm13, zmm28, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62721D50BC29" , vfnmadd231ps(zmm13, zmm28, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62721D40BC6A7F" , vfnmadd231ps(zmm13, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62721D40BCAA00200000" , vfnmadd231ps(zmm13, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62721D40BC6A80" , vfnmadd231ps(zmm13, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62721D40BCAAC0DFFFFF" , vfnmadd231ps(zmm13, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62721D50BC6A7F" , vfnmadd231ps(zmm13, zmm28, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62721D50BCAA00020000" , vfnmadd231ps(zmm13, zmm28, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62721D50BC6A80" , vfnmadd231ps(zmm13, zmm28, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62721D50BCAAFCFDFFFF" , vfnmadd231ps(zmm13, zmm28, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("C462D1BDF5" , vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("6272D50FBDF5" , k(k7).vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("6272D58FBDF5" , k(k7).z().vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("6272D518BDF5" , rn_sae().vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("6272D558BDF5" , ru_sae().vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("6272D538BDF5" , rd_sae().vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("6272D578BDF5" , rz_sae().vfnmadd231sd(xmm14, xmm5, xmm5)); + TEST_INSTRUCTION("C462D1BD31" , vfnmadd231sd(xmm14, xmm5, qword_ptr(rcx))); + TEST_INSTRUCTION("C422D1BDB4F034120000" , vfnmadd231sd(xmm14, xmm5, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C462D1BDB2F8030000" , vfnmadd231sd(xmm14, xmm5, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C462D1BDB200040000" , vfnmadd231sd(xmm14, xmm5, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C462D1BDB200FCFFFF" , vfnmadd231sd(xmm14, xmm5, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C462D1BDB2F8FBFFFF" , vfnmadd231sd(xmm14, xmm5, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62027D00BDC9" , vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62027D06BDC9" , k(k6).vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62027D86BDC9" , k(k6).z().vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62027D10BDC9" , rn_sae().vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62027D50BDC9" , ru_sae().vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62027D30BDC9" , rd_sae().vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62027D70BDC9" , rz_sae().vfnmadd231ss(xmm25, xmm16, xmm25)); + TEST_INSTRUCTION("62627D00BD09" , vfnmadd231ss(xmm25, xmm16, dword_ptr(rcx))); + TEST_INSTRUCTION("62227D00BD8CF034120000" , vfnmadd231ss(xmm25, xmm16, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62627D00BD4A7F" , vfnmadd231ss(xmm25, xmm16, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62627D00BD8A00020000" , vfnmadd231ss(xmm25, xmm16, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62627D00BD4A80" , vfnmadd231ss(xmm25, xmm16, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62627D00BD8AFCFDFFFF" , vfnmadd231ss(xmm25, xmm16, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6242BD489ED9" , vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6242BD4C9ED9" , k(k4).vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6242BDCC9ED9" , k(k4).z().vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6242BD189ED9" , rn_sae().vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6242BD589ED9" , ru_sae().vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6242BD389ED9" , rd_sae().vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6242BD789ED9" , rz_sae().vfnmsub132pd(zmm27, zmm8, zmm9)); + TEST_INSTRUCTION("6262BD489E19" , vfnmsub132pd(zmm27, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222BD489E9CF034120000" , vfnmsub132pd(zmm27, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262BD589E19" , vfnmsub132pd(zmm27, zmm8, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262BD489E5A7F" , vfnmsub132pd(zmm27, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262BD489E9A00200000" , vfnmsub132pd(zmm27, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262BD489E5A80" , vfnmsub132pd(zmm27, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262BD489E9AC0DFFFFF" , vfnmsub132pd(zmm27, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262BD589E5A7F" , vfnmsub132pd(zmm27, zmm8, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262BD589E9A00040000" , vfnmsub132pd(zmm27, zmm8, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262BD589E5A80" , vfnmsub132pd(zmm27, zmm8, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262BD589E9AF8FBFFFF" , vfnmsub132pd(zmm27, zmm8, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("624225489ED1" , vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("6242254C9ED1" , k(k4).vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("624225CC9ED1" , k(k4).z().vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("624225189ED1" , rn_sae().vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("624225589ED1" , ru_sae().vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("624225389ED1" , rd_sae().vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("624225789ED1" , rz_sae().vfnmsub132ps(zmm26, zmm11, zmm9)); + TEST_INSTRUCTION("626225489E11" , vfnmsub132ps(zmm26, zmm11, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622225489E94F034120000" , vfnmsub132ps(zmm26, zmm11, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626225589E11" , vfnmsub132ps(zmm26, zmm11, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("626225489E527F" , vfnmsub132ps(zmm26, zmm11, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("626225489E9200200000" , vfnmsub132ps(zmm26, zmm11, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("626225489E5280" , vfnmsub132ps(zmm26, zmm11, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626225489E92C0DFFFFF" , vfnmsub132ps(zmm26, zmm11, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("626225589E527F" , vfnmsub132ps(zmm26, zmm11, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("626225589E9200020000" , vfnmsub132ps(zmm26, zmm11, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("626225589E5280" , vfnmsub132ps(zmm26, zmm11, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("626225589E92FCFDFFFF" , vfnmsub132ps(zmm26, zmm11, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B2BD089FDB" , vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("62B2BD0B9FDB" , k(k3).vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("62B2BD8B9FDB" , k(k3).z().vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("62B2BD189FDB" , rn_sae().vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("62B2BD589FDB" , ru_sae().vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("62B2BD389FDB" , rd_sae().vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("62B2BD789FDB" , rz_sae().vfnmsub132sd(xmm3, xmm8, xmm19)); + TEST_INSTRUCTION("C4E2B99F19" , vfnmsub132sd(xmm3, xmm8, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A2B99F9CF034120000" , vfnmsub132sd(xmm3, xmm8, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C4E2B99F9AF8030000" , vfnmsub132sd(xmm3, xmm8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C4E2B99F9A00040000" , vfnmsub132sd(xmm3, xmm8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C4E2B99F9A00FCFFFF" , vfnmsub132sd(xmm3, xmm8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C4E2B99F9AF8FBFFFF" , vfnmsub132sd(xmm3, xmm8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62E275009FDE" , vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275019FDE" , k(k1).vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275819FDE" , k(k1).z().vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275109FDE" , rn_sae().vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275509FDE" , ru_sae().vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275309FDE" , rd_sae().vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275709FDE" , rz_sae().vfnmsub132ss(xmm19, xmm17, xmm6)); + TEST_INSTRUCTION("62E275009F19" , vfnmsub132ss(xmm19, xmm17, dword_ptr(rcx))); + TEST_INSTRUCTION("62A275009F9CF034120000" , vfnmsub132ss(xmm19, xmm17, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E275009F5A7F" , vfnmsub132ss(xmm19, xmm17, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E275009F9A00020000" , vfnmsub132ss(xmm19, xmm17, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E275009F5A80" , vfnmsub132ss(xmm19, xmm17, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E275009F9AFCFDFFFF" , vfnmsub132ss(xmm19, xmm17, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F2BD48AEFF" , vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BD4DAEFF" , k(k5).vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BDCDAEFF" , k(k5).z().vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BD18AEFF" , rn_sae().vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BD58AEFF" , ru_sae().vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BD38AEFF" , rd_sae().vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BD78AEFF" , rz_sae().vfnmsub213pd(zmm7, zmm8, zmm7)); + TEST_INSTRUCTION("62F2BD48AE39" , vfnmsub213pd(zmm7, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2BD48AEBCF034120000" , vfnmsub213pd(zmm7, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2BD58AE39" , vfnmsub213pd(zmm7, zmm8, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2BD48AE7A7F" , vfnmsub213pd(zmm7, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2BD48AEBA00200000" , vfnmsub213pd(zmm7, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2BD48AE7A80" , vfnmsub213pd(zmm7, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2BD48AEBAC0DFFFFF" , vfnmsub213pd(zmm7, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2BD58AE7A7F" , vfnmsub213pd(zmm7, zmm8, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2BD58AEBA00040000" , vfnmsub213pd(zmm7, zmm8, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2BD58AE7A80" , vfnmsub213pd(zmm7, zmm8, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2BD58AEBAF8FBFFFF" , vfnmsub213pd(zmm7, zmm8, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62423D40AEEE" , vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62423D47AEEE" , k(k7).vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62423DC7AEEE" , k(k7).z().vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62423D10AEEE" , rn_sae().vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62423D50AEEE" , ru_sae().vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62423D30AEEE" , rd_sae().vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62423D70AEEE" , rz_sae().vfnmsub213ps(zmm29, zmm24, zmm14)); + TEST_INSTRUCTION("62623D40AE29" , vfnmsub213ps(zmm29, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62223D40AEACF034120000" , vfnmsub213ps(zmm29, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62623D50AE29" , vfnmsub213ps(zmm29, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62623D40AE6A7F" , vfnmsub213ps(zmm29, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62623D40AEAA00200000" , vfnmsub213ps(zmm29, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62623D40AE6A80" , vfnmsub213ps(zmm29, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62623D40AEAAC0DFFFFF" , vfnmsub213ps(zmm29, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62623D50AE6A7F" , vfnmsub213ps(zmm29, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62623D50AEAA00020000" , vfnmsub213ps(zmm29, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62623D50AE6A80" , vfnmsub213ps(zmm29, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62623D50AEAAFCFDFFFF" , vfnmsub213ps(zmm29, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6222BD08AFCF" , vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6222BD09AFCF" , k(k1).vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6222BD89AFCF" , k(k1).z().vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6222BD18AFCF" , rn_sae().vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6222BD58AFCF" , ru_sae().vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6222BD38AFCF" , rd_sae().vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6222BD78AFCF" , rz_sae().vfnmsub213sd(xmm25, xmm8, xmm23)); + TEST_INSTRUCTION("6262BD08AF09" , vfnmsub213sd(xmm25, xmm8, qword_ptr(rcx))); + TEST_INSTRUCTION("6222BD08AF8CF034120000" , vfnmsub213sd(xmm25, xmm8, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262BD08AF4A7F" , vfnmsub213sd(xmm25, xmm8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262BD08AF8A00040000" , vfnmsub213sd(xmm25, xmm8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262BD08AF4A80" , vfnmsub213sd(xmm25, xmm8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262BD08AF8AF8FBFFFF" , vfnmsub213sd(xmm25, xmm8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62425D00AFC7" , vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62425D06AFC7" , k(k6).vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62425D86AFC7" , k(k6).z().vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62425D10AFC7" , rn_sae().vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62425D50AFC7" , ru_sae().vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62425D30AFC7" , rd_sae().vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62425D70AFC7" , rz_sae().vfnmsub213ss(xmm24, xmm20, xmm15)); + TEST_INSTRUCTION("62625D00AF01" , vfnmsub213ss(xmm24, xmm20, dword_ptr(rcx))); + TEST_INSTRUCTION("62225D00AF84F034120000" , vfnmsub213ss(xmm24, xmm20, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62625D00AF427F" , vfnmsub213ss(xmm24, xmm20, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62625D00AF8200020000" , vfnmsub213ss(xmm24, xmm20, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62625D00AF4280" , vfnmsub213ss(xmm24, xmm20, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62625D00AF82FCFDFFFF" , vfnmsub213ss(xmm24, xmm20, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62D2AD48BECC" , vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62D2AD4DBECC" , k(k5).vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62D2ADCDBECC" , k(k5).z().vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62D2AD18BECC" , rn_sae().vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62D2AD58BECC" , ru_sae().vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62D2AD38BECC" , rd_sae().vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62D2AD78BECC" , rz_sae().vfnmsub231pd(zmm1, zmm10, zmm12)); + TEST_INSTRUCTION("62F2AD48BE09" , vfnmsub231pd(zmm1, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2AD48BE8CF034120000" , vfnmsub231pd(zmm1, zmm10, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2AD58BE09" , vfnmsub231pd(zmm1, zmm10, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2AD48BE4A7F" , vfnmsub231pd(zmm1, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2AD48BE8A00200000" , vfnmsub231pd(zmm1, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2AD48BE4A80" , vfnmsub231pd(zmm1, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2AD48BE8AC0DFFFFF" , vfnmsub231pd(zmm1, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2AD58BE4A7F" , vfnmsub231pd(zmm1, zmm10, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2AD58BE8A00040000" , vfnmsub231pd(zmm1, zmm10, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2AD58BE4A80" , vfnmsub231pd(zmm1, zmm10, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2AD58BE8AF8FBFFFF" , vfnmsub231pd(zmm1, zmm10, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62A22D40BECB" , vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62A22D44BECB" , k(k4).vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62A22DC4BECB" , k(k4).z().vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62A22D10BECB" , rn_sae().vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62A22D50BECB" , ru_sae().vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62A22D30BECB" , rd_sae().vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62A22D70BECB" , rz_sae().vfnmsub231ps(zmm17, zmm26, zmm19)); + TEST_INSTRUCTION("62E22D40BE09" , vfnmsub231ps(zmm17, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A22D40BE8CF034120000" , vfnmsub231ps(zmm17, zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E22D50BE09" , vfnmsub231ps(zmm17, zmm26, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E22D40BE4A7F" , vfnmsub231ps(zmm17, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E22D40BE8A00200000" , vfnmsub231ps(zmm17, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E22D40BE4A80" , vfnmsub231ps(zmm17, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E22D40BE8AC0DFFFFF" , vfnmsub231ps(zmm17, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E22D50BE4A7F" , vfnmsub231ps(zmm17, zmm26, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E22D50BE8A00020000" , vfnmsub231ps(zmm17, zmm26, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E22D50BE4A80" , vfnmsub231ps(zmm17, zmm26, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E22D50BE8AFCFDFFFF" , vfnmsub231ps(zmm17, zmm26, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6282CD08BFDA" , vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("6282CD0FBFDA" , k(k7).vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("6282CD8FBFDA" , k(k7).z().vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("6282CD18BFDA" , rn_sae().vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("6282CD58BFDA" , ru_sae().vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("6282CD38BFDA" , rd_sae().vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("6282CD78BFDA" , rz_sae().vfnmsub231sd(xmm19, xmm6, xmm26)); + TEST_INSTRUCTION("62E2CD08BF19" , vfnmsub231sd(xmm19, xmm6, qword_ptr(rcx))); + TEST_INSTRUCTION("62A2CD08BF9CF034120000" , vfnmsub231sd(xmm19, xmm6, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2CD08BF5A7F" , vfnmsub231sd(xmm19, xmm6, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E2CD08BF9A00040000" , vfnmsub231sd(xmm19, xmm6, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E2CD08BF5A80" , vfnmsub231sd(xmm19, xmm6, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E2CD08BF9AF8FBFFFF" , vfnmsub231sd(xmm19, xmm6, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62726D00BFE9" , vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D05BFE9" , k(k5).vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D85BFE9" , k(k5).z().vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D10BFE9" , rn_sae().vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D50BFE9" , ru_sae().vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D30BFE9" , rd_sae().vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D70BFE9" , rz_sae().vfnmsub231ss(xmm13, xmm18, xmm1)); + TEST_INSTRUCTION("62726D00BF29" , vfnmsub231ss(xmm13, xmm18, dword_ptr(rcx))); + TEST_INSTRUCTION("62326D00BFACF034120000" , vfnmsub231ss(xmm13, xmm18, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62726D00BF6A7F" , vfnmsub231ss(xmm13, xmm18, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62726D00BFAA00020000" , vfnmsub231ss(xmm13, xmm18, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62726D00BF6A80" , vfnmsub231ss(xmm13, xmm18, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62726D00BFAAFCFDFFFF" , vfnmsub231ss(xmm13, xmm18, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6292FD4842F1" , vgetexppd(zmm6, zmm25)); + TEST_INSTRUCTION("6292FD4B42F1" , k(k3).vgetexppd(zmm6, zmm25)); + TEST_INSTRUCTION("6292FDCB42F1" , k(k3).z().vgetexppd(zmm6, zmm25)); + TEST_INSTRUCTION("6292FD1842F1" , sae().vgetexppd(zmm6, zmm25)); + TEST_INSTRUCTION("62F2FD484231" , vgetexppd(zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2FD4842B4F034120000" , vgetexppd(zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2FD584231" , vgetexppd(zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2FD4842727F" , vgetexppd(zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2FD4842B200200000" , vgetexppd(zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2FD48427280" , vgetexppd(zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2FD4842B2C0DFFFFF" , vgetexppd(zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2FD5842727F" , vgetexppd(zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2FD5842B200040000" , vgetexppd(zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2FD58427280" , vgetexppd(zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2FD5842B2F8FBFFFF" , vgetexppd(zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B27D4842F8" , vgetexpps(zmm7, zmm16)); + TEST_INSTRUCTION("62B27D4A42F8" , k(k2).vgetexpps(zmm7, zmm16)); + TEST_INSTRUCTION("62B27DCA42F8" , k(k2).z().vgetexpps(zmm7, zmm16)); + TEST_INSTRUCTION("62B27D1842F8" , sae().vgetexpps(zmm7, zmm16)); + TEST_INSTRUCTION("62F27D484239" , vgetexpps(zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D4842BCF034120000" , vgetexpps(zmm7, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D584239" , vgetexpps(zmm7, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27D48427A7F" , vgetexpps(zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27D4842BA00200000" , vgetexpps(zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27D48427A80" , vgetexpps(zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27D4842BAC0DFFFFF" , vgetexpps(zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27D58427A7F" , vgetexpps(zmm7, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27D5842BA00020000" , vgetexpps(zmm7, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27D58427A80" , vgetexpps(zmm7, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27D5842BAFCFDFFFF" , vgetexpps(zmm7, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62728D0843D5" , vgetexpsd(xmm10, xmm14, xmm5)); + TEST_INSTRUCTION("62728D0C43D5" , k(k4).vgetexpsd(xmm10, xmm14, xmm5)); + TEST_INSTRUCTION("62728D8C43D5" , k(k4).z().vgetexpsd(xmm10, xmm14, xmm5)); + TEST_INSTRUCTION("62728D1843D5" , sae().vgetexpsd(xmm10, xmm14, xmm5)); + TEST_INSTRUCTION("62728D084311" , vgetexpsd(xmm10, xmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("62328D084394F034120000" , vgetexpsd(xmm10, xmm14, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62728D0843527F" , vgetexpsd(xmm10, xmm14, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62728D08439200040000" , vgetexpsd(xmm10, xmm14, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62728D08435280" , vgetexpsd(xmm10, xmm14, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62728D084392F8FBFFFF" , vgetexpsd(xmm10, xmm14, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62A2550043C7" , vgetexpss(xmm16, xmm21, xmm23)); + TEST_INSTRUCTION("62A2550243C7" , k(k2).vgetexpss(xmm16, xmm21, xmm23)); + TEST_INSTRUCTION("62A2558243C7" , k(k2).z().vgetexpss(xmm16, xmm21, xmm23)); + TEST_INSTRUCTION("62A2551043C7" , sae().vgetexpss(xmm16, xmm21, xmm23)); + TEST_INSTRUCTION("62E255004301" , vgetexpss(xmm16, xmm21, dword_ptr(rcx))); + TEST_INSTRUCTION("62A255004384F034120000" , vgetexpss(xmm16, xmm21, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2550043427F" , vgetexpss(xmm16, xmm21, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E25500438200020000" , vgetexpss(xmm16, xmm21, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E25500434280" , vgetexpss(xmm16, xmm21, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E255004382FCFDFFFF" , vgetexpss(xmm16, xmm21, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6253FD4826CAAB" , vgetmantpd(zmm9, zmm10, 171)); + TEST_INSTRUCTION("6253FD4D26CAAB" , k(k5).vgetmantpd(zmm9, zmm10, 171)); + TEST_INSTRUCTION("6253FDCD26CAAB" , k(k5).z().vgetmantpd(zmm9, zmm10, 171)); + TEST_INSTRUCTION("6253FD1826CAAB" , sae().vgetmantpd(zmm9, zmm10, 171)); + TEST_INSTRUCTION("6253FD4826CA7B" , vgetmantpd(zmm9, zmm10, 123)); + TEST_INSTRUCTION("6253FD1826CA7B" , sae().vgetmantpd(zmm9, zmm10, 123)); + TEST_INSTRUCTION("6273FD4826097B" , vgetmantpd(zmm9, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233FD48268CF0341200007B" , vgetmantpd(zmm9, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6273FD5826097B" , vgetmantpd(zmm9, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273FD48264A7F7B" , vgetmantpd(zmm9, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273FD48268A002000007B" , vgetmantpd(zmm9, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273FD48264A807B" , vgetmantpd(zmm9, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273FD48268AC0DFFFFF7B" , vgetmantpd(zmm9, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273FD58264A7F7B" , vgetmantpd(zmm9, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273FD58268A000400007B" , vgetmantpd(zmm9, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273FD58264A807B" , vgetmantpd(zmm9, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273FD58268AF8FBFFFF7B" , vgetmantpd(zmm9, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62037D4826E9AB" , vgetmantps(zmm29, zmm25, 171)); + TEST_INSTRUCTION("62037D4B26E9AB" , k(k3).vgetmantps(zmm29, zmm25, 171)); + TEST_INSTRUCTION("62037DCB26E9AB" , k(k3).z().vgetmantps(zmm29, zmm25, 171)); + TEST_INSTRUCTION("62037D1826E9AB" , sae().vgetmantps(zmm29, zmm25, 171)); + TEST_INSTRUCTION("62037D4826E97B" , vgetmantps(zmm29, zmm25, 123)); + TEST_INSTRUCTION("62037D1826E97B" , sae().vgetmantps(zmm29, zmm25, 123)); + TEST_INSTRUCTION("62637D4826297B" , vgetmantps(zmm29, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62237D4826ACF0341200007B" , vgetmantps(zmm29, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62637D5826297B" , vgetmantps(zmm29, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62637D48266A7F7B" , vgetmantps(zmm29, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62637D4826AA002000007B" , vgetmantps(zmm29, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62637D48266A807B" , vgetmantps(zmm29, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62637D4826AAC0DFFFFF7B" , vgetmantps(zmm29, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62637D58266A7F7B" , vgetmantps(zmm29, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62637D5826AA000200007B" , vgetmantps(zmm29, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62637D58266A807B" , vgetmantps(zmm29, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62637D5826AAFCFDFFFF7B" , vgetmantps(zmm29, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62A3E50827E1AB" , vgetmantsd(xmm20, xmm3, xmm17, 171)); + TEST_INSTRUCTION("62A3E50F27E1AB" , k(k7).vgetmantsd(xmm20, xmm3, xmm17, 171)); + TEST_INSTRUCTION("62A3E58F27E1AB" , k(k7).z().vgetmantsd(xmm20, xmm3, xmm17, 171)); + TEST_INSTRUCTION("62A3E51827E1AB" , sae().vgetmantsd(xmm20, xmm3, xmm17, 171)); + TEST_INSTRUCTION("62A3E50827E17B" , vgetmantsd(xmm20, xmm3, xmm17, 123)); + TEST_INSTRUCTION("62A3E51827E17B" , sae().vgetmantsd(xmm20, xmm3, xmm17, 123)); + TEST_INSTRUCTION("62E3E50827217B" , vgetmantsd(xmm20, xmm3, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A3E50827A4F0341200007B" , vgetmantsd(xmm20, xmm3, qword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62E3E50827627F7B" , vgetmantsd(xmm20, xmm3, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("62E3E50827A2000400007B" , vgetmantsd(xmm20, xmm3, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("62E3E5082762807B" , vgetmantsd(xmm20, xmm3, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("62E3E50827A2F8FBFFFF7B" , vgetmantsd(xmm20, xmm3, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62731D0827EEAB" , vgetmantss(xmm13, xmm12, xmm6, 171)); + TEST_INSTRUCTION("62731D0A27EEAB" , k(k2).vgetmantss(xmm13, xmm12, xmm6, 171)); + TEST_INSTRUCTION("62731D8A27EEAB" , k(k2).z().vgetmantss(xmm13, xmm12, xmm6, 171)); + TEST_INSTRUCTION("62731D1827EEAB" , sae().vgetmantss(xmm13, xmm12, xmm6, 171)); + TEST_INSTRUCTION("62731D0827EE7B" , vgetmantss(xmm13, xmm12, xmm6, 123)); + TEST_INSTRUCTION("62731D1827EE7B" , sae().vgetmantss(xmm13, xmm12, xmm6, 123)); + TEST_INSTRUCTION("62731D0827297B" , vgetmantss(xmm13, xmm12, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62331D0827ACF0341200007B" , vgetmantss(xmm13, xmm12, dword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62731D08276A7F7B" , vgetmantss(xmm13, xmm12, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62731D0827AA000200007B" , vgetmantss(xmm13, xmm12, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62731D08276A807B" , vgetmantss(xmm13, xmm12, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62731D0827AAFCFDFFFF7B" , vgetmantss(xmm13, xmm12, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62337D4018C6AB" , vinsertf32x4(zmm8, zmm16, xmm22, 171)); + TEST_INSTRUCTION("62337D4518C6AB" , k(k5).vinsertf32x4(zmm8, zmm16, xmm22, 171)); + TEST_INSTRUCTION("62337DC518C6AB" , k(k5).z().vinsertf32x4(zmm8, zmm16, xmm22, 171)); + TEST_INSTRUCTION("62337D4018C67B" , vinsertf32x4(zmm8, zmm16, xmm22, 123)); + TEST_INSTRUCTION("62737D4018017B" , vinsertf32x4(zmm8, zmm16, xmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62337D401884F0341200007B" , vinsertf32x4(zmm8, zmm16, xmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62737D4018427F7B" , vinsertf32x4(zmm8, zmm16, xmmword_ptr(rdx, 2032), 123)); + TEST_INSTRUCTION("62737D401882000800007B" , vinsertf32x4(zmm8, zmm16, xmmword_ptr(rdx, 2048), 123)); + TEST_INSTRUCTION("62737D401842807B" , vinsertf32x4(zmm8, zmm16, xmmword_ptr(rdx, -2048), 123)); + TEST_INSTRUCTION("62737D401882F0F7FFFF7B" , vinsertf32x4(zmm8, zmm16, xmmword_ptr(rdx, -2064), 123)); + TEST_INSTRUCTION("62C3B5481AF4AB" , vinsertf64x4(zmm22, zmm9, ymm12, 171)); + TEST_INSTRUCTION("62C3B54E1AF4AB" , k(k6).vinsertf64x4(zmm22, zmm9, ymm12, 171)); + TEST_INSTRUCTION("62C3B5CE1AF4AB" , k(k6).z().vinsertf64x4(zmm22, zmm9, ymm12, 171)); + TEST_INSTRUCTION("62C3B5481AF47B" , vinsertf64x4(zmm22, zmm9, ymm12, 123)); + TEST_INSTRUCTION("62E3B5481A317B" , vinsertf64x4(zmm22, zmm9, ymmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A3B5481AB4F0341200007B" , vinsertf64x4(zmm22, zmm9, ymmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62E3B5481A727F7B" , vinsertf64x4(zmm22, zmm9, ymmword_ptr(rdx, 4064), 123)); + TEST_INSTRUCTION("62E3B5481AB2001000007B" , vinsertf64x4(zmm22, zmm9, ymmword_ptr(rdx, 4096), 123)); + TEST_INSTRUCTION("62E3B5481A72807B" , vinsertf64x4(zmm22, zmm9, ymmword_ptr(rdx, -4096), 123)); + TEST_INSTRUCTION("62E3B5481AB2E0EFFFFF7B" , vinsertf64x4(zmm22, zmm9, ymmword_ptr(rdx, -4128), 123)); + TEST_INSTRUCTION("62935D4838F8AB" , vinserti32x4(zmm7, zmm4, xmm24, 171)); + TEST_INSTRUCTION("62935D4F38F8AB" , k(k7).vinserti32x4(zmm7, zmm4, xmm24, 171)); + TEST_INSTRUCTION("62935DCF38F8AB" , k(k7).z().vinserti32x4(zmm7, zmm4, xmm24, 171)); + TEST_INSTRUCTION("62935D4838F87B" , vinserti32x4(zmm7, zmm4, xmm24, 123)); + TEST_INSTRUCTION("62F35D4838397B" , vinserti32x4(zmm7, zmm4, xmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B35D4838BCF0341200007B" , vinserti32x4(zmm7, zmm4, xmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F35D48387A7F7B" , vinserti32x4(zmm7, zmm4, xmmword_ptr(rdx, 2032), 123)); + TEST_INSTRUCTION("62F35D4838BA000800007B" , vinserti32x4(zmm7, zmm4, xmmword_ptr(rdx, 2048), 123)); + TEST_INSTRUCTION("62F35D48387A807B" , vinserti32x4(zmm7, zmm4, xmmword_ptr(rdx, -2048), 123)); + TEST_INSTRUCTION("62F35D4838BAF0F7FFFF7B" , vinserti32x4(zmm7, zmm4, xmmword_ptr(rdx, -2064), 123)); + TEST_INSTRUCTION("62A3D5483AD7AB" , vinserti64x4(zmm18, zmm5, ymm23, 171)); + TEST_INSTRUCTION("62A3D54A3AD7AB" , k(k2).vinserti64x4(zmm18, zmm5, ymm23, 171)); + TEST_INSTRUCTION("62A3D5CA3AD7AB" , k(k2).z().vinserti64x4(zmm18, zmm5, ymm23, 171)); + TEST_INSTRUCTION("62A3D5483AD77B" , vinserti64x4(zmm18, zmm5, ymm23, 123)); + TEST_INSTRUCTION("62E3D5483A117B" , vinserti64x4(zmm18, zmm5, ymmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A3D5483A94F0341200007B" , vinserti64x4(zmm18, zmm5, ymmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62E3D5483A527F7B" , vinserti64x4(zmm18, zmm5, ymmword_ptr(rdx, 4064), 123)); + TEST_INSTRUCTION("62E3D5483A92001000007B" , vinserti64x4(zmm18, zmm5, ymmword_ptr(rdx, 4096), 123)); + TEST_INSTRUCTION("62E3D5483A52807B" , vinserti64x4(zmm18, zmm5, ymmword_ptr(rdx, -4096), 123)); + TEST_INSTRUCTION("62E3D5483A92E0EFFFFF7B" , vinserti64x4(zmm18, zmm5, ymmword_ptr(rdx, -4128), 123)); + TEST_INSTRUCTION("62034D0821C4AB" , vinsertps(xmm24, xmm6, xmm28, 171)); + TEST_INSTRUCTION("62034D0821C47B" , vinsertps(xmm24, xmm6, xmm28, 123)); + TEST_INSTRUCTION("62634D0821017B" , vinsertps(xmm24, xmm6, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62234D082184F0341200007B" , vinsertps(xmm24, xmm6, dword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62634D0821427F7B" , vinsertps(xmm24, xmm6, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62634D082182000200007B" , vinsertps(xmm24, xmm6, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62634D082142807B" , vinsertps(xmm24, xmm6, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62634D082182FCFDFFFF7B" , vinsertps(xmm24, xmm6, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62319D485FCD" , vmaxpd(zmm9, zmm12, zmm21)); + TEST_INSTRUCTION("62319D4E5FCD" , k(k6).vmaxpd(zmm9, zmm12, zmm21)); + TEST_INSTRUCTION("62319DCE5FCD" , k(k6).z().vmaxpd(zmm9, zmm12, zmm21)); + TEST_INSTRUCTION("62319D185FCD" , sae().vmaxpd(zmm9, zmm12, zmm21)); + TEST_INSTRUCTION("62719D485F09" , vmaxpd(zmm9, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62319D485F8CF034120000" , vmaxpd(zmm9, zmm12, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62719D585F09" , vmaxpd(zmm9, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62719D485F4A7F" , vmaxpd(zmm9, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62719D485F8A00200000" , vmaxpd(zmm9, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62719D485F4A80" , vmaxpd(zmm9, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62719D485F8AC0DFFFFF" , vmaxpd(zmm9, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62719D585F4A7F" , vmaxpd(zmm9, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62719D585F8A00040000" , vmaxpd(zmm9, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62719D585F4A80" , vmaxpd(zmm9, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62719D585F8AF8FBFFFF" , vmaxpd(zmm9, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62813C405FC8" , vmaxps(zmm17, zmm24, zmm24)); + TEST_INSTRUCTION("62813C445FC8" , k(k4).vmaxps(zmm17, zmm24, zmm24)); + TEST_INSTRUCTION("62813CC45FC8" , k(k4).z().vmaxps(zmm17, zmm24, zmm24)); + TEST_INSTRUCTION("62813C105FC8" , sae().vmaxps(zmm17, zmm24, zmm24)); + TEST_INSTRUCTION("62E13C405F09" , vmaxps(zmm17, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A13C405F8CF034120000" , vmaxps(zmm17, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E13C505F09" , vmaxps(zmm17, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E13C405F4A7F" , vmaxps(zmm17, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E13C405F8A00200000" , vmaxps(zmm17, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E13C405F4A80" , vmaxps(zmm17, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E13C405F8AC0DFFFFF" , vmaxps(zmm17, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E13C505F4A7F" , vmaxps(zmm17, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E13C505F8A00020000" , vmaxps(zmm17, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E13C505F4A80" , vmaxps(zmm17, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E13C505F8AFCFDFFFF" , vmaxps(zmm17, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A1D7005FF8" , vmaxsd(xmm23, xmm21, xmm16)); + TEST_INSTRUCTION("62A1D7035FF8" , k(k3).vmaxsd(xmm23, xmm21, xmm16)); + TEST_INSTRUCTION("62A1D7835FF8" , k(k3).z().vmaxsd(xmm23, xmm21, xmm16)); + TEST_INSTRUCTION("62A1D7105FF8" , sae().vmaxsd(xmm23, xmm21, xmm16)); + TEST_INSTRUCTION("62E1D7005F39" , vmaxsd(xmm23, xmm21, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1D7005FBCF034120000" , vmaxsd(xmm23, xmm21, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1D7005F7A7F" , vmaxsd(xmm23, xmm21, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1D7005FBA00040000" , vmaxsd(xmm23, xmm21, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1D7005F7A80" , vmaxsd(xmm23, xmm21, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1D7005FBAF8FBFFFF" , vmaxsd(xmm23, xmm21, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62A176005FF0" , vmaxss(xmm22, xmm17, xmm16)); + TEST_INSTRUCTION("62A176075FF0" , k(k7).vmaxss(xmm22, xmm17, xmm16)); + TEST_INSTRUCTION("62A176875FF0" , k(k7).z().vmaxss(xmm22, xmm17, xmm16)); + TEST_INSTRUCTION("62A176105FF0" , sae().vmaxss(xmm22, xmm17, xmm16)); + TEST_INSTRUCTION("62E176005F31" , vmaxss(xmm22, xmm17, dword_ptr(rcx))); + TEST_INSTRUCTION("62A176005FB4F034120000" , vmaxss(xmm22, xmm17, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E176005F727F" , vmaxss(xmm22, xmm17, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E176005FB200020000" , vmaxss(xmm22, xmm17, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E176005F7280" , vmaxss(xmm22, xmm17, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E176005FB2FCFDFFFF" , vmaxss(xmm22, xmm17, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6211B5405DD3" , vminpd(zmm10, zmm25, zmm27)); + TEST_INSTRUCTION("6211B5445DD3" , k(k4).vminpd(zmm10, zmm25, zmm27)); + TEST_INSTRUCTION("6211B5C45DD3" , k(k4).z().vminpd(zmm10, zmm25, zmm27)); + TEST_INSTRUCTION("6211B5105DD3" , sae().vminpd(zmm10, zmm25, zmm27)); + TEST_INSTRUCTION("6271B5405D11" , vminpd(zmm10, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231B5405D94F034120000" , vminpd(zmm10, zmm25, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271B5505D11" , vminpd(zmm10, zmm25, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271B5405D527F" , vminpd(zmm10, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271B5405D9200200000" , vminpd(zmm10, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271B5405D5280" , vminpd(zmm10, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271B5405D92C0DFFFFF" , vminpd(zmm10, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271B5505D527F" , vminpd(zmm10, zmm25, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271B5505D9200040000" , vminpd(zmm10, zmm25, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271B5505D5280" , vminpd(zmm10, zmm25, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271B5505D92F8FBFFFF" , vminpd(zmm10, zmm25, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B10C485DD8" , vminps(zmm3, zmm14, zmm16)); + TEST_INSTRUCTION("62B10C4F5DD8" , k(k7).vminps(zmm3, zmm14, zmm16)); + TEST_INSTRUCTION("62B10CCF5DD8" , k(k7).z().vminps(zmm3, zmm14, zmm16)); + TEST_INSTRUCTION("62B10C185DD8" , sae().vminps(zmm3, zmm14, zmm16)); + TEST_INSTRUCTION("62F10C485D19" , vminps(zmm3, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B10C485D9CF034120000" , vminps(zmm3, zmm14, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F10C585D19" , vminps(zmm3, zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F10C485D5A7F" , vminps(zmm3, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F10C485D9A00200000" , vminps(zmm3, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F10C485D5A80" , vminps(zmm3, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F10C485D9AC0DFFFFF" , vminps(zmm3, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F10C585D5A7F" , vminps(zmm3, zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F10C585D9A00020000" , vminps(zmm3, zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F10C585D5A80" , vminps(zmm3, zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F10C585D9AFCFDFFFF" , vminps(zmm3, zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6211F7085DD4" , vminsd(xmm10, xmm1, xmm28)); + TEST_INSTRUCTION("6211F70A5DD4" , k(k2).vminsd(xmm10, xmm1, xmm28)); + TEST_INSTRUCTION("6211F78A5DD4" , k(k2).z().vminsd(xmm10, xmm1, xmm28)); + TEST_INSTRUCTION("6211F7185DD4" , sae().vminsd(xmm10, xmm1, xmm28)); + TEST_INSTRUCTION("C5735D11" , vminsd(xmm10, xmm1, qword_ptr(rcx))); + TEST_INSTRUCTION("C421735D94F034120000" , vminsd(xmm10, xmm1, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5735D92F8030000" , vminsd(xmm10, xmm1, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C5735D9200040000" , vminsd(xmm10, xmm1, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C5735D9200FCFFFF" , vminsd(xmm10, xmm1, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C5735D92F8FBFFFF" , vminsd(xmm10, xmm1, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("624156085DE0" , vminss(xmm28, xmm5, xmm8)); + TEST_INSTRUCTION("6241560C5DE0" , k(k4).vminss(xmm28, xmm5, xmm8)); + TEST_INSTRUCTION("6241568C5DE0" , k(k4).z().vminss(xmm28, xmm5, xmm8)); + TEST_INSTRUCTION("624156185DE0" , sae().vminss(xmm28, xmm5, xmm8)); + TEST_INSTRUCTION("626156085D21" , vminss(xmm28, xmm5, dword_ptr(rcx))); + TEST_INSTRUCTION("622156085DA4F034120000" , vminss(xmm28, xmm5, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626156085D627F" , vminss(xmm28, xmm5, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("626156085DA200020000" , vminss(xmm28, xmm5, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("626156085D6280" , vminss(xmm28, xmm5, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("626156085DA2FCFDFFFF" , vminss(xmm28, xmm5, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C1FD4828F9" , vmovapd(zmm23, zmm9)); + TEST_INSTRUCTION("62C1FD4D28F9" , k(k5).vmovapd(zmm23, zmm9)); + TEST_INSTRUCTION("62C1FDCD28F9" , k(k5).z().vmovapd(zmm23, zmm9)); + TEST_INSTRUCTION("62E1FD482839" , vmovapd(zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD4828BCF034120000" , vmovapd(zmm23, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1FD48287A7F" , vmovapd(zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FD4828BA00200000" , vmovapd(zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FD48287A80" , vmovapd(zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FD4828BAC0DFFFFF" , vmovapd(zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62417C4828D3" , vmovaps(zmm26, zmm11)); + TEST_INSTRUCTION("62417C4F28D3" , k(k7).vmovaps(zmm26, zmm11)); + TEST_INSTRUCTION("62417CCF28D3" , k(k7).z().vmovaps(zmm26, zmm11)); + TEST_INSTRUCTION("62617C482811" , vmovaps(zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62217C482894F034120000" , vmovaps(zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62617C4828527F" , vmovaps(zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62617C48289200200000" , vmovaps(zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62617C48285280" , vmovaps(zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62617C482892C0DFFFFF" , vmovaps(zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("C5796EF0" , vmovd(xmm14, eax)); + TEST_INSTRUCTION("C5796EF5" , vmovd(xmm14, ebp)); + TEST_INSTRUCTION("C441796EF5" , vmovd(xmm14, r13d)); + TEST_INSTRUCTION("C5796E31" , vmovd(xmm14, dword_ptr(rcx))); + TEST_INSTRUCTION("C421796EB4F034120000" , vmovd(xmm14, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5796EB2FC010000" , vmovd(xmm14, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5796EB200020000" , vmovd(xmm14, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5796EB200FEFFFF" , vmovd(xmm14, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5796EB2FCFDFFFF" , vmovd(xmm14, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("C5797E31" , vmovd(dword_ptr(rcx), xmm14)); + TEST_INSTRUCTION("C421797EB4F034120000" , vmovd(dword_ptr(rax, r14, 3, 4660), xmm14)); + TEST_INSTRUCTION("C5797EB2FC010000" , vmovd(dword_ptr(rdx, 508), xmm14)); + TEST_INSTRUCTION("C5797EB200020000" , vmovd(dword_ptr(rdx, 512), xmm14)); + TEST_INSTRUCTION("C5797EB200FEFFFF" , vmovd(dword_ptr(rdx, -512), xmm14)); + TEST_INSTRUCTION("C5797EB2FCFDFFFF" , vmovd(dword_ptr(rdx, -516), xmm14)); + TEST_INSTRUCTION("62D1FF4812CA" , vmovddup(zmm1, zmm10)); + TEST_INSTRUCTION("62D1FF4B12CA" , k(k3).vmovddup(zmm1, zmm10)); + TEST_INSTRUCTION("62D1FFCB12CA" , k(k3).z().vmovddup(zmm1, zmm10)); + TEST_INSTRUCTION("62F1FF481209" , vmovddup(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF48128CF034120000" , vmovddup(zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FF48124A7F" , vmovddup(zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1FF48128A00200000" , vmovddup(zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1FF48124A80" , vmovddup(zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1FF48128AC0DFFFFF" , vmovddup(zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62817D486FF5" , vmovdqa32(zmm22, zmm29)); + TEST_INSTRUCTION("62817D4D6FF5" , k(k5).vmovdqa32(zmm22, zmm29)); + TEST_INSTRUCTION("62817DCD6FF5" , k(k5).z().vmovdqa32(zmm22, zmm29)); + TEST_INSTRUCTION("62E17D486F31" , vmovdqa32(zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17D486FB4F034120000" , vmovdqa32(zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17D486F727F" , vmovdqa32(zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17D486FB200200000" , vmovdqa32(zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17D486F7280" , vmovdqa32(zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17D486FB2C0DFFFFF" , vmovdqa32(zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271FD486FCF" , vmovdqa64(zmm9, zmm7)); + TEST_INSTRUCTION("6271FD4A6FCF" , k(k2).vmovdqa64(zmm9, zmm7)); + TEST_INSTRUCTION("6271FDCA6FCF" , k(k2).z().vmovdqa64(zmm9, zmm7)); + TEST_INSTRUCTION("6271FD486F09" , vmovdqa64(zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231FD486F8CF034120000" , vmovdqa64(zmm9, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271FD486F4A7F" , vmovdqa64(zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271FD486F8A00200000" , vmovdqa64(zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271FD486F4A80" , vmovdqa64(zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271FD486F8AC0DFFFFF" , vmovdqa64(zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62B17E486FEE" , vmovdqu32(zmm5, zmm22)); + TEST_INSTRUCTION("62B17E4D6FEE" , k(k5).vmovdqu32(zmm5, zmm22)); + TEST_INSTRUCTION("62B17ECD6FEE" , k(k5).z().vmovdqu32(zmm5, zmm22)); + TEST_INSTRUCTION("62F17E486F29" , vmovdqu32(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17E486FACF034120000" , vmovdqu32(zmm5, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17E486F6A7F" , vmovdqu32(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17E486FAA00200000" , vmovdqu32(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17E486F6A80" , vmovdqu32(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17E486FAAC0DFFFFF" , vmovdqu32(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261FE486FE5" , vmovdqu64(zmm28, zmm5)); + TEST_INSTRUCTION("6261FE4B6FE5" , k(k3).vmovdqu64(zmm28, zmm5)); + TEST_INSTRUCTION("6261FECB6FE5" , k(k3).z().vmovdqu64(zmm28, zmm5)); + TEST_INSTRUCTION("6261FE486F21" , vmovdqu64(zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221FE486FA4F034120000" , vmovdqu64(zmm28, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261FE486F627F" , vmovdqu64(zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261FE486FA200200000" , vmovdqu64(zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261FE486F6280" , vmovdqu64(zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261FE486FA2C0DFFFFF" , vmovdqu64(zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62817C0012F1" , vmovhlps(xmm22, xmm16, xmm25)); + TEST_INSTRUCTION("6261F5081609" , vmovhpd(xmm25, xmm1, qword_ptr(rcx))); + TEST_INSTRUCTION("6221F508168CF034120000" , vmovhpd(xmm25, xmm1, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261F508164A7F" , vmovhpd(xmm25, xmm1, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261F508168A00040000" , vmovhpd(xmm25, xmm1, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6261F508164A80" , vmovhpd(xmm25, xmm1, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261F508168AF8FBFFFF" , vmovhpd(xmm25, xmm1, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C5791709" , vmovhpd(qword_ptr(rcx), xmm9)); + TEST_INSTRUCTION("C42179178CF034120000" , vmovhpd(qword_ptr(rax, r14, 3, 4660), xmm9)); + TEST_INSTRUCTION("C579178AF8030000" , vmovhpd(qword_ptr(rdx, 1016), xmm9)); + TEST_INSTRUCTION("C579178A00040000" , vmovhpd(qword_ptr(rdx, 1024), xmm9)); + TEST_INSTRUCTION("C579178A00FCFFFF" , vmovhpd(qword_ptr(rdx, -1024), xmm9)); + TEST_INSTRUCTION("C579178AF8FBFFFF" , vmovhpd(qword_ptr(rdx, -1032), xmm9)); + TEST_INSTRUCTION("626174001621" , vmovhps(xmm28, xmm17, qword_ptr(rcx))); + TEST_INSTRUCTION("6221740016A4F034120000" , vmovhps(xmm28, xmm17, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261740016627F" , vmovhps(xmm28, xmm17, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261740016A200040000" , vmovhps(xmm28, xmm17, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62617400166280" , vmovhps(xmm28, xmm17, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261740016A2F8FBFFFF" , vmovhps(xmm28, xmm17, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C5781729" , vmovhps(qword_ptr(rcx), xmm13)); + TEST_INSTRUCTION("C4217817ACF034120000" , vmovhps(qword_ptr(rax, r14, 3, 4660), xmm13)); + TEST_INSTRUCTION("C57817AAF8030000" , vmovhps(qword_ptr(rdx, 1016), xmm13)); + TEST_INSTRUCTION("C57817AA00040000" , vmovhps(qword_ptr(rdx, 1024), xmm13)); + TEST_INSTRUCTION("C57817AA00FCFFFF" , vmovhps(qword_ptr(rdx, -1024), xmm13)); + TEST_INSTRUCTION("C57817AAF8FBFFFF" , vmovhps(qword_ptr(rdx, -1032), xmm13)); + TEST_INSTRUCTION("C59816F6" , vmovlhps(xmm6, xmm12, xmm6)); + TEST_INSTRUCTION("62E1DD001209" , vmovlpd(xmm17, xmm20, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1DD00128CF034120000" , vmovlpd(xmm17, xmm20, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1DD00124A7F" , vmovlpd(xmm17, xmm20, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1DD00128A00040000" , vmovlpd(xmm17, xmm20, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1DD00124A80" , vmovlpd(xmm17, xmm20, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1DD00128AF8FBFFFF" , vmovlpd(xmm17, xmm20, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("C5F91339" , vmovlpd(qword_ptr(rcx), xmm7)); + TEST_INSTRUCTION("C4A17913BCF034120000" , vmovlpd(qword_ptr(rax, r14, 3, 4660), xmm7)); + TEST_INSTRUCTION("C5F913BAF8030000" , vmovlpd(qword_ptr(rdx, 1016), xmm7)); + TEST_INSTRUCTION("C5F913BA00040000" , vmovlpd(qword_ptr(rdx, 1024), xmm7)); + TEST_INSTRUCTION("C5F913BA00FCFFFF" , vmovlpd(qword_ptr(rdx, -1024), xmm7)); + TEST_INSTRUCTION("C5F913BAF8FBFFFF" , vmovlpd(qword_ptr(rdx, -1032), xmm7)); + TEST_INSTRUCTION("C5201219" , vmovlps(xmm11, xmm11, qword_ptr(rcx))); + TEST_INSTRUCTION("C42120129CF034120000" , vmovlps(xmm11, xmm11, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C520129AF8030000" , vmovlps(xmm11, xmm11, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C520129A00040000" , vmovlps(xmm11, xmm11, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C520129A00FCFFFF" , vmovlps(xmm11, xmm11, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C520129AF8FBFFFF" , vmovlps(xmm11, xmm11, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62E17C081329" , vmovlps(qword_ptr(rcx), xmm21)); + TEST_INSTRUCTION("62A17C0813ACF034120000" , vmovlps(qword_ptr(rax, r14, 3, 4660), xmm21)); + TEST_INSTRUCTION("62E17C08136A7F" , vmovlps(qword_ptr(rdx, 1016), xmm21)); + TEST_INSTRUCTION("62E17C0813AA00040000" , vmovlps(qword_ptr(rdx, 1024), xmm21)); + TEST_INSTRUCTION("62E17C08136A80" , vmovlps(qword_ptr(rdx, -1024), xmm21)); + TEST_INSTRUCTION("62E17C0813AAF8FBFFFF" , vmovlps(qword_ptr(rdx, -1032), xmm21)); + TEST_INSTRUCTION("62E17D48E721" , vmovntdq(zmmword_ptr(rcx), zmm20)); + TEST_INSTRUCTION("62A17D48E7A4F034120000" , vmovntdq(zmmword_ptr(rax, r14, 3, 4660), zmm20)); + TEST_INSTRUCTION("62E17D48E7627F" , vmovntdq(zmmword_ptr(rdx, 8128), zmm20)); + TEST_INSTRUCTION("62E17D48E7A200200000" , vmovntdq(zmmword_ptr(rdx, 8192), zmm20)); + TEST_INSTRUCTION("62E17D48E76280" , vmovntdq(zmmword_ptr(rdx, -8192), zmm20)); + TEST_INSTRUCTION("62E17D48E7A2C0DFFFFF" , vmovntdq(zmmword_ptr(rdx, -8256), zmm20)); + TEST_INSTRUCTION("62727D482A11" , vmovntdqa(zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D482A94F034120000" , vmovntdqa(zmm10, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D482A527F" , vmovntdqa(zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62727D482A9200200000" , vmovntdqa(zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62727D482A5280" , vmovntdqa(zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62727D482A92C0DFFFFF" , vmovntdqa(zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FD482B29" , vmovntpd(zmmword_ptr(rcx), zmm21)); + TEST_INSTRUCTION("62A1FD482BACF034120000" , vmovntpd(zmmword_ptr(rax, r14, 3, 4660), zmm21)); + TEST_INSTRUCTION("62E1FD482B6A7F" , vmovntpd(zmmword_ptr(rdx, 8128), zmm21)); + TEST_INSTRUCTION("62E1FD482BAA00200000" , vmovntpd(zmmword_ptr(rdx, 8192), zmm21)); + TEST_INSTRUCTION("62E1FD482B6A80" , vmovntpd(zmmword_ptr(rdx, -8192), zmm21)); + TEST_INSTRUCTION("62E1FD482BAAC0DFFFFF" , vmovntpd(zmmword_ptr(rdx, -8256), zmm21)); + TEST_INSTRUCTION("62E17C482B39" , vmovntps(zmmword_ptr(rcx), zmm23)); + TEST_INSTRUCTION("62A17C482BBCF034120000" , vmovntps(zmmword_ptr(rax, r14, 3, 4660), zmm23)); + TEST_INSTRUCTION("62E17C482B7A7F" , vmovntps(zmmword_ptr(rdx, 8128), zmm23)); + TEST_INSTRUCTION("62E17C482BBA00200000" , vmovntps(zmmword_ptr(rdx, 8192), zmm23)); + TEST_INSTRUCTION("62E17C482B7A80" , vmovntps(zmmword_ptr(rdx, -8192), zmm23)); + TEST_INSTRUCTION("62E17C482BBAC0DFFFFF" , vmovntps(zmmword_ptr(rdx, -8256), zmm23)); + TEST_INSTRUCTION("6261FD086EC0" , vmovq(xmm24, rax)); + TEST_INSTRUCTION("6241FD086EC0" , vmovq(xmm24, r8)); + TEST_INSTRUCTION("C5FB1029" , vmovsd(xmm5, qword_ptr(rcx))); + TEST_INSTRUCTION("62F1FF0B1029" , k(k3).vmovsd(xmm5, qword_ptr(rcx))); + TEST_INSTRUCTION("62F1FF8B1029" , k(k3).z().vmovsd(xmm5, qword_ptr(rcx))); + TEST_INSTRUCTION("C4A17B10ACF034120000" , vmovsd(xmm5, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5FB10AAF8030000" , vmovsd(xmm5, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("C5FB10AA00040000" , vmovsd(xmm5, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("C5FB10AA00FCFFFF" , vmovsd(xmm5, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("C5FB10AAF8FBFFFF" , vmovsd(xmm5, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62E1FF081109" , vmovsd(qword_ptr(rcx), xmm17)); + TEST_INSTRUCTION("62E1FF0B1109" , k(k3).vmovsd(qword_ptr(rcx), xmm17)); + TEST_INSTRUCTION("62A1FF08118CF034120000" , vmovsd(qword_ptr(rax, r14, 3, 4660), xmm17)); + TEST_INSTRUCTION("62E1FF08114A7F" , vmovsd(qword_ptr(rdx, 1016), xmm17)); + TEST_INSTRUCTION("62E1FF08118A00040000" , vmovsd(qword_ptr(rdx, 1024), xmm17)); + TEST_INSTRUCTION("62E1FF08114A80" , vmovsd(qword_ptr(rdx, -1024), xmm17)); + TEST_INSTRUCTION("62E1FF08118AF8FBFFFF" , vmovsd(qword_ptr(rdx, -1032), xmm17)); + TEST_INSTRUCTION("62C1970010EC" , vmovsd(xmm21, xmm29, xmm12)); + TEST_INSTRUCTION("62C1970710EC" , k(k7).vmovsd(xmm21, xmm29, xmm12)); + TEST_INSTRUCTION("62C1978710EC" , k(k7).z().vmovsd(xmm21, xmm29, xmm12)); + TEST_INSTRUCTION("62A17E4816D4" , vmovshdup(zmm18, zmm20)); + TEST_INSTRUCTION("62A17E4D16D4" , k(k5).vmovshdup(zmm18, zmm20)); + TEST_INSTRUCTION("62A17ECD16D4" , k(k5).z().vmovshdup(zmm18, zmm20)); + TEST_INSTRUCTION("62E17E481611" , vmovshdup(zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17E481694F034120000" , vmovshdup(zmm18, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17E4816527F" , vmovshdup(zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17E48169200200000" , vmovshdup(zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17E48165280" , vmovshdup(zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17E481692C0DFFFFF" , vmovshdup(zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62717E4812CD" , vmovsldup(zmm9, zmm5)); + TEST_INSTRUCTION("62717E4F12CD" , k(k7).vmovsldup(zmm9, zmm5)); + TEST_INSTRUCTION("62717ECF12CD" , k(k7).z().vmovsldup(zmm9, zmm5)); + TEST_INSTRUCTION("62717E481209" , vmovsldup(zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62317E48128CF034120000" , vmovsldup(zmm9, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62717E48124A7F" , vmovsldup(zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62717E48128A00200000" , vmovsldup(zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62717E48124A80" , vmovsldup(zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62717E48128AC0DFFFFF" , vmovsldup(zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("C5FA1009" , vmovss(xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("62F17E0C1009" , k(k4).vmovss(xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("62F17E8C1009" , k(k4).z().vmovss(xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("C4A17A108CF034120000" , vmovss(xmm1, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5FA108AFC010000" , vmovss(xmm1, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("C5FA108A00020000" , vmovss(xmm1, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("C5FA108A00FEFFFF" , vmovss(xmm1, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("C5FA108AFCFDFFFF" , vmovss(xmm1, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("C57A1129" , vmovss(dword_ptr(rcx), xmm13)); + TEST_INSTRUCTION("62717E0A1129" , k(k2).vmovss(dword_ptr(rcx), xmm13)); + TEST_INSTRUCTION("C4217A11ACF034120000" , vmovss(dword_ptr(rax, r14, 3, 4660), xmm13)); + TEST_INSTRUCTION("C57A11AAFC010000" , vmovss(dword_ptr(rdx, 508), xmm13)); + TEST_INSTRUCTION("C57A11AA00020000" , vmovss(dword_ptr(rdx, 512), xmm13)); + TEST_INSTRUCTION("C57A11AA00FEFFFF" , vmovss(dword_ptr(rdx, -512), xmm13)); + TEST_INSTRUCTION("C57A11AAFCFDFFFF" , vmovss(dword_ptr(rdx, -516), xmm13)); + TEST_INSTRUCTION("62C1260010D6" , vmovss(xmm18, xmm27, xmm14)); + TEST_INSTRUCTION("62C1260210D6" , k(k2).vmovss(xmm18, xmm27, xmm14)); + TEST_INSTRUCTION("62C1268210D6" , k(k2).z().vmovss(xmm18, xmm27, xmm14)); + TEST_INSTRUCTION("62E1FD4810C6" , vmovupd(zmm16, zmm6)); + TEST_INSTRUCTION("62E1FD4A10C6" , k(k2).vmovupd(zmm16, zmm6)); + TEST_INSTRUCTION("62E1FDCA10C6" , k(k2).z().vmovupd(zmm16, zmm6)); + TEST_INSTRUCTION("62E1FD481001" , vmovupd(zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD481084F034120000" , vmovupd(zmm16, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1FD4810427F" , vmovupd(zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FD48108200200000" , vmovupd(zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FD48104280" , vmovupd(zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FD481082C0DFFFFF" , vmovupd(zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E17C4810F4" , vmovups(zmm22, zmm4)); + TEST_INSTRUCTION("62E17C4F10F4" , k(k7).vmovups(zmm22, zmm4)); + TEST_INSTRUCTION("62E17CCF10F4" , k(k7).z().vmovups(zmm22, zmm4)); + TEST_INSTRUCTION("62E17C481031" , vmovups(zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17C4810B4F034120000" , vmovups(zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17C4810727F" , vmovups(zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17C4810B200200000" , vmovups(zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17C48107280" , vmovups(zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17C4810B2C0DFFFFF" , vmovups(zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261B54059C5" , vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B54459C5" , k(k4).vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B5C459C5" , k(k4).z().vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B51059C5" , rn_sae().vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B55059C5" , ru_sae().vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B53059C5" , rd_sae().vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B57059C5" , rz_sae().vmulpd(zmm24, zmm25, zmm5)); + TEST_INSTRUCTION("6261B5405901" , vmulpd(zmm24, zmm25, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221B5405984F034120000" , vmulpd(zmm24, zmm25, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261B5505901" , vmulpd(zmm24, zmm25, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261B54059427F" , vmulpd(zmm24, zmm25, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261B540598200200000" , vmulpd(zmm24, zmm25, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261B540594280" , vmulpd(zmm24, zmm25, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261B5405982C0DFFFFF" , vmulpd(zmm24, zmm25, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261B55059427F" , vmulpd(zmm24, zmm25, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261B550598200040000" , vmulpd(zmm24, zmm25, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261B550594280" , vmulpd(zmm24, zmm25, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261B5505982F8FBFFFF" , vmulpd(zmm24, zmm25, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F1244059F3" , vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F1244559F3" , k(k5).vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F124C559F3" , k(k5).z().vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F1241059F3" , rn_sae().vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F1245059F3" , ru_sae().vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F1243059F3" , rd_sae().vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F1247059F3" , rz_sae().vmulps(zmm6, zmm27, zmm3)); + TEST_INSTRUCTION("62F124405931" , vmulps(zmm6, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1244059B4F034120000" , vmulps(zmm6, zmm27, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F124505931" , vmulps(zmm6, zmm27, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F1244059727F" , vmulps(zmm6, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1244059B200200000" , vmulps(zmm6, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F12440597280" , vmulps(zmm6, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1244059B2C0DFFFFF" , vmulps(zmm6, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1245059727F" , vmulps(zmm6, zmm27, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F1245059B200020000" , vmulps(zmm6, zmm27, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F12450597280" , vmulps(zmm6, zmm27, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F1245059B2FCFDFFFF" , vmulps(zmm6, zmm27, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A1970059FE" , vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62A1970559FE" , k(k5).vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62A1978559FE" , k(k5).z().vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62A1971059FE" , rn_sae().vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62A1975059FE" , ru_sae().vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62A1973059FE" , rd_sae().vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62A1977059FE" , rz_sae().vmulsd(xmm23, xmm29, xmm22)); + TEST_INSTRUCTION("62E197005939" , vmulsd(xmm23, xmm29, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1970059BCF034120000" , vmulsd(xmm23, xmm29, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E19700597A7F" , vmulsd(xmm23, xmm29, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1970059BA00040000" , vmulsd(xmm23, xmm29, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E19700597A80" , vmulsd(xmm23, xmm29, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1970059BAF8FBFFFF" , vmulsd(xmm23, xmm29, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62412E0059C8" , vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62412E0559C8" , k(k5).vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62412E8559C8" , k(k5).z().vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62412E1059C8" , rn_sae().vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62412E5059C8" , ru_sae().vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62412E3059C8" , rd_sae().vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62412E7059C8" , rz_sae().vmulss(xmm25, xmm26, xmm8)); + TEST_INSTRUCTION("62612E005909" , vmulss(xmm25, xmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62212E00598CF034120000" , vmulss(xmm25, xmm26, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62612E00594A7F" , vmulss(xmm25, xmm26, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62612E00598A00020000" , vmulss(xmm25, xmm26, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62612E00594A80" , vmulss(xmm25, xmm26, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62612E00598AFCFDFFFF" , vmulss(xmm25, xmm26, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62927D481EE5" , vpabsd(zmm4, zmm29)); + TEST_INSTRUCTION("62927D4C1EE5" , k(k4).vpabsd(zmm4, zmm29)); + TEST_INSTRUCTION("62927DCC1EE5" , k(k4).z().vpabsd(zmm4, zmm29)); + TEST_INSTRUCTION("62F27D481E21" , vpabsd(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D481EA4F034120000" , vpabsd(zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D581E21" , vpabsd(zmm4, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27D481E627F" , vpabsd(zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27D481EA200200000" , vpabsd(zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27D481E6280" , vpabsd(zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27D481EA2C0DFFFFF" , vpabsd(zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27D581E627F" , vpabsd(zmm4, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27D581EA200020000" , vpabsd(zmm4, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27D581E6280" , vpabsd(zmm4, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27D581EA2FCFDFFFF" , vpabsd(zmm4, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62E2FD481FCB" , vpabsq(zmm17, zmm3)); + TEST_INSTRUCTION("62E2FD4A1FCB" , k(k2).vpabsq(zmm17, zmm3)); + TEST_INSTRUCTION("62E2FDCA1FCB" , k(k2).z().vpabsq(zmm17, zmm3)); + TEST_INSTRUCTION("62E2FD481F09" , vpabsq(zmm17, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2FD481F8CF034120000" , vpabsq(zmm17, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2FD581F09" , vpabsq(zmm17, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2FD481F4A7F" , vpabsq(zmm17, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2FD481F8A00200000" , vpabsq(zmm17, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2FD481F4A80" , vpabsq(zmm17, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2FD481F8AC0DFFFFF" , vpabsq(zmm17, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2FD581F4A7F" , vpabsq(zmm17, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2FD581F8A00040000" , vpabsq(zmm17, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2FD581F4A80" , vpabsq(zmm17, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2FD581F8AF8FBFFFF" , vpabsq(zmm17, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62513D48FED3" , vpaddd(zmm10, zmm8, zmm11)); + TEST_INSTRUCTION("62513D4FFED3" , k(k7).vpaddd(zmm10, zmm8, zmm11)); + TEST_INSTRUCTION("62513DCFFED3" , k(k7).z().vpaddd(zmm10, zmm8, zmm11)); + TEST_INSTRUCTION("62713D48FE11" , vpaddd(zmm10, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62313D48FE94F034120000" , vpaddd(zmm10, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62713D58FE11" , vpaddd(zmm10, zmm8, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62713D48FE527F" , vpaddd(zmm10, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62713D48FE9200200000" , vpaddd(zmm10, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62713D48FE5280" , vpaddd(zmm10, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62713D48FE92C0DFFFFF" , vpaddd(zmm10, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62713D58FE527F" , vpaddd(zmm10, zmm8, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62713D58FE9200020000" , vpaddd(zmm10, zmm8, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62713D58FE5280" , vpaddd(zmm10, zmm8, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62713D58FE92FCFDFFFF" , vpaddd(zmm10, zmm8, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6291DD48D4F2" , vpaddq(zmm6, zmm4, zmm26)); + TEST_INSTRUCTION("6291DD4BD4F2" , k(k3).vpaddq(zmm6, zmm4, zmm26)); + TEST_INSTRUCTION("6291DDCBD4F2" , k(k3).z().vpaddq(zmm6, zmm4, zmm26)); + TEST_INSTRUCTION("62F1DD48D431" , vpaddq(zmm6, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1DD48D4B4F034120000" , vpaddq(zmm6, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1DD58D431" , vpaddq(zmm6, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1DD48D4727F" , vpaddq(zmm6, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1DD48D4B200200000" , vpaddq(zmm6, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1DD48D47280" , vpaddq(zmm6, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1DD48D4B2C0DFFFFF" , vpaddq(zmm6, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1DD58D4727F" , vpaddq(zmm6, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1DD58D4B200040000" , vpaddq(zmm6, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1DD58D47280" , vpaddq(zmm6, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1DD58D4B2F8FBFFFF" , vpaddq(zmm6, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B11540DBC8" , vpandd(zmm1, zmm29, zmm16)); + TEST_INSTRUCTION("62B11542DBC8" , k(k2).vpandd(zmm1, zmm29, zmm16)); + TEST_INSTRUCTION("62B115C2DBC8" , k(k2).z().vpandd(zmm1, zmm29, zmm16)); + TEST_INSTRUCTION("62F11540DB09" , vpandd(zmm1, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B11540DB8CF034120000" , vpandd(zmm1, zmm29, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F11550DB09" , vpandd(zmm1, zmm29, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F11540DB4A7F" , vpandd(zmm1, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F11540DB8A00200000" , vpandd(zmm1, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F11540DB4A80" , vpandd(zmm1, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F11540DB8AC0DFFFFF" , vpandd(zmm1, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F11550DB4A7F" , vpandd(zmm1, zmm29, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F11550DB8A00020000" , vpandd(zmm1, zmm29, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F11550DB4A80" , vpandd(zmm1, zmm29, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F11550DB8AFCFDFFFF" , vpandd(zmm1, zmm29, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A17540DFF0" , vpandnd(zmm22, zmm17, zmm16)); + TEST_INSTRUCTION("62A17545DFF0" , k(k5).vpandnd(zmm22, zmm17, zmm16)); + TEST_INSTRUCTION("62A175C5DFF0" , k(k5).z().vpandnd(zmm22, zmm17, zmm16)); + TEST_INSTRUCTION("62E17540DF31" , vpandnd(zmm22, zmm17, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A17540DFB4F034120000" , vpandnd(zmm22, zmm17, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E17550DF31" , vpandnd(zmm22, zmm17, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E17540DF727F" , vpandnd(zmm22, zmm17, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E17540DFB200200000" , vpandnd(zmm22, zmm17, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E17540DF7280" , vpandnd(zmm22, zmm17, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E17540DFB2C0DFFFFF" , vpandnd(zmm22, zmm17, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E17550DF727F" , vpandnd(zmm22, zmm17, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E17550DFB200020000" , vpandnd(zmm22, zmm17, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E17550DF7280" , vpandnd(zmm22, zmm17, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E17550DFB2FCFDFFFF" , vpandnd(zmm22, zmm17, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6261DD48DFCA" , vpandnq(zmm25, zmm4, zmm2)); + TEST_INSTRUCTION("6261DD4BDFCA" , k(k3).vpandnq(zmm25, zmm4, zmm2)); + TEST_INSTRUCTION("6261DDCBDFCA" , k(k3).z().vpandnq(zmm25, zmm4, zmm2)); + TEST_INSTRUCTION("6261DD48DF09" , vpandnq(zmm25, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6221DD48DF8CF034120000" , vpandnq(zmm25, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261DD58DF09" , vpandnq(zmm25, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6261DD48DF4A7F" , vpandnq(zmm25, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6261DD48DF8A00200000" , vpandnq(zmm25, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6261DD48DF4A80" , vpandnq(zmm25, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6261DD48DF8AC0DFFFFF" , vpandnq(zmm25, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6261DD58DF4A7F" , vpandnq(zmm25, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6261DD58DF8A00040000" , vpandnq(zmm25, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6261DD58DF4A80" , vpandnq(zmm25, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6261DD58DF8AF8FBFFFF" , vpandnq(zmm25, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62419D48DBD9" , vpandq(zmm27, zmm12, zmm9)); + TEST_INSTRUCTION("62419D4ADBD9" , k(k2).vpandq(zmm27, zmm12, zmm9)); + TEST_INSTRUCTION("62419DCADBD9" , k(k2).z().vpandq(zmm27, zmm12, zmm9)); + TEST_INSTRUCTION("62619D48DB19" , vpandq(zmm27, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62219D48DB9CF034120000" , vpandq(zmm27, zmm12, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62619D58DB19" , vpandq(zmm27, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62619D48DB5A7F" , vpandq(zmm27, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62619D48DB9A00200000" , vpandq(zmm27, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62619D48DB5A80" , vpandq(zmm27, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62619D48DB9AC0DFFFFF" , vpandq(zmm27, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62619D58DB5A7F" , vpandq(zmm27, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62619D58DB9A00040000" , vpandq(zmm27, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62619D58DB5A80" , vpandq(zmm27, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62619D58DB9AF8FBFFFF" , vpandq(zmm27, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C23D4064FC" , vpblendmd(zmm23, zmm24, zmm12)); + TEST_INSTRUCTION("62C23D4164FC" , k(k1).vpblendmd(zmm23, zmm24, zmm12)); + TEST_INSTRUCTION("62C23DC164FC" , k(k1).z().vpblendmd(zmm23, zmm24, zmm12)); + TEST_INSTRUCTION("62E23D406439" , vpblendmd(zmm23, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A23D4064BCF034120000" , vpblendmd(zmm23, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E23D506439" , vpblendmd(zmm23, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E23D40647A7F" , vpblendmd(zmm23, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E23D4064BA00200000" , vpblendmd(zmm23, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E23D40647A80" , vpblendmd(zmm23, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E23D4064BAC0DFFFFF" , vpblendmd(zmm23, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E23D50647A7F" , vpblendmd(zmm23, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E23D5064BA00020000" , vpblendmd(zmm23, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E23D50647A80" , vpblendmd(zmm23, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E23D5064BAFCFDFFFF" , vpblendmd(zmm23, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62E27D485819" , vpbroadcastd(zmm19, dword_ptr(rcx))); + TEST_INSTRUCTION("62E27D4D5819" , k(k5).vpbroadcastd(zmm19, dword_ptr(rcx))); + TEST_INSTRUCTION("62E27DCD5819" , k(k5).z().vpbroadcastd(zmm19, dword_ptr(rcx))); + TEST_INSTRUCTION("62A27D48589CF034120000" , vpbroadcastd(zmm19, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E27D48585A7F" , vpbroadcastd(zmm19, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E27D48589A00020000" , vpbroadcastd(zmm19, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E27D48585A80" , vpbroadcastd(zmm19, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E27D48589AFCFDFFFF" , vpbroadcastd(zmm19, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F27D4858D9" , vpbroadcastd(zmm3, xmm1)); + TEST_INSTRUCTION("62F27D4E58D9" , k(k6).vpbroadcastd(zmm3, xmm1)); + TEST_INSTRUCTION("62F27DCE58D9" , k(k6).z().vpbroadcastd(zmm3, xmm1)); + TEST_INSTRUCTION("62727D487CC0" , vpbroadcastd(zmm8, eax)); + TEST_INSTRUCTION("62727D4B7CC0" , k(k3).vpbroadcastd(zmm8, eax)); + TEST_INSTRUCTION("62727DCB7CC0" , k(k3).z().vpbroadcastd(zmm8, eax)); + TEST_INSTRUCTION("62727D487CC5" , vpbroadcastd(zmm8, ebp)); + TEST_INSTRUCTION("62527D487CC5" , vpbroadcastd(zmm8, r13d)); + TEST_INSTRUCTION("6272FD485931" , vpbroadcastq(zmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("6272FD4D5931" , k(k5).vpbroadcastq(zmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("6272FDCD5931" , k(k5).z().vpbroadcastq(zmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("6232FD4859B4F034120000" , vpbroadcastq(zmm14, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272FD4859727F" , vpbroadcastq(zmm14, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6272FD4859B200040000" , vpbroadcastq(zmm14, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6272FD48597280" , vpbroadcastq(zmm14, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6272FD4859B2F8FBFFFF" , vpbroadcastq(zmm14, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6272FD4859C4" , vpbroadcastq(zmm8, xmm4)); + TEST_INSTRUCTION("6272FD4B59C4" , k(k3).vpbroadcastq(zmm8, xmm4)); + TEST_INSTRUCTION("6272FDCB59C4" , k(k3).z().vpbroadcastq(zmm8, xmm4)); + TEST_INSTRUCTION("62F2FD487CE8" , vpbroadcastq(zmm5, rax)); + TEST_INSTRUCTION("62F2FD4E7CE8" , k(k6).vpbroadcastq(zmm5, rax)); + TEST_INSTRUCTION("62F2FDCE7CE8" , k(k6).z().vpbroadcastq(zmm5, rax)); + TEST_INSTRUCTION("62D2FD487CE8" , vpbroadcastq(zmm5, r8)); + TEST_INSTRUCTION("62B335401FD6AB" , vpcmpd(k2, zmm25, zmm22, 171)); + TEST_INSTRUCTION("62B335431FD6AB" , k(k3).vpcmpd(k2, zmm25, zmm22, 171)); + TEST_INSTRUCTION("62B335401FD67B" , vpcmpd(k2, zmm25, zmm22, 123)); + TEST_INSTRUCTION("62F335401F117B" , vpcmpd(k2, zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B335401F94F0341200007B" , vpcmpd(k2, zmm25, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F335501F117B" , vpcmpd(k2, zmm25, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F335401F527F7B" , vpcmpd(k2, zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F335401F92002000007B" , vpcmpd(k2, zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F335401F52807B" , vpcmpd(k2, zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F335401F92C0DFFFFF7B" , vpcmpd(k2, zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F335501F527F7B" , vpcmpd(k2, zmm25, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F335501F92000200007B" , vpcmpd(k2, zmm25, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F335501F52807B" , vpcmpd(k2, zmm25, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F335501F92FCFDFFFF7B" , vpcmpd(k2, zmm25, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62B13D4876ED" , vpcmpeqd(k5, zmm8, zmm21)); + TEST_INSTRUCTION("62B13D4C76ED" , k(k4).vpcmpeqd(k5, zmm8, zmm21)); + TEST_INSTRUCTION("62F13D487629" , vpcmpeqd(k5, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B13D4876ACF034120000" , vpcmpeqd(k5, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F13D587629" , vpcmpeqd(k5, zmm8, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F13D48766A7F" , vpcmpeqd(k5, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F13D4876AA00200000" , vpcmpeqd(k5, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F13D48766A80" , vpcmpeqd(k5, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F13D4876AAC0DFFFFF" , vpcmpeqd(k5, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F13D58766A7F" , vpcmpeqd(k5, zmm8, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F13D5876AA00020000" , vpcmpeqd(k5, zmm8, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F13D58766A80" , vpcmpeqd(k5, zmm8, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F13D5876AAFCFDFFFF" , vpcmpeqd(k5, zmm8, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D28D4829E1" , vpcmpeqq(k4, zmm14, zmm9)); + TEST_INSTRUCTION("62D28D4E29E1" , k(k6).vpcmpeqq(k4, zmm14, zmm9)); + TEST_INSTRUCTION("62F28D482921" , vpcmpeqq(k4, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B28D4829A4F034120000" , vpcmpeqq(k4, zmm14, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F28D582921" , vpcmpeqq(k4, zmm14, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F28D4829627F" , vpcmpeqq(k4, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F28D4829A200200000" , vpcmpeqq(k4, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F28D48296280" , vpcmpeqq(k4, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F28D4829A2C0DFFFFF" , vpcmpeqq(k4, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F28D5829627F" , vpcmpeqq(k4, zmm14, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F28D5829A200040000" , vpcmpeqq(k4, zmm14, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F28D58296280" , vpcmpeqq(k4, zmm14, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F28D5829A2F8FBFFFF" , vpcmpeqq(k4, zmm14, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D13D4866E0" , vpcmpgtd(k4, zmm8, zmm8)); + TEST_INSTRUCTION("62D13D4F66E0" , k(k7).vpcmpgtd(k4, zmm8, zmm8)); + TEST_INSTRUCTION("62F13D486621" , vpcmpgtd(k4, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B13D4866A4F034120000" , vpcmpgtd(k4, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F13D586621" , vpcmpgtd(k4, zmm8, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F13D4866627F" , vpcmpgtd(k4, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F13D4866A200200000" , vpcmpgtd(k4, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F13D48666280" , vpcmpgtd(k4, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F13D4866A2C0DFFFFF" , vpcmpgtd(k4, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F13D5866627F" , vpcmpgtd(k4, zmm8, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F13D5866A200020000" , vpcmpgtd(k4, zmm8, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F13D58666280" , vpcmpgtd(k4, zmm8, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F13D5866A2FCFDFFFF" , vpcmpgtd(k4, zmm8, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62929D4837DA" , vpcmpgtq(k3, zmm12, zmm26)); + TEST_INSTRUCTION("62929D4C37DA" , k(k4).vpcmpgtq(k3, zmm12, zmm26)); + TEST_INSTRUCTION("62F29D483719" , vpcmpgtq(k3, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B29D48379CF034120000" , vpcmpgtq(k3, zmm12, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F29D583719" , vpcmpgtq(k3, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F29D48375A7F" , vpcmpgtq(k3, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F29D48379A00200000" , vpcmpgtq(k3, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F29D48375A80" , vpcmpgtq(k3, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F29D48379AC0DFFFFF" , vpcmpgtq(k3, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F29D58375A7F" , vpcmpgtq(k3, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F29D58379A00040000" , vpcmpgtq(k3, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F29D58375A80" , vpcmpgtq(k3, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F29D58379AF8FBFFFF" , vpcmpgtq(k3, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D3B5401FDFAB" , vpcmpq(k3, zmm25, zmm15, 171)); + TEST_INSTRUCTION("62D3B5441FDFAB" , k(k4).vpcmpq(k3, zmm25, zmm15, 171)); + TEST_INSTRUCTION("62D3B5401FDF7B" , vpcmpq(k3, zmm25, zmm15, 123)); + TEST_INSTRUCTION("62F3B5401F197B" , vpcmpq(k3, zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B3B5401F9CF0341200007B" , vpcmpq(k3, zmm25, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F3B5501F197B" , vpcmpq(k3, zmm25, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F3B5401F5A7F7B" , vpcmpq(k3, zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F3B5401F9A002000007B" , vpcmpq(k3, zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F3B5401F5A807B" , vpcmpq(k3, zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F3B5401F9AC0DFFFFF7B" , vpcmpq(k3, zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F3B5501F5A7F7B" , vpcmpq(k3, zmm25, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F3B5501F9A000400007B" , vpcmpq(k3, zmm25, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3B5501F5A807B" , vpcmpq(k3, zmm25, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F3B5501F9AF8FBFFFF7B" , vpcmpq(k3, zmm25, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F315401EDDAB" , vpcmpud(k3, zmm29, zmm5, 171)); + TEST_INSTRUCTION("62F315471EDDAB" , k(k7).vpcmpud(k3, zmm29, zmm5, 171)); + TEST_INSTRUCTION("62F315401EDD7B" , vpcmpud(k3, zmm29, zmm5, 123)); + TEST_INSTRUCTION("62F315401E197B" , vpcmpud(k3, zmm29, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B315401E9CF0341200007B" , vpcmpud(k3, zmm29, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F315501E197B" , vpcmpud(k3, zmm29, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F315401E5A7F7B" , vpcmpud(k3, zmm29, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F315401E9A002000007B" , vpcmpud(k3, zmm29, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F315401E5A807B" , vpcmpud(k3, zmm29, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F315401E9AC0DFFFFF7B" , vpcmpud(k3, zmm29, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F315501E5A7F7B" , vpcmpud(k3, zmm29, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F315501E9A000200007B" , vpcmpud(k3, zmm29, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F315501E5A807B" , vpcmpud(k3, zmm29, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F315501E9AFCFDFFFF7B" , vpcmpud(k3, zmm29, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D38D481ED4AB" , vpcmpuq(k2, zmm14, zmm12, 171)); + TEST_INSTRUCTION("62D38D4B1ED4AB" , k(k3).vpcmpuq(k2, zmm14, zmm12, 171)); + TEST_INSTRUCTION("62D38D481ED47B" , vpcmpuq(k2, zmm14, zmm12, 123)); + TEST_INSTRUCTION("62F38D481E117B" , vpcmpuq(k2, zmm14, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B38D481E94F0341200007B" , vpcmpuq(k2, zmm14, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F38D581E117B" , vpcmpuq(k2, zmm14, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F38D481E527F7B" , vpcmpuq(k2, zmm14, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F38D481E92002000007B" , vpcmpuq(k2, zmm14, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F38D481E52807B" , vpcmpuq(k2, zmm14, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F38D481E92C0DFFFFF7B" , vpcmpuq(k2, zmm14, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F38D581E527F7B" , vpcmpuq(k2, zmm14, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F38D581E92000400007B" , vpcmpuq(k2, zmm14, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F38D581E52807B" , vpcmpuq(k2, zmm14, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F38D581E92F8FBFFFF7B" , vpcmpuq(k2, zmm14, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("6262ED4064C5" , vpblendmq(zmm24, zmm18, zmm5)); + TEST_INSTRUCTION("6262ED4364C5" , k(k3).vpblendmq(zmm24, zmm18, zmm5)); + TEST_INSTRUCTION("6262EDC364C5" , k(k3).z().vpblendmq(zmm24, zmm18, zmm5)); + TEST_INSTRUCTION("6262ED406401" , vpblendmq(zmm24, zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222ED406484F034120000" , vpblendmq(zmm24, zmm18, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262ED506401" , vpblendmq(zmm24, zmm18, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262ED4064427F" , vpblendmq(zmm24, zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262ED40648200200000" , vpblendmq(zmm24, zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262ED40644280" , vpblendmq(zmm24, zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262ED406482C0DFFFFF" , vpblendmq(zmm24, zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262ED5064427F" , vpblendmq(zmm24, zmm18, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262ED50648200040000" , vpblendmq(zmm24, zmm18, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262ED50644280" , vpblendmq(zmm24, zmm18, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262ED506482F8FBFFFF" , vpblendmq(zmm24, zmm18, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E27D488B21" , vpcompressd(zmmword_ptr(rcx), zmm20)); + TEST_INSTRUCTION("62E27D4E8B21" , k(k6).vpcompressd(zmmword_ptr(rcx), zmm20)); + TEST_INSTRUCTION("62A27D488BA4F034120000" , vpcompressd(zmmword_ptr(rax, r14, 3, 4660), zmm20)); + TEST_INSTRUCTION("62E27D488B627F" , vpcompressd(zmmword_ptr(rdx, 508), zmm20)); + TEST_INSTRUCTION("62E27D488BA200020000" , vpcompressd(zmmword_ptr(rdx, 512), zmm20)); + TEST_INSTRUCTION("62E27D488B6280" , vpcompressd(zmmword_ptr(rdx, -512), zmm20)); + TEST_INSTRUCTION("62E27D488BA2FCFDFFFF" , vpcompressd(zmmword_ptr(rdx, -516), zmm20)); + TEST_INSTRUCTION("62127D488BE0" , vpcompressd(zmm24, zmm12)); + TEST_INSTRUCTION("62127D4D8BE0" , k(k5).vpcompressd(zmm24, zmm12)); + TEST_INSTRUCTION("62127DCD8BE0" , k(k5).z().vpcompressd(zmm24, zmm12)); + TEST_INSTRUCTION("62422D4836C8" , vpermd(zmm25, zmm10, zmm8)); + TEST_INSTRUCTION("62422D4E36C8" , k(k6).vpermd(zmm25, zmm10, zmm8)); + TEST_INSTRUCTION("62422DCE36C8" , k(k6).z().vpermd(zmm25, zmm10, zmm8)); + TEST_INSTRUCTION("62622D483609" , vpermd(zmm25, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62222D48368CF034120000" , vpermd(zmm25, zmm10, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62622D583609" , vpermd(zmm25, zmm10, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62622D48364A7F" , vpermd(zmm25, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62622D48368A00200000" , vpermd(zmm25, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62622D48364A80" , vpermd(zmm25, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62622D48368AC0DFFFFF" , vpermd(zmm25, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62622D58364A7F" , vpermd(zmm25, zmm10, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62622D58368A00020000" , vpermd(zmm25, zmm10, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62622D58364A80" , vpermd(zmm25, zmm10, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62622D58368AFCFDFFFF" , vpermd(zmm25, zmm10, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6253FD4805F8AB" , vpermilpd(zmm15, zmm8, 171)); + TEST_INSTRUCTION("6253FD4E05F8AB" , k(k6).vpermilpd(zmm15, zmm8, 171)); + TEST_INSTRUCTION("6253FDCE05F8AB" , k(k6).z().vpermilpd(zmm15, zmm8, 171)); + TEST_INSTRUCTION("6253FD4805F87B" , vpermilpd(zmm15, zmm8, 123)); + TEST_INSTRUCTION("6273FD4805397B" , vpermilpd(zmm15, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233FD4805BCF0341200007B" , vpermilpd(zmm15, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6273FD5805397B" , vpermilpd(zmm15, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273FD48057A7F7B" , vpermilpd(zmm15, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273FD4805BA002000007B" , vpermilpd(zmm15, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273FD48057A807B" , vpermilpd(zmm15, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273FD4805BAC0DFFFFF7B" , vpermilpd(zmm15, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273FD58057A7F7B" , vpermilpd(zmm15, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273FD5805BA000400007B" , vpermilpd(zmm15, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273FD58057A807B" , vpermilpd(zmm15, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273FD5805BAF8FBFFFF7B" , vpermilpd(zmm15, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62C2AD400DF8" , vpermilpd(zmm23, zmm26, zmm8)); + TEST_INSTRUCTION("62C2AD410DF8" , k(k1).vpermilpd(zmm23, zmm26, zmm8)); + TEST_INSTRUCTION("62C2ADC10DF8" , k(k1).z().vpermilpd(zmm23, zmm26, zmm8)); + TEST_INSTRUCTION("62E2AD400D39" , vpermilpd(zmm23, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2AD400DBCF034120000" , vpermilpd(zmm23, zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2AD500D39" , vpermilpd(zmm23, zmm26, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2AD400D7A7F" , vpermilpd(zmm23, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2AD400DBA00200000" , vpermilpd(zmm23, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2AD400D7A80" , vpermilpd(zmm23, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2AD400DBAC0DFFFFF" , vpermilpd(zmm23, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2AD500D7A7F" , vpermilpd(zmm23, zmm26, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2AD500DBA00040000" , vpermilpd(zmm23, zmm26, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2AD500D7A80" , vpermilpd(zmm23, zmm26, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2AD500DBAF8FBFFFF" , vpermilpd(zmm23, zmm26, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62637D4804CFAB" , vpermilps(zmm25, zmm7, 171)); + TEST_INSTRUCTION("62637D4A04CFAB" , k(k2).vpermilps(zmm25, zmm7, 171)); + TEST_INSTRUCTION("62637DCA04CFAB" , k(k2).z().vpermilps(zmm25, zmm7, 171)); + TEST_INSTRUCTION("62637D4804CF7B" , vpermilps(zmm25, zmm7, 123)); + TEST_INSTRUCTION("62637D4804097B" , vpermilps(zmm25, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62237D48048CF0341200007B" , vpermilps(zmm25, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62637D5804097B" , vpermilps(zmm25, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62637D48044A7F7B" , vpermilps(zmm25, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62637D48048A002000007B" , vpermilps(zmm25, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62637D48044A807B" , vpermilps(zmm25, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62637D48048AC0DFFFFF7B" , vpermilps(zmm25, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62637D58044A7F7B" , vpermilps(zmm25, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62637D58048A000200007B" , vpermilps(zmm25, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62637D58044A807B" , vpermilps(zmm25, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62637D58048AFCFDFFFF7B" , vpermilps(zmm25, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62B22D400CD9" , vpermilps(zmm3, zmm26, zmm17)); + TEST_INSTRUCTION("62B22D430CD9" , k(k3).vpermilps(zmm3, zmm26, zmm17)); + TEST_INSTRUCTION("62B22DC30CD9" , k(k3).z().vpermilps(zmm3, zmm26, zmm17)); + TEST_INSTRUCTION("62F22D400C19" , vpermilps(zmm3, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B22D400C9CF034120000" , vpermilps(zmm3, zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F22D500C19" , vpermilps(zmm3, zmm26, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F22D400C5A7F" , vpermilps(zmm3, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F22D400C9A00200000" , vpermilps(zmm3, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F22D400C5A80" , vpermilps(zmm3, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F22D400C9AC0DFFFFF" , vpermilps(zmm3, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F22D500C5A7F" , vpermilps(zmm3, zmm26, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F22D500C9A00020000" , vpermilps(zmm3, zmm26, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F22D500C5A80" , vpermilps(zmm3, zmm26, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F22D500C9AFCFDFFFF" , vpermilps(zmm3, zmm26, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6243FD4801E7AB" , vpermpd(zmm28, zmm15, 171)); + TEST_INSTRUCTION("6243FD4C01E7AB" , k(k4).vpermpd(zmm28, zmm15, 171)); + TEST_INSTRUCTION("6243FDCC01E7AB" , k(k4).z().vpermpd(zmm28, zmm15, 171)); + TEST_INSTRUCTION("6243FD4801E77B" , vpermpd(zmm28, zmm15, 123)); + TEST_INSTRUCTION("6263FD4801217B" , vpermpd(zmm28, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223FD4801A4F0341200007B" , vpermpd(zmm28, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6263FD5801217B" , vpermpd(zmm28, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6263FD4801627F7B" , vpermpd(zmm28, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6263FD4801A2002000007B" , vpermpd(zmm28, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6263FD480162807B" , vpermpd(zmm28, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6263FD4801A2C0DFFFFF7B" , vpermpd(zmm28, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6263FD5801627F7B" , vpermpd(zmm28, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6263FD5801A2000400007B" , vpermpd(zmm28, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6263FD580162807B" , vpermpd(zmm28, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6263FD5801A2F8FBFFFF7B" , vpermpd(zmm28, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62A24D4816F5" , vpermps(zmm22, zmm6, zmm21)); + TEST_INSTRUCTION("62A24D4D16F5" , k(k5).vpermps(zmm22, zmm6, zmm21)); + TEST_INSTRUCTION("62A24DCD16F5" , k(k5).z().vpermps(zmm22, zmm6, zmm21)); + TEST_INSTRUCTION("62E24D481631" , vpermps(zmm22, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A24D4816B4F034120000" , vpermps(zmm22, zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E24D581631" , vpermps(zmm22, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E24D4816727F" , vpermps(zmm22, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E24D4816B200200000" , vpermps(zmm22, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E24D48167280" , vpermps(zmm22, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E24D4816B2C0DFFFFF" , vpermps(zmm22, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E24D5816727F" , vpermps(zmm22, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E24D5816B200020000" , vpermps(zmm22, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E24D58167280" , vpermps(zmm22, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E24D5816B2FCFDFFFF" , vpermps(zmm22, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6223FD4800C7AB" , vpermq(zmm24, zmm23, 171)); + TEST_INSTRUCTION("6223FD4B00C7AB" , k(k3).vpermq(zmm24, zmm23, 171)); + TEST_INSTRUCTION("6223FDCB00C7AB" , k(k3).z().vpermq(zmm24, zmm23, 171)); + TEST_INSTRUCTION("6223FD4800C77B" , vpermq(zmm24, zmm23, 123)); + TEST_INSTRUCTION("6263FD4800017B" , vpermq(zmm24, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223FD480084F0341200007B" , vpermq(zmm24, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6263FD5800017B" , vpermq(zmm24, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6263FD4800427F7B" , vpermq(zmm24, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6263FD480082002000007B" , vpermq(zmm24, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6263FD480042807B" , vpermq(zmm24, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6263FD480082C0DFFFFF7B" , vpermq(zmm24, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6263FD5800427F7B" , vpermq(zmm24, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6263FD580082000400007B" , vpermq(zmm24, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6263FD580042807B" , vpermq(zmm24, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6263FD580082F8FBFFFF7B" , vpermq(zmm24, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62E27D488911" , vpexpandd(zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62E27D4A8911" , k(k2).vpexpandd(zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62E27DCA8911" , k(k2).z().vpexpandd(zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A27D488994F034120000" , vpexpandd(zmm18, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E27D4889527F" , vpexpandd(zmm18, zmmword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E27D48899200020000" , vpexpandd(zmm18, zmmword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E27D48895280" , vpexpandd(zmm18, zmmword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E27D488992FCFDFFFF" , vpexpandd(zmm18, zmmword_ptr(rdx, -516))); + TEST_INSTRUCTION("62127D4889E4" , vpexpandd(zmm12, zmm28)); + TEST_INSTRUCTION("62127D4E89E4" , k(k6).vpexpandd(zmm12, zmm28)); + TEST_INSTRUCTION("62127DCE89E4" , k(k6).z().vpexpandd(zmm12, zmm28)); + TEST_INSTRUCTION("62F2FD488909" , vpexpandq(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F2FD4F8909" , k(k7).vpexpandq(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62F2FDCF8909" , k(k7).z().vpexpandq(zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2FD48898CF034120000" , vpexpandq(zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2FD48894A7F" , vpexpandq(zmm1, zmmword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F2FD48898A00040000" , vpexpandq(zmm1, zmmword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F2FD48894A80" , vpexpandq(zmm1, zmmword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F2FD48898AF8FBFFFF" , vpexpandq(zmm1, zmmword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6282FD4889CA" , vpexpandq(zmm17, zmm26)); + TEST_INSTRUCTION("6282FD4F89CA" , k(k7).vpexpandq(zmm17, zmm26)); + TEST_INSTRUCTION("6282FDCF89CA" , k(k7).z().vpexpandq(zmm17, zmm26)); + TEST_INSTRUCTION("624215483DF1" , vpmaxsd(zmm30, zmm13, zmm9)); + TEST_INSTRUCTION("6242154F3DF1" , k(k7).vpmaxsd(zmm30, zmm13, zmm9)); + TEST_INSTRUCTION("624215CF3DF1" , k(k7).z().vpmaxsd(zmm30, zmm13, zmm9)); + TEST_INSTRUCTION("626215483D31" , vpmaxsd(zmm30, zmm13, zmmword_ptr(rcx))); + TEST_INSTRUCTION("622215483DB4F034120000" , vpmaxsd(zmm30, zmm13, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626215583D31" , vpmaxsd(zmm30, zmm13, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("626215483D727F" , vpmaxsd(zmm30, zmm13, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("626215483DB200200000" , vpmaxsd(zmm30, zmm13, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("626215483D7280" , vpmaxsd(zmm30, zmm13, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("626215483DB2C0DFFFFF" , vpmaxsd(zmm30, zmm13, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("626215583D727F" , vpmaxsd(zmm30, zmm13, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("626215583DB200020000" , vpmaxsd(zmm30, zmm13, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("626215583D7280" , vpmaxsd(zmm30, zmm13, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("626215583DB2FCFDFFFF" , vpmaxsd(zmm30, zmm13, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2C5483DDD" , vpmaxsq(zmm3, zmm7, zmm5)); + TEST_INSTRUCTION("62F2C54B3DDD" , k(k3).vpmaxsq(zmm3, zmm7, zmm5)); + TEST_INSTRUCTION("62F2C5CB3DDD" , k(k3).z().vpmaxsq(zmm3, zmm7, zmm5)); + TEST_INSTRUCTION("62F2C5483D19" , vpmaxsq(zmm3, zmm7, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2C5483D9CF034120000" , vpmaxsq(zmm3, zmm7, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2C5583D19" , vpmaxsq(zmm3, zmm7, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2C5483D5A7F" , vpmaxsq(zmm3, zmm7, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2C5483D9A00200000" , vpmaxsq(zmm3, zmm7, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2C5483D5A80" , vpmaxsq(zmm3, zmm7, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2C5483D9AC0DFFFFF" , vpmaxsq(zmm3, zmm7, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2C5583D5A7F" , vpmaxsq(zmm3, zmm7, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2C5583D9A00040000" , vpmaxsq(zmm3, zmm7, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2C5583D5A80" , vpmaxsq(zmm3, zmm7, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2C5583D9AF8FBFFFF" , vpmaxsq(zmm3, zmm7, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C225403FF4" , vpmaxud(zmm22, zmm27, zmm12)); + TEST_INSTRUCTION("62C225473FF4" , k(k7).vpmaxud(zmm22, zmm27, zmm12)); + TEST_INSTRUCTION("62C225C73FF4" , k(k7).z().vpmaxud(zmm22, zmm27, zmm12)); + TEST_INSTRUCTION("62E225403F31" , vpmaxud(zmm22, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A225403FB4F034120000" , vpmaxud(zmm22, zmm27, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E225503F31" , vpmaxud(zmm22, zmm27, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E225403F727F" , vpmaxud(zmm22, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E225403FB200200000" , vpmaxud(zmm22, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E225403F7280" , vpmaxud(zmm22, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E225403FB2C0DFFFFF" , vpmaxud(zmm22, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E225503F727F" , vpmaxud(zmm22, zmm27, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E225503FB200020000" , vpmaxud(zmm22, zmm27, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E225503F7280" , vpmaxud(zmm22, zmm27, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E225503FB2FCFDFFFF" , vpmaxud(zmm22, zmm27, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D2B5483FCC" , vpmaxuq(zmm1, zmm9, zmm12)); + TEST_INSTRUCTION("62D2B54A3FCC" , k(k2).vpmaxuq(zmm1, zmm9, zmm12)); + TEST_INSTRUCTION("62D2B5CA3FCC" , k(k2).z().vpmaxuq(zmm1, zmm9, zmm12)); + TEST_INSTRUCTION("62F2B5483F09" , vpmaxuq(zmm1, zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2B5483F8CF034120000" , vpmaxuq(zmm1, zmm9, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2B5583F09" , vpmaxuq(zmm1, zmm9, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2B5483F4A7F" , vpmaxuq(zmm1, zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2B5483F8A00200000" , vpmaxuq(zmm1, zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2B5483F4A80" , vpmaxuq(zmm1, zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2B5483F8AC0DFFFFF" , vpmaxuq(zmm1, zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2B5583F4A7F" , vpmaxuq(zmm1, zmm9, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2B5583F8A00040000" , vpmaxuq(zmm1, zmm9, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2B5583F4A80" , vpmaxuq(zmm1, zmm9, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2B5583F8AF8FBFFFF" , vpmaxuq(zmm1, zmm9, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E2754039DA" , vpminsd(zmm19, zmm17, zmm2)); + TEST_INSTRUCTION("62E2754739DA" , k(k7).vpminsd(zmm19, zmm17, zmm2)); + TEST_INSTRUCTION("62E275C739DA" , k(k7).z().vpminsd(zmm19, zmm17, zmm2)); + TEST_INSTRUCTION("62E275403919" , vpminsd(zmm19, zmm17, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A27540399CF034120000" , vpminsd(zmm19, zmm17, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E275503919" , vpminsd(zmm19, zmm17, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E27540395A7F" , vpminsd(zmm19, zmm17, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E27540399A00200000" , vpminsd(zmm19, zmm17, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E27540395A80" , vpminsd(zmm19, zmm17, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E27540399AC0DFFFFF" , vpminsd(zmm19, zmm17, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E27550395A7F" , vpminsd(zmm19, zmm17, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E27550399A00020000" , vpminsd(zmm19, zmm17, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E27550395A80" , vpminsd(zmm19, zmm17, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E27550399AFCFDFFFF" , vpminsd(zmm19, zmm17, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A2F54839EE" , vpminsq(zmm21, zmm1, zmm22)); + TEST_INSTRUCTION("62A2F54E39EE" , k(k6).vpminsq(zmm21, zmm1, zmm22)); + TEST_INSTRUCTION("62A2F5CE39EE" , k(k6).z().vpminsq(zmm21, zmm1, zmm22)); + TEST_INSTRUCTION("62E2F5483929" , vpminsq(zmm21, zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2F54839ACF034120000" , vpminsq(zmm21, zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2F5583929" , vpminsq(zmm21, zmm1, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2F548396A7F" , vpminsq(zmm21, zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2F54839AA00200000" , vpminsq(zmm21, zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2F548396A80" , vpminsq(zmm21, zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2F54839AAC0DFFFFF" , vpminsq(zmm21, zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2F558396A7F" , vpminsq(zmm21, zmm1, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2F55839AA00040000" , vpminsq(zmm21, zmm1, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2F558396A80" , vpminsq(zmm21, zmm1, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2F55839AAF8FBFFFF" , vpminsq(zmm21, zmm1, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F24D403BE3" , vpminud(zmm4, zmm22, zmm3)); + TEST_INSTRUCTION("62F24D443BE3" , k(k4).vpminud(zmm4, zmm22, zmm3)); + TEST_INSTRUCTION("62F24DC43BE3" , k(k4).z().vpminud(zmm4, zmm22, zmm3)); + TEST_INSTRUCTION("62F24D403B21" , vpminud(zmm4, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B24D403BA4F034120000" , vpminud(zmm4, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F24D503B21" , vpminud(zmm4, zmm22, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F24D403B627F" , vpminud(zmm4, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F24D403BA200200000" , vpminud(zmm4, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F24D403B6280" , vpminud(zmm4, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F24D403BA2C0DFFFFF" , vpminud(zmm4, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F24D503B627F" , vpminud(zmm4, zmm22, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F24D503BA200020000" , vpminud(zmm4, zmm22, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F24D503B6280" , vpminud(zmm4, zmm22, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F24D503BA2FCFDFFFF" , vpminud(zmm4, zmm22, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6202AD403BCB" , vpminuq(zmm25, zmm26, zmm27)); + TEST_INSTRUCTION("6202AD463BCB" , k(k6).vpminuq(zmm25, zmm26, zmm27)); + TEST_INSTRUCTION("6202ADC63BCB" , k(k6).z().vpminuq(zmm25, zmm26, zmm27)); + TEST_INSTRUCTION("6262AD403B09" , vpminuq(zmm25, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222AD403B8CF034120000" , vpminuq(zmm25, zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262AD503B09" , vpminuq(zmm25, zmm26, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262AD403B4A7F" , vpminuq(zmm25, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262AD403B8A00200000" , vpminuq(zmm25, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262AD403B4A80" , vpminuq(zmm25, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262AD403B8AC0DFFFFF" , vpminuq(zmm25, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262AD503B4A7F" , vpminuq(zmm25, zmm26, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262AD503B8A00040000" , vpminuq(zmm25, zmm26, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262AD503B4A80" , vpminuq(zmm25, zmm26, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262AD503B8AF8FBFFFF" , vpminuq(zmm25, zmm26, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62427D4821CA" , vpmovsxbd(zmm25, xmm10)); + TEST_INSTRUCTION("62427D4921CA" , k(k1).vpmovsxbd(zmm25, xmm10)); + TEST_INSTRUCTION("62427DC921CA" , k(k1).z().vpmovsxbd(zmm25, xmm10)); + TEST_INSTRUCTION("62627D482109" , vpmovsxbd(zmm25, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62227D48218CF034120000" , vpmovsxbd(zmm25, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62627D48214A7F" , vpmovsxbd(zmm25, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62627D48218A00080000" , vpmovsxbd(zmm25, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62627D48214A80" , vpmovsxbd(zmm25, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62627D48218AF0F7FFFF" , vpmovsxbd(zmm25, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62527D4822F6" , vpmovsxbq(zmm14, xmm14)); + TEST_INSTRUCTION("62527D4D22F6" , k(k5).vpmovsxbq(zmm14, xmm14)); + TEST_INSTRUCTION("62527DCD22F6" , k(k5).z().vpmovsxbq(zmm14, xmm14)); + TEST_INSTRUCTION("62727D482231" , vpmovsxbq(zmm14, qword_ptr(rcx))); + TEST_INSTRUCTION("62327D4822B4F034120000" , vpmovsxbq(zmm14, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D4822727F" , vpmovsxbq(zmm14, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62727D4822B200040000" , vpmovsxbq(zmm14, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62727D48227280" , vpmovsxbq(zmm14, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62727D4822B2F8FBFFFF" , vpmovsxbq(zmm14, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62527D4825D9" , vpmovsxdq(zmm11, ymm9)); + TEST_INSTRUCTION("62527D4E25D9" , k(k6).vpmovsxdq(zmm11, ymm9)); + TEST_INSTRUCTION("62527DCE25D9" , k(k6).z().vpmovsxdq(zmm11, ymm9)); + TEST_INSTRUCTION("62727D482519" , vpmovsxdq(zmm11, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62327D48259CF034120000" , vpmovsxdq(zmm11, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D48255A7F" , vpmovsxdq(zmm11, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62727D48259A00100000" , vpmovsxdq(zmm11, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62727D48255A80" , vpmovsxdq(zmm11, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62727D48259AE0EFFFFF" , vpmovsxdq(zmm11, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62527D4823E3" , vpmovsxwd(zmm12, ymm11)); + TEST_INSTRUCTION("62527D4A23E3" , k(k2).vpmovsxwd(zmm12, ymm11)); + TEST_INSTRUCTION("62527DCA23E3" , k(k2).z().vpmovsxwd(zmm12, ymm11)); + TEST_INSTRUCTION("62727D482321" , vpmovsxwd(zmm12, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62327D4823A4F034120000" , vpmovsxwd(zmm12, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D4823627F" , vpmovsxwd(zmm12, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62727D4823A200100000" , vpmovsxwd(zmm12, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62727D48236280" , vpmovsxwd(zmm12, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62727D4823A2E0EFFFFF" , vpmovsxwd(zmm12, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62527D4824DE" , vpmovsxwq(zmm11, xmm14)); + TEST_INSTRUCTION("62527D4D24DE" , k(k5).vpmovsxwq(zmm11, xmm14)); + TEST_INSTRUCTION("62527DCD24DE" , k(k5).z().vpmovsxwq(zmm11, xmm14)); + TEST_INSTRUCTION("62727D482419" , vpmovsxwq(zmm11, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D48249CF034120000" , vpmovsxwq(zmm11, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D48245A7F" , vpmovsxwq(zmm11, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62727D48249A00080000" , vpmovsxwq(zmm11, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62727D48245A80" , vpmovsxwq(zmm11, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62727D48249AF0F7FFFF" , vpmovsxwq(zmm11, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62027D4831C9" , vpmovzxbd(zmm25, xmm25)); + TEST_INSTRUCTION("62027D4C31C9" , k(k4).vpmovzxbd(zmm25, xmm25)); + TEST_INSTRUCTION("62027DCC31C9" , k(k4).z().vpmovzxbd(zmm25, xmm25)); + TEST_INSTRUCTION("62627D483109" , vpmovzxbd(zmm25, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62227D48318CF034120000" , vpmovzxbd(zmm25, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62627D48314A7F" , vpmovzxbd(zmm25, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62627D48318A00080000" , vpmovzxbd(zmm25, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62627D48314A80" , vpmovzxbd(zmm25, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62627D48318AF0F7FFFF" , vpmovzxbd(zmm25, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62A27D4832FC" , vpmovzxbq(zmm23, xmm20)); + TEST_INSTRUCTION("62A27D4B32FC" , k(k3).vpmovzxbq(zmm23, xmm20)); + TEST_INSTRUCTION("62A27DCB32FC" , k(k3).z().vpmovzxbq(zmm23, xmm20)); + TEST_INSTRUCTION("62E27D483239" , vpmovzxbq(zmm23, qword_ptr(rcx))); + TEST_INSTRUCTION("62A27D4832BCF034120000" , vpmovzxbq(zmm23, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E27D48327A7F" , vpmovzxbq(zmm23, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E27D4832BA00040000" , vpmovzxbq(zmm23, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E27D48327A80" , vpmovzxbq(zmm23, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E27D4832BAF8FBFFFF" , vpmovzxbq(zmm23, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62327D4835CE" , vpmovzxdq(zmm9, ymm22)); + TEST_INSTRUCTION("62327D4B35CE" , k(k3).vpmovzxdq(zmm9, ymm22)); + TEST_INSTRUCTION("62327DCB35CE" , k(k3).z().vpmovzxdq(zmm9, ymm22)); + TEST_INSTRUCTION("62727D483509" , vpmovzxdq(zmm9, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62327D48358CF034120000" , vpmovzxdq(zmm9, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D48354A7F" , vpmovzxdq(zmm9, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62727D48358A00100000" , vpmovzxdq(zmm9, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62727D48354A80" , vpmovzxdq(zmm9, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62727D48358AE0EFFFFF" , vpmovzxdq(zmm9, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62927D4833F5" , vpmovzxwd(zmm6, ymm29)); + TEST_INSTRUCTION("62927D4C33F5" , k(k4).vpmovzxwd(zmm6, ymm29)); + TEST_INSTRUCTION("62927DCC33F5" , k(k4).z().vpmovzxwd(zmm6, ymm29)); + TEST_INSTRUCTION("62F27D483331" , vpmovzxwd(zmm6, ymmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D4833B4F034120000" , vpmovzxwd(zmm6, ymmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D4833727F" , vpmovzxwd(zmm6, ymmword_ptr(rdx, 4064))); + TEST_INSTRUCTION("62F27D4833B200100000" , vpmovzxwd(zmm6, ymmword_ptr(rdx, 4096))); + TEST_INSTRUCTION("62F27D48337280" , vpmovzxwd(zmm6, ymmword_ptr(rdx, -4096))); + TEST_INSTRUCTION("62F27D4833B2E0EFFFFF" , vpmovzxwd(zmm6, ymmword_ptr(rdx, -4128))); + TEST_INSTRUCTION("62327D4834E2" , vpmovzxwq(zmm12, xmm18)); + TEST_INSTRUCTION("62327D4E34E2" , k(k6).vpmovzxwq(zmm12, xmm18)); + TEST_INSTRUCTION("62327DCE34E2" , k(k6).z().vpmovzxwq(zmm12, xmm18)); + TEST_INSTRUCTION("62727D483421" , vpmovzxwq(zmm12, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62327D4834A4F034120000" , vpmovzxwq(zmm12, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62727D4834627F" , vpmovzxwq(zmm12, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62727D4834A200080000" , vpmovzxwq(zmm12, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62727D48346280" , vpmovzxwq(zmm12, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62727D4834A2F0F7FFFF" , vpmovzxwq(zmm12, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62D2CD4028EC" , vpmuldq(zmm5, zmm22, zmm12)); + TEST_INSTRUCTION("62D2CD4428EC" , k(k4).vpmuldq(zmm5, zmm22, zmm12)); + TEST_INSTRUCTION("62D2CDC428EC" , k(k4).z().vpmuldq(zmm5, zmm22, zmm12)); + TEST_INSTRUCTION("62F2CD402829" , vpmuldq(zmm5, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2CD4028ACF034120000" , vpmuldq(zmm5, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2CD502829" , vpmuldq(zmm5, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2CD40286A7F" , vpmuldq(zmm5, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2CD4028AA00200000" , vpmuldq(zmm5, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2CD40286A80" , vpmuldq(zmm5, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2CD4028AAC0DFFFFF" , vpmuldq(zmm5, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2CD50286A7F" , vpmuldq(zmm5, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2CD5028AA00040000" , vpmuldq(zmm5, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2CD50286A80" , vpmuldq(zmm5, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2CD5028AAF8FBFFFF" , vpmuldq(zmm5, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62723D4040E2" , vpmulld(zmm12, zmm24, zmm2)); + TEST_INSTRUCTION("62723D4640E2" , k(k6).vpmulld(zmm12, zmm24, zmm2)); + TEST_INSTRUCTION("62723DC640E2" , k(k6).z().vpmulld(zmm12, zmm24, zmm2)); + TEST_INSTRUCTION("62723D404021" , vpmulld(zmm12, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62323D4040A4F034120000" , vpmulld(zmm12, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62723D504021" , vpmulld(zmm12, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62723D4040627F" , vpmulld(zmm12, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62723D4040A200200000" , vpmulld(zmm12, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62723D40406280" , vpmulld(zmm12, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62723D4040A2C0DFFFFF" , vpmulld(zmm12, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62723D5040627F" , vpmulld(zmm12, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62723D5040A200020000" , vpmulld(zmm12, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62723D50406280" , vpmulld(zmm12, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62723D5040A2FCFDFFFF" , vpmulld(zmm12, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6251ED48F4C2" , vpmuludq(zmm8, zmm2, zmm10)); + TEST_INSTRUCTION("6251ED4FF4C2" , k(k7).vpmuludq(zmm8, zmm2, zmm10)); + TEST_INSTRUCTION("6251EDCFF4C2" , k(k7).z().vpmuludq(zmm8, zmm2, zmm10)); + TEST_INSTRUCTION("6271ED48F401" , vpmuludq(zmm8, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231ED48F484F034120000" , vpmuludq(zmm8, zmm2, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271ED58F401" , vpmuludq(zmm8, zmm2, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271ED48F4427F" , vpmuludq(zmm8, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271ED48F48200200000" , vpmuludq(zmm8, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271ED48F44280" , vpmuludq(zmm8, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271ED48F482C0DFFFFF" , vpmuludq(zmm8, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271ED58F4427F" , vpmuludq(zmm8, zmm2, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271ED58F48200040000" , vpmuludq(zmm8, zmm2, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271ED58F44280" , vpmuludq(zmm8, zmm2, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271ED58F482F8FBFFFF" , vpmuludq(zmm8, zmm2, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62412D48EBEF" , vpord(zmm29, zmm10, zmm15)); + TEST_INSTRUCTION("62412D4CEBEF" , k(k4).vpord(zmm29, zmm10, zmm15)); + TEST_INSTRUCTION("62412DCCEBEF" , k(k4).z().vpord(zmm29, zmm10, zmm15)); + TEST_INSTRUCTION("62612D48EB29" , vpord(zmm29, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62212D48EBACF034120000" , vpord(zmm29, zmm10, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62612D58EB29" , vpord(zmm29, zmm10, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62612D48EB6A7F" , vpord(zmm29, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62612D48EBAA00200000" , vpord(zmm29, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62612D48EB6A80" , vpord(zmm29, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62612D48EBAAC0DFFFFF" , vpord(zmm29, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62612D58EB6A7F" , vpord(zmm29, zmm10, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62612D58EBAA00020000" , vpord(zmm29, zmm10, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62612D58EB6A80" , vpord(zmm29, zmm10, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62612D58EBAAFCFDFFFF" , vpord(zmm29, zmm10, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6291C540EBDA" , vporq(zmm3, zmm23, zmm26)); + TEST_INSTRUCTION("6291C544EBDA" , k(k4).vporq(zmm3, zmm23, zmm26)); + TEST_INSTRUCTION("6291C5C4EBDA" , k(k4).z().vporq(zmm3, zmm23, zmm26)); + TEST_INSTRUCTION("62F1C540EB19" , vporq(zmm3, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1C540EB9CF034120000" , vporq(zmm3, zmm23, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1C550EB19" , vporq(zmm3, zmm23, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1C540EB5A7F" , vporq(zmm3, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1C540EB9A00200000" , vporq(zmm3, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1C540EB5A80" , vporq(zmm3, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1C540EB9AC0DFFFFF" , vporq(zmm3, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1C550EB5A7F" , vporq(zmm3, zmm23, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1C550EB9A00040000" , vporq(zmm3, zmm23, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1C550EB5A80" , vporq(zmm3, zmm23, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1C550EB9AF8FBFFFF" , vporq(zmm3, zmm23, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D17D4870FCAB" , vpshufd(zmm7, zmm12, 171)); + TEST_INSTRUCTION("62D17D4970FCAB" , k(k1).vpshufd(zmm7, zmm12, 171)); + TEST_INSTRUCTION("62D17DC970FCAB" , k(k1).z().vpshufd(zmm7, zmm12, 171)); + TEST_INSTRUCTION("62D17D4870FC7B" , vpshufd(zmm7, zmm12, 123)); + TEST_INSTRUCTION("62F17D4870397B" , vpshufd(zmm7, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B17D4870BCF0341200007B" , vpshufd(zmm7, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F17D5870397B" , vpshufd(zmm7, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F17D48707A7F7B" , vpshufd(zmm7, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F17D4870BA002000007B" , vpshufd(zmm7, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F17D48707A807B" , vpshufd(zmm7, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F17D4870BAC0DFFFFF7B" , vpshufd(zmm7, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F17D58707A7F7B" , vpshufd(zmm7, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F17D5870BA000200007B" , vpshufd(zmm7, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F17D58707A807B" , vpshufd(zmm7, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F17D5870BAFCFDFFFF7B" , vpshufd(zmm7, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D14D40F2FE" , vpslld(zmm7, zmm22, xmm14)); + TEST_INSTRUCTION("62D14D44F2FE" , k(k4).vpslld(zmm7, zmm22, xmm14)); + TEST_INSTRUCTION("62D14DC4F2FE" , k(k4).z().vpslld(zmm7, zmm22, xmm14)); + TEST_INSTRUCTION("62F14D40F239" , vpslld(zmm7, zmm22, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62B14D40F2BCF034120000" , vpslld(zmm7, zmm22, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F14D40F27A7F" , vpslld(zmm7, zmm22, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62F14D40F2BA00080000" , vpslld(zmm7, zmm22, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62F14D40F27A80" , vpslld(zmm7, zmm22, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62F14D40F2BAF0F7FFFF" , vpslld(zmm7, zmm22, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6201ED48F3EB" , vpsllq(zmm29, zmm2, xmm27)); + TEST_INSTRUCTION("6201ED4DF3EB" , k(k5).vpsllq(zmm29, zmm2, xmm27)); + TEST_INSTRUCTION("6201EDCDF3EB" , k(k5).z().vpsllq(zmm29, zmm2, xmm27)); + TEST_INSTRUCTION("6261ED48F329" , vpsllq(zmm29, zmm2, xmmword_ptr(rcx))); + TEST_INSTRUCTION("6221ED48F3ACF034120000" , vpsllq(zmm29, zmm2, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261ED48F36A7F" , vpsllq(zmm29, zmm2, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("6261ED48F3AA00080000" , vpsllq(zmm29, zmm2, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("6261ED48F36A80" , vpsllq(zmm29, zmm2, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("6261ED48F3AAF0F7FFFF" , vpsllq(zmm29, zmm2, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("6242654847EF" , vpsllvd(zmm29, zmm3, zmm15)); + TEST_INSTRUCTION("6242654F47EF" , k(k7).vpsllvd(zmm29, zmm3, zmm15)); + TEST_INSTRUCTION("624265CF47EF" , k(k7).z().vpsllvd(zmm29, zmm3, zmm15)); + TEST_INSTRUCTION("626265484729" , vpsllvd(zmm29, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222654847ACF034120000" , vpsllvd(zmm29, zmm3, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626265584729" , vpsllvd(zmm29, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62626548476A7F" , vpsllvd(zmm29, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262654847AA00200000" , vpsllvd(zmm29, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62626548476A80" , vpsllvd(zmm29, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262654847AAC0DFFFFF" , vpsllvd(zmm29, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62626558476A7F" , vpsllvd(zmm29, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("6262655847AA00020000" , vpsllvd(zmm29, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62626558476A80" , vpsllvd(zmm29, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("6262655847AAFCFDFFFF" , vpsllvd(zmm29, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D2954047E5" , vpsllvq(zmm4, zmm29, zmm13)); + TEST_INSTRUCTION("62D2954547E5" , k(k5).vpsllvq(zmm4, zmm29, zmm13)); + TEST_INSTRUCTION("62D295C547E5" , k(k5).z().vpsllvq(zmm4, zmm29, zmm13)); + TEST_INSTRUCTION("62F295404721" , vpsllvq(zmm4, zmm29, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2954047A4F034120000" , vpsllvq(zmm4, zmm29, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F295504721" , vpsllvq(zmm4, zmm29, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2954047627F" , vpsllvq(zmm4, zmm29, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2954047A200200000" , vpsllvq(zmm4, zmm29, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F29540476280" , vpsllvq(zmm4, zmm29, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2954047A2C0DFFFFF" , vpsllvq(zmm4, zmm29, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2955047627F" , vpsllvq(zmm4, zmm29, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2955047A200040000" , vpsllvq(zmm4, zmm29, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F29550476280" , vpsllvq(zmm4, zmm29, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2955047A2F8FBFFFF" , vpsllvq(zmm4, zmm29, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62812D48E2D9" , vpsrad(zmm19, zmm10, xmm25)); + TEST_INSTRUCTION("62812D4AE2D9" , k(k2).vpsrad(zmm19, zmm10, xmm25)); + TEST_INSTRUCTION("62812DCAE2D9" , k(k2).z().vpsrad(zmm19, zmm10, xmm25)); + TEST_INSTRUCTION("62E12D48E219" , vpsrad(zmm19, zmm10, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A12D48E29CF034120000" , vpsrad(zmm19, zmm10, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E12D48E25A7F" , vpsrad(zmm19, zmm10, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E12D48E29A00080000" , vpsrad(zmm19, zmm10, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E12D48E25A80" , vpsrad(zmm19, zmm10, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E12D48E29AF0F7FFFF" , vpsrad(zmm19, zmm10, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62A1C540E2FA" , vpsraq(zmm23, zmm23, xmm18)); + TEST_INSTRUCTION("62A1C544E2FA" , k(k4).vpsraq(zmm23, zmm23, xmm18)); + TEST_INSTRUCTION("62A1C5C4E2FA" , k(k4).z().vpsraq(zmm23, zmm23, xmm18)); + TEST_INSTRUCTION("62E1C540E239" , vpsraq(zmm23, zmm23, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1C540E2BCF034120000" , vpsraq(zmm23, zmm23, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1C540E27A7F" , vpsraq(zmm23, zmm23, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E1C540E2BA00080000" , vpsraq(zmm23, zmm23, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E1C540E27A80" , vpsraq(zmm23, zmm23, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E1C540E2BAF0F7FFFF" , vpsraq(zmm23, zmm23, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62E2554846CE" , vpsravd(zmm17, zmm5, zmm6)); + TEST_INSTRUCTION("62E2554E46CE" , k(k6).vpsravd(zmm17, zmm5, zmm6)); + TEST_INSTRUCTION("62E255CE46CE" , k(k6).z().vpsravd(zmm17, zmm5, zmm6)); + TEST_INSTRUCTION("62E255484609" , vpsravd(zmm17, zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A25548468CF034120000" , vpsravd(zmm17, zmm5, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E255584609" , vpsravd(zmm17, zmm5, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E25548464A7F" , vpsravd(zmm17, zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E25548468A00200000" , vpsravd(zmm17, zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E25548464A80" , vpsravd(zmm17, zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E25548468AC0DFFFFF" , vpsravd(zmm17, zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E25558464A7F" , vpsravd(zmm17, zmm5, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E25558468A00020000" , vpsravd(zmm17, zmm5, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E25558464A80" , vpsravd(zmm17, zmm5, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E25558468AFCFDFFFF" , vpsravd(zmm17, zmm5, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6292BD4846DA" , vpsravq(zmm3, zmm8, zmm26)); + TEST_INSTRUCTION("6292BD4946DA" , k(k1).vpsravq(zmm3, zmm8, zmm26)); + TEST_INSTRUCTION("6292BDC946DA" , k(k1).z().vpsravq(zmm3, zmm8, zmm26)); + TEST_INSTRUCTION("62F2BD484619" , vpsravq(zmm3, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2BD48469CF034120000" , vpsravq(zmm3, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2BD584619" , vpsravq(zmm3, zmm8, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2BD48465A7F" , vpsravq(zmm3, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2BD48469A00200000" , vpsravq(zmm3, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2BD48465A80" , vpsravq(zmm3, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2BD48469AC0DFFFFF" , vpsravq(zmm3, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2BD58465A7F" , vpsravq(zmm3, zmm8, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2BD58469A00040000" , vpsravq(zmm3, zmm8, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2BD58465A80" , vpsravq(zmm3, zmm8, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2BD58469AF8FBFFFF" , vpsravq(zmm3, zmm8, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62216540D2CF" , vpsrld(zmm25, zmm19, xmm23)); + TEST_INSTRUCTION("62216546D2CF" , k(k6).vpsrld(zmm25, zmm19, xmm23)); + TEST_INSTRUCTION("622165C6D2CF" , k(k6).z().vpsrld(zmm25, zmm19, xmm23)); + TEST_INSTRUCTION("62616540D209" , vpsrld(zmm25, zmm19, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62216540D28CF034120000" , vpsrld(zmm25, zmm19, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62616540D24A7F" , vpsrld(zmm25, zmm19, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62616540D28A00080000" , vpsrld(zmm25, zmm19, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62616540D24A80" , vpsrld(zmm25, zmm19, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62616540D28AF0F7FFFF" , vpsrld(zmm25, zmm19, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62A1AD48D3DD" , vpsrlq(zmm19, zmm10, xmm21)); + TEST_INSTRUCTION("62A1AD4CD3DD" , k(k4).vpsrlq(zmm19, zmm10, xmm21)); + TEST_INSTRUCTION("62A1ADCCD3DD" , k(k4).z().vpsrlq(zmm19, zmm10, xmm21)); + TEST_INSTRUCTION("62E1AD48D319" , vpsrlq(zmm19, zmm10, xmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1AD48D39CF034120000" , vpsrlq(zmm19, zmm10, xmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1AD48D35A7F" , vpsrlq(zmm19, zmm10, xmmword_ptr(rdx, 2032))); + TEST_INSTRUCTION("62E1AD48D39A00080000" , vpsrlq(zmm19, zmm10, xmmword_ptr(rdx, 2048))); + TEST_INSTRUCTION("62E1AD48D35A80" , vpsrlq(zmm19, zmm10, xmmword_ptr(rdx, -2048))); + TEST_INSTRUCTION("62E1AD48D39AF0F7FFFF" , vpsrlq(zmm19, zmm10, xmmword_ptr(rdx, -2064))); + TEST_INSTRUCTION("62D25D4845D3" , vpsrlvd(zmm2, zmm4, zmm11)); + TEST_INSTRUCTION("62D25D4F45D3" , k(k7).vpsrlvd(zmm2, zmm4, zmm11)); + TEST_INSTRUCTION("62D25DCF45D3" , k(k7).z().vpsrlvd(zmm2, zmm4, zmm11)); + TEST_INSTRUCTION("62F25D484511" , vpsrlvd(zmm2, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B25D484594F034120000" , vpsrlvd(zmm2, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F25D584511" , vpsrlvd(zmm2, zmm4, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F25D4845527F" , vpsrlvd(zmm2, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F25D48459200200000" , vpsrlvd(zmm2, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F25D48455280" , vpsrlvd(zmm2, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F25D484592C0DFFFFF" , vpsrlvd(zmm2, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F25D5845527F" , vpsrlvd(zmm2, zmm4, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F25D58459200020000" , vpsrlvd(zmm2, zmm4, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F25D58455280" , vpsrlvd(zmm2, zmm4, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F25D584592FCFDFFFF" , vpsrlvd(zmm2, zmm4, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62529D4045C7" , vpsrlvq(zmm8, zmm28, zmm15)); + TEST_INSTRUCTION("62529D4545C7" , k(k5).vpsrlvq(zmm8, zmm28, zmm15)); + TEST_INSTRUCTION("62529DC545C7" , k(k5).z().vpsrlvq(zmm8, zmm28, zmm15)); + TEST_INSTRUCTION("62729D404501" , vpsrlvq(zmm8, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62329D404584F034120000" , vpsrlvq(zmm8, zmm28, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62729D504501" , vpsrlvq(zmm8, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62729D4045427F" , vpsrlvq(zmm8, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62729D40458200200000" , vpsrlvq(zmm8, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62729D40454280" , vpsrlvq(zmm8, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62729D404582C0DFFFFF" , vpsrlvq(zmm8, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62729D5045427F" , vpsrlvq(zmm8, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62729D50458200040000" , vpsrlvq(zmm8, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62729D50454280" , vpsrlvq(zmm8, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62729D504582F8FBFFFF" , vpsrlvq(zmm8, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D1254872D1AB" , vpsrld(zmm11, zmm9, 171)); + TEST_INSTRUCTION("62D1254E72D1AB" , k(k6).vpsrld(zmm11, zmm9, 171)); + TEST_INSTRUCTION("62D125CE72D1AB" , k(k6).z().vpsrld(zmm11, zmm9, 171)); + TEST_INSTRUCTION("62D1254872D17B" , vpsrld(zmm11, zmm9, 123)); + TEST_INSTRUCTION("62F1254872117B" , vpsrld(zmm11, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B125487294F0341200007B" , vpsrld(zmm11, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1255872117B" , vpsrld(zmm11, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1254872527F7B" , vpsrld(zmm11, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F125487292002000007B" , vpsrld(zmm11, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F125487252807B" , vpsrld(zmm11, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F125487292C0DFFFFF7B" , vpsrld(zmm11, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1255872527F7B" , vpsrld(zmm11, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F125587292000200007B" , vpsrld(zmm11, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F125587252807B" , vpsrld(zmm11, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F125587292FCFDFFFF7B" , vpsrld(zmm11, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62D1CD4873D6AB" , vpsrlq(zmm6, zmm14, 171)); + TEST_INSTRUCTION("62D1CD4D73D6AB" , k(k5).vpsrlq(zmm6, zmm14, 171)); + TEST_INSTRUCTION("62D1CDCD73D6AB" , k(k5).z().vpsrlq(zmm6, zmm14, 171)); + TEST_INSTRUCTION("62D1CD4873D67B" , vpsrlq(zmm6, zmm14, 123)); + TEST_INSTRUCTION("62F1CD4873117B" , vpsrlq(zmm6, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1CD487394F0341200007B" , vpsrlq(zmm6, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1CD5873117B" , vpsrlq(zmm6, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD4873527F7B" , vpsrlq(zmm6, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1CD487392002000007B" , vpsrlq(zmm6, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1CD487352807B" , vpsrlq(zmm6, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1CD487392C0DFFFFF7B" , vpsrlq(zmm6, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1CD5873527F7B" , vpsrlq(zmm6, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD587392000400007B" , vpsrlq(zmm6, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD587352807B" , vpsrlq(zmm6, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1CD587392F8FBFFFF7B" , vpsrlq(zmm6, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62210D48FAD7" , vpsubd(zmm26, zmm14, zmm23)); + TEST_INSTRUCTION("62210D4FFAD7" , k(k7).vpsubd(zmm26, zmm14, zmm23)); + TEST_INSTRUCTION("62210DCFFAD7" , k(k7).z().vpsubd(zmm26, zmm14, zmm23)); + TEST_INSTRUCTION("62610D48FA11" , vpsubd(zmm26, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62210D48FA94F034120000" , vpsubd(zmm26, zmm14, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62610D58FA11" , vpsubd(zmm26, zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62610D48FA527F" , vpsubd(zmm26, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62610D48FA9200200000" , vpsubd(zmm26, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62610D48FA5280" , vpsubd(zmm26, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62610D48FA92C0DFFFFF" , vpsubd(zmm26, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62610D58FA527F" , vpsubd(zmm26, zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62610D58FA9200020000" , vpsubd(zmm26, zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62610D58FA5280" , vpsubd(zmm26, zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62610D58FA92FCFDFFFF" , vpsubd(zmm26, zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A1BD48FBC7" , vpsubq(zmm16, zmm8, zmm23)); + TEST_INSTRUCTION("62A1BD4FFBC7" , k(k7).vpsubq(zmm16, zmm8, zmm23)); + TEST_INSTRUCTION("62A1BDCFFBC7" , k(k7).z().vpsubq(zmm16, zmm8, zmm23)); + TEST_INSTRUCTION("62E1BD48FB01" , vpsubq(zmm16, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1BD48FB84F034120000" , vpsubq(zmm16, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1BD58FB01" , vpsubq(zmm16, zmm8, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1BD48FB427F" , vpsubq(zmm16, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1BD48FB8200200000" , vpsubq(zmm16, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1BD48FB4280" , vpsubq(zmm16, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1BD48FB82C0DFFFFF" , vpsubq(zmm16, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1BD58FB427F" , vpsubq(zmm16, zmm8, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1BD58FB8200040000" , vpsubq(zmm16, zmm8, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1BD58FB4280" , vpsubq(zmm16, zmm8, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1BD58FB82F8FBFFFF" , vpsubq(zmm16, zmm8, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62923D4027D0" , vptestmd(k2, zmm24, zmm24)); + TEST_INSTRUCTION("62923D4227D0" , k(k2).vptestmd(k2, zmm24, zmm24)); + TEST_INSTRUCTION("62F23D402711" , vptestmd(k2, zmm24, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B23D402794F034120000" , vptestmd(k2, zmm24, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F23D502711" , vptestmd(k2, zmm24, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F23D4027527F" , vptestmd(k2, zmm24, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F23D40279200200000" , vptestmd(k2, zmm24, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F23D40275280" , vptestmd(k2, zmm24, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F23D402792C0DFFFFF" , vptestmd(k2, zmm24, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F23D5027527F" , vptestmd(k2, zmm24, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F23D50279200020000" , vptestmd(k2, zmm24, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F23D50275280" , vptestmd(k2, zmm24, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F23D502792FCFDFFFF" , vptestmd(k2, zmm24, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B2854827E4" , vptestmq(k4, zmm15, zmm20)); + TEST_INSTRUCTION("62B2854A27E4" , k(k2).vptestmq(k4, zmm15, zmm20)); + TEST_INSTRUCTION("62F285482721" , vptestmq(k4, zmm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2854827A4F034120000" , vptestmq(k4, zmm15, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F285582721" , vptestmq(k4, zmm15, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2854827627F" , vptestmq(k4, zmm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2854827A200200000" , vptestmq(k4, zmm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F28548276280" , vptestmq(k4, zmm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2854827A2C0DFFFFF" , vptestmq(k4, zmm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2855827627F" , vptestmq(k4, zmm15, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2855827A200040000" , vptestmq(k4, zmm15, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F28558276280" , vptestmq(k4, zmm15, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2855827A2F8FBFFFF" , vptestmq(k4, zmm15, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62714D486ADF" , vpunpckhdq(zmm11, zmm6, zmm7)); + TEST_INSTRUCTION("62714D4B6ADF" , k(k3).vpunpckhdq(zmm11, zmm6, zmm7)); + TEST_INSTRUCTION("62714DCB6ADF" , k(k3).z().vpunpckhdq(zmm11, zmm6, zmm7)); + TEST_INSTRUCTION("62714D486A19" , vpunpckhdq(zmm11, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62314D486A9CF034120000" , vpunpckhdq(zmm11, zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62714D586A19" , vpunpckhdq(zmm11, zmm6, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62714D486A5A7F" , vpunpckhdq(zmm11, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62714D486A9A00200000" , vpunpckhdq(zmm11, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62714D486A5A80" , vpunpckhdq(zmm11, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62714D486A9AC0DFFFFF" , vpunpckhdq(zmm11, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62714D586A5A7F" , vpunpckhdq(zmm11, zmm6, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62714D586A9A00020000" , vpunpckhdq(zmm11, zmm6, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62714D586A5A80" , vpunpckhdq(zmm11, zmm6, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62714D586A9AFCFDFFFF" , vpunpckhdq(zmm11, zmm6, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6211CD486DC2" , vpunpckhqdq(zmm8, zmm6, zmm26)); + TEST_INSTRUCTION("6211CD4E6DC2" , k(k6).vpunpckhqdq(zmm8, zmm6, zmm26)); + TEST_INSTRUCTION("6211CDCE6DC2" , k(k6).z().vpunpckhqdq(zmm8, zmm6, zmm26)); + TEST_INSTRUCTION("6271CD486D01" , vpunpckhqdq(zmm8, zmm6, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231CD486D84F034120000" , vpunpckhqdq(zmm8, zmm6, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271CD586D01" , vpunpckhqdq(zmm8, zmm6, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271CD486D427F" , vpunpckhqdq(zmm8, zmm6, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271CD486D8200200000" , vpunpckhqdq(zmm8, zmm6, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271CD486D4280" , vpunpckhqdq(zmm8, zmm6, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271CD486D82C0DFFFFF" , vpunpckhqdq(zmm8, zmm6, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271CD586D427F" , vpunpckhqdq(zmm8, zmm6, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271CD586D8200040000" , vpunpckhqdq(zmm8, zmm6, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271CD586D4280" , vpunpckhqdq(zmm8, zmm6, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271CD586D82F8FBFFFF" , vpunpckhqdq(zmm8, zmm6, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62C16D4062C5" , vpunpckldq(zmm16, zmm18, zmm13)); + TEST_INSTRUCTION("62C16D4762C5" , k(k7).vpunpckldq(zmm16, zmm18, zmm13)); + TEST_INSTRUCTION("62C16DC762C5" , k(k7).z().vpunpckldq(zmm16, zmm18, zmm13)); + TEST_INSTRUCTION("62E16D406201" , vpunpckldq(zmm16, zmm18, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A16D406284F034120000" , vpunpckldq(zmm16, zmm18, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E16D506201" , vpunpckldq(zmm16, zmm18, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E16D4062427F" , vpunpckldq(zmm16, zmm18, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E16D40628200200000" , vpunpckldq(zmm16, zmm18, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E16D40624280" , vpunpckldq(zmm16, zmm18, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E16D406282C0DFFFFF" , vpunpckldq(zmm16, zmm18, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E16D5062427F" , vpunpckldq(zmm16, zmm18, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E16D50628200020000" , vpunpckldq(zmm16, zmm18, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E16D50624280" , vpunpckldq(zmm16, zmm18, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E16D506282FCFDFFFF" , vpunpckldq(zmm16, zmm18, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C1FD406CC9" , vpunpcklqdq(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C1FD456CC9" , k(k5).vpunpcklqdq(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62C1FDC56CC9" , k(k5).z().vpunpcklqdq(zmm17, zmm16, zmm9)); + TEST_INSTRUCTION("62E1FD406C09" , vpunpcklqdq(zmm17, zmm16, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD406C8CF034120000" , vpunpcklqdq(zmm17, zmm16, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1FD506C09" , vpunpcklqdq(zmm17, zmm16, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1FD406C4A7F" , vpunpcklqdq(zmm17, zmm16, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FD406C8A00200000" , vpunpcklqdq(zmm17, zmm16, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FD406C4A80" , vpunpcklqdq(zmm17, zmm16, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FD406C8AC0DFFFFF" , vpunpcklqdq(zmm17, zmm16, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FD506C4A7F" , vpunpcklqdq(zmm17, zmm16, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1FD506C8A00040000" , vpunpcklqdq(zmm17, zmm16, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1FD506C4A80" , vpunpcklqdq(zmm17, zmm16, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1FD506C8AF8FBFFFF" , vpunpcklqdq(zmm17, zmm16, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62916548EFE9" , vpxord(zmm5, zmm3, zmm25)); + TEST_INSTRUCTION("6291654BEFE9" , k(k3).vpxord(zmm5, zmm3, zmm25)); + TEST_INSTRUCTION("629165CBEFE9" , k(k3).z().vpxord(zmm5, zmm3, zmm25)); + TEST_INSTRUCTION("62F16548EF29" , vpxord(zmm5, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B16548EFACF034120000" , vpxord(zmm5, zmm3, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F16558EF29" , vpxord(zmm5, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F16548EF6A7F" , vpxord(zmm5, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F16548EFAA00200000" , vpxord(zmm5, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F16548EF6A80" , vpxord(zmm5, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F16548EFAAC0DFFFFF" , vpxord(zmm5, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F16558EF6A7F" , vpxord(zmm5, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F16558EFAA00020000" , vpxord(zmm5, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F16558EF6A80" , vpxord(zmm5, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F16558EFAAFCFDFFFF" , vpxord(zmm5, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6231DD48EFD2" , vpxorq(zmm10, zmm4, zmm18)); + TEST_INSTRUCTION("6231DD4CEFD2" , k(k4).vpxorq(zmm10, zmm4, zmm18)); + TEST_INSTRUCTION("6231DDCCEFD2" , k(k4).z().vpxorq(zmm10, zmm4, zmm18)); + TEST_INSTRUCTION("6271DD48EF11" , vpxorq(zmm10, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231DD48EF94F034120000" , vpxorq(zmm10, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271DD58EF11" , vpxorq(zmm10, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271DD48EF527F" , vpxorq(zmm10, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271DD48EF9200200000" , vpxorq(zmm10, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271DD48EF5280" , vpxorq(zmm10, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271DD48EF92C0DFFFFF" , vpxorq(zmm10, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271DD58EF527F" , vpxorq(zmm10, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271DD58EF9200040000" , vpxorq(zmm10, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271DD58EF5280" , vpxorq(zmm10, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271DD58EF92F8FBFFFF" , vpxorq(zmm10, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6242FD484CD2" , vrcp14pd(zmm26, zmm10)); + TEST_INSTRUCTION("6242FD4E4CD2" , k(k6).vrcp14pd(zmm26, zmm10)); + TEST_INSTRUCTION("6242FDCE4CD2" , k(k6).z().vrcp14pd(zmm26, zmm10)); + TEST_INSTRUCTION("6262FD484C11" , vrcp14pd(zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222FD484C94F034120000" , vrcp14pd(zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262FD584C11" , vrcp14pd(zmm26, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262FD484C527F" , vrcp14pd(zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262FD484C9200200000" , vrcp14pd(zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262FD484C5280" , vrcp14pd(zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262FD484C92C0DFFFFF" , vrcp14pd(zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262FD584C527F" , vrcp14pd(zmm26, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262FD584C9200040000" , vrcp14pd(zmm26, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262FD584C5280" , vrcp14pd(zmm26, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262FD584C92F8FBFFFF" , vrcp14pd(zmm26, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62927D484CDB" , vrcp14ps(zmm3, zmm27)); + TEST_INSTRUCTION("62927D4D4CDB" , k(k5).vrcp14ps(zmm3, zmm27)); + TEST_INSTRUCTION("62927DCD4CDB" , k(k5).z().vrcp14ps(zmm3, zmm27)); + TEST_INSTRUCTION("62F27D484C19" , vrcp14ps(zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D484C9CF034120000" , vrcp14ps(zmm3, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D584C19" , vrcp14ps(zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27D484C5A7F" , vrcp14ps(zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27D484C9A00200000" , vrcp14ps(zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27D484C5A80" , vrcp14ps(zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27D484C9AC0DFFFFF" , vrcp14ps(zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27D584C5A7F" , vrcp14ps(zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27D584C9A00020000" , vrcp14ps(zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27D584C5A80" , vrcp14ps(zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27D584C9AFCFDFFFF" , vrcp14ps(zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6272CD084DF7" , vrcp14sd(xmm14, xmm6, xmm7)); + TEST_INSTRUCTION("6272CD094DF7" , k(k1).vrcp14sd(xmm14, xmm6, xmm7)); + TEST_INSTRUCTION("6272CD894DF7" , k(k1).z().vrcp14sd(xmm14, xmm6, xmm7)); + TEST_INSTRUCTION("6272CD084D31" , vrcp14sd(xmm14, xmm6, qword_ptr(rcx))); + TEST_INSTRUCTION("6232CD084DB4F034120000" , vrcp14sd(xmm14, xmm6, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272CD084D727F" , vrcp14sd(xmm14, xmm6, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6272CD084DB200040000" , vrcp14sd(xmm14, xmm6, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6272CD084D7280" , vrcp14sd(xmm14, xmm6, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6272CD084DB2F8FBFFFF" , vrcp14sd(xmm14, xmm6, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("622275084DCD" , vrcp14ss(xmm25, xmm1, xmm21)); + TEST_INSTRUCTION("6222750A4DCD" , k(k2).vrcp14ss(xmm25, xmm1, xmm21)); + TEST_INSTRUCTION("6222758A4DCD" , k(k2).z().vrcp14ss(xmm25, xmm1, xmm21)); + TEST_INSTRUCTION("626275084D09" , vrcp14ss(xmm25, xmm1, dword_ptr(rcx))); + TEST_INSTRUCTION("622275084D8CF034120000" , vrcp14ss(xmm25, xmm1, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626275084D4A7F" , vrcp14ss(xmm25, xmm1, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("626275084D8A00020000" , vrcp14ss(xmm25, xmm1, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("626275084D4A80" , vrcp14ss(xmm25, xmm1, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("626275084D8AFCFDFFFF" , vrcp14ss(xmm25, xmm1, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6272FD484EF4" , vrsqrt14pd(zmm14, zmm4)); + TEST_INSTRUCTION("6272FD4F4EF4" , k(k7).vrsqrt14pd(zmm14, zmm4)); + TEST_INSTRUCTION("6272FDCF4EF4" , k(k7).z().vrsqrt14pd(zmm14, zmm4)); + TEST_INSTRUCTION("6272FD484E31" , vrsqrt14pd(zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232FD484EB4F034120000" , vrsqrt14pd(zmm14, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272FD584E31" , vrsqrt14pd(zmm14, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272FD484E727F" , vrsqrt14pd(zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272FD484EB200200000" , vrsqrt14pd(zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272FD484E7280" , vrsqrt14pd(zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272FD484EB2C0DFFFFF" , vrsqrt14pd(zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272FD584E727F" , vrsqrt14pd(zmm14, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272FD584EB200040000" , vrsqrt14pd(zmm14, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272FD584E7280" , vrsqrt14pd(zmm14, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272FD584EB2F8FBFFFF" , vrsqrt14pd(zmm14, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62927D484ED9" , vrsqrt14ps(zmm3, zmm25)); + TEST_INSTRUCTION("62927D4B4ED9" , k(k3).vrsqrt14ps(zmm3, zmm25)); + TEST_INSTRUCTION("62927DCB4ED9" , k(k3).z().vrsqrt14ps(zmm3, zmm25)); + TEST_INSTRUCTION("62F27D484E19" , vrsqrt14ps(zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B27D484E9CF034120000" , vrsqrt14ps(zmm3, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F27D584E19" , vrsqrt14ps(zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F27D484E5A7F" , vrsqrt14ps(zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F27D484E9A00200000" , vrsqrt14ps(zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F27D484E5A80" , vrsqrt14ps(zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F27D484E9AC0DFFFFF" , vrsqrt14ps(zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F27D584E5A7F" , vrsqrt14ps(zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F27D584E9A00020000" , vrsqrt14ps(zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F27D584E5A80" , vrsqrt14ps(zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F27D584E9AFCFDFFFF" , vrsqrt14ps(zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2D5004FCB" , vrsqrt14sd(xmm1, xmm21, xmm3)); + TEST_INSTRUCTION("62F2D5024FCB" , k(k2).vrsqrt14sd(xmm1, xmm21, xmm3)); + TEST_INSTRUCTION("62F2D5824FCB" , k(k2).z().vrsqrt14sd(xmm1, xmm21, xmm3)); + TEST_INSTRUCTION("62F2D5004F09" , vrsqrt14sd(xmm1, xmm21, qword_ptr(rcx))); + TEST_INSTRUCTION("62B2D5004F8CF034120000" , vrsqrt14sd(xmm1, xmm21, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2D5004F4A7F" , vrsqrt14sd(xmm1, xmm21, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F2D5004F8A00040000" , vrsqrt14sd(xmm1, xmm21, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F2D5004F4A80" , vrsqrt14sd(xmm1, xmm21, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F2D5004F8AF8FBFFFF" , vrsqrt14sd(xmm1, xmm21, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62A22D004FDA" , vrsqrt14ss(xmm19, xmm26, xmm18)); + TEST_INSTRUCTION("62A22D034FDA" , k(k3).vrsqrt14ss(xmm19, xmm26, xmm18)); + TEST_INSTRUCTION("62A22D834FDA" , k(k3).z().vrsqrt14ss(xmm19, xmm26, xmm18)); + TEST_INSTRUCTION("62E22D004F19" , vrsqrt14ss(xmm19, xmm26, dword_ptr(rcx))); + TEST_INSTRUCTION("62A22D004F9CF034120000" , vrsqrt14ss(xmm19, xmm26, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E22D004F5A7F" , vrsqrt14ss(xmm19, xmm26, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E22D004F9A00020000" , vrsqrt14ss(xmm19, xmm26, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E22D004F5A80" , vrsqrt14ss(xmm19, xmm26, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E22D004F9AFCFDFFFF" , vrsqrt14ss(xmm19, xmm26, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6291AD48C6C9AB" , vshufpd(zmm1, zmm10, zmm25, 171)); + TEST_INSTRUCTION("6291AD4BC6C9AB" , k(k3).vshufpd(zmm1, zmm10, zmm25, 171)); + TEST_INSTRUCTION("6291ADCBC6C9AB" , k(k3).z().vshufpd(zmm1, zmm10, zmm25, 171)); + TEST_INSTRUCTION("6291AD48C6C97B" , vshufpd(zmm1, zmm10, zmm25, 123)); + TEST_INSTRUCTION("62F1AD48C6097B" , vshufpd(zmm1, zmm10, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1AD48C68CF0341200007B" , vshufpd(zmm1, zmm10, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1AD58C6097B" , vshufpd(zmm1, zmm10, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1AD48C64A7F7B" , vshufpd(zmm1, zmm10, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1AD48C68A002000007B" , vshufpd(zmm1, zmm10, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1AD48C64A807B" , vshufpd(zmm1, zmm10, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1AD48C68AC0DFFFFF7B" , vshufpd(zmm1, zmm10, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1AD58C64A7F7B" , vshufpd(zmm1, zmm10, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1AD58C68A000400007B" , vshufpd(zmm1, zmm10, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1AD58C64A807B" , vshufpd(zmm1, zmm10, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1AD58C68AF8FBFFFF7B" , vshufpd(zmm1, zmm10, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62917448C6C9AB" , vshufps(zmm1, zmm1, zmm25, 171)); + TEST_INSTRUCTION("62917449C6C9AB" , k(k1).vshufps(zmm1, zmm1, zmm25, 171)); + TEST_INSTRUCTION("629174C9C6C9AB" , k(k1).z().vshufps(zmm1, zmm1, zmm25, 171)); + TEST_INSTRUCTION("62917448C6C97B" , vshufps(zmm1, zmm1, zmm25, 123)); + TEST_INSTRUCTION("62F17448C6097B" , vshufps(zmm1, zmm1, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B17448C68CF0341200007B" , vshufps(zmm1, zmm1, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F17458C6097B" , vshufps(zmm1, zmm1, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F17448C64A7F7B" , vshufps(zmm1, zmm1, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F17448C68A002000007B" , vshufps(zmm1, zmm1, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F17448C64A807B" , vshufps(zmm1, zmm1, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F17448C68AC0DFFFFF7B" , vshufps(zmm1, zmm1, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F17458C64A7F7B" , vshufps(zmm1, zmm1, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F17458C68A000200007B" , vshufps(zmm1, zmm1, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F17458C64A807B" , vshufps(zmm1, zmm1, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F17458C68AFCFDFFFF7B" , vshufps(zmm1, zmm1, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6271FD4851CD" , vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FD4A51CD" , k(k2).vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FDCA51CD" , k(k2).z().vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FD1851CD" , rn_sae().vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FD5851CD" , ru_sae().vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FD3851CD" , rd_sae().vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FD7851CD" , rz_sae().vsqrtpd(zmm9, zmm5)); + TEST_INSTRUCTION("6271FD485109" , vsqrtpd(zmm9, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6231FD48518CF034120000" , vsqrtpd(zmm9, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271FD585109" , vsqrtpd(zmm9, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6271FD48514A7F" , vsqrtpd(zmm9, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6271FD48518A00200000" , vsqrtpd(zmm9, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6271FD48514A80" , vsqrtpd(zmm9, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6271FD48518AC0DFFFFF" , vsqrtpd(zmm9, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6271FD58514A7F" , vsqrtpd(zmm9, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6271FD58518A00040000" , vsqrtpd(zmm9, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6271FD58514A80" , vsqrtpd(zmm9, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6271FD58518AF8FBFFFF" , vsqrtpd(zmm9, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B17C4851E7" , vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62B17C4E51E7" , k(k6).vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62B17CCE51E7" , k(k6).z().vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62B17C1851E7" , rn_sae().vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62B17C5851E7" , ru_sae().vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62B17C3851E7" , rd_sae().vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62B17C7851E7" , rz_sae().vsqrtps(zmm4, zmm23)); + TEST_INSTRUCTION("62F17C485121" , vsqrtps(zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17C4851A4F034120000" , vsqrtps(zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17C585121" , vsqrtps(zmm4, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F17C4851627F" , vsqrtps(zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17C4851A200200000" , vsqrtps(zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17C48516280" , vsqrtps(zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17C4851A2C0DFFFFF" , vsqrtps(zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F17C5851627F" , vsqrtps(zmm4, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F17C5851A200020000" , vsqrtps(zmm4, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F17C58516280" , vsqrtps(zmm4, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F17C5851A2FCFDFFFF" , vsqrtps(zmm4, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6271BF0051C5" , vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF0351C5" , k(k3).vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF8351C5" , k(k3).z().vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF1051C5" , rn_sae().vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF5051C5" , ru_sae().vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF3051C5" , rd_sae().vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF7051C5" , rz_sae().vsqrtsd(xmm8, xmm24, xmm5)); + TEST_INSTRUCTION("6271BF005101" , vsqrtsd(xmm8, xmm24, qword_ptr(rcx))); + TEST_INSTRUCTION("6231BF005184F034120000" , vsqrtsd(xmm8, xmm24, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271BF0051427F" , vsqrtsd(xmm8, xmm24, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271BF00518200040000" , vsqrtsd(xmm8, xmm24, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271BF00514280" , vsqrtsd(xmm8, xmm24, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271BF005182F8FBFFFF" , vsqrtsd(xmm8, xmm24, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62410E0851CB" , vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62410E0F51CB" , k(k7).vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62410E8F51CB" , k(k7).z().vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62410E1851CB" , rn_sae().vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62410E5851CB" , ru_sae().vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62410E3851CB" , rd_sae().vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62410E7851CB" , rz_sae().vsqrtss(xmm25, xmm14, xmm11)); + TEST_INSTRUCTION("62610E085109" , vsqrtss(xmm25, xmm14, dword_ptr(rcx))); + TEST_INSTRUCTION("62210E08518CF034120000" , vsqrtss(xmm25, xmm14, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62610E08514A7F" , vsqrtss(xmm25, xmm14, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62610E08518A00020000" , vsqrtss(xmm25, xmm14, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62610E08514A80" , vsqrtss(xmm25, xmm14, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62610E08518AFCFDFFFF" , vsqrtss(xmm25, xmm14, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62C19D405CE8" , vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62C19D415CE8" , k(k1).vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62C19DC15CE8" , k(k1).z().vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62C19D105CE8" , rn_sae().vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62C19D505CE8" , ru_sae().vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62C19D305CE8" , rd_sae().vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62C19D705CE8" , rz_sae().vsubpd(zmm21, zmm28, zmm8)); + TEST_INSTRUCTION("62E19D405C29" , vsubpd(zmm21, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A19D405CACF034120000" , vsubpd(zmm21, zmm28, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E19D505C29" , vsubpd(zmm21, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E19D405C6A7F" , vsubpd(zmm21, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E19D405CAA00200000" , vsubpd(zmm21, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E19D405C6A80" , vsubpd(zmm21, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E19D405CAAC0DFFFFF" , vsubpd(zmm21, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E19D505C6A7F" , vsubpd(zmm21, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E19D505CAA00040000" , vsubpd(zmm21, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E19D505C6A80" , vsubpd(zmm21, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E19D505CAAF8FBFFFF" , vsubpd(zmm21, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62E12C485CDD" , vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12C4F5CDD" , k(k7).vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12CCF5CDD" , k(k7).z().vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12C185CDD" , rn_sae().vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12C585CDD" , ru_sae().vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12C385CDD" , rd_sae().vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12C785CDD" , rz_sae().vsubps(zmm19, zmm10, zmm5)); + TEST_INSTRUCTION("62E12C485C19" , vsubps(zmm19, zmm10, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A12C485C9CF034120000" , vsubps(zmm19, zmm10, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E12C585C19" , vsubps(zmm19, zmm10, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E12C485C5A7F" , vsubps(zmm19, zmm10, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E12C485C9A00200000" , vsubps(zmm19, zmm10, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E12C485C5A80" , vsubps(zmm19, zmm10, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E12C485C9AC0DFFFFF" , vsubps(zmm19, zmm10, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E12C585C5A7F" , vsubps(zmm19, zmm10, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E12C585C9A00020000" , vsubps(zmm19, zmm10, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E12C585C5A80" , vsubps(zmm19, zmm10, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E12C585C9AFCFDFFFF" , vsubps(zmm19, zmm10, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6241C7005CC5" , vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6241C7075CC5" , k(k7).vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6241C7875CC5" , k(k7).z().vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6241C7105CC5" , rn_sae().vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6241C7505CC5" , ru_sae().vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6241C7305CC5" , rd_sae().vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6241C7705CC5" , rz_sae().vsubsd(xmm24, xmm23, xmm13)); + TEST_INSTRUCTION("6261C7005C01" , vsubsd(xmm24, xmm23, qword_ptr(rcx))); + TEST_INSTRUCTION("6221C7005C84F034120000" , vsubsd(xmm24, xmm23, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6261C7005C427F" , vsubsd(xmm24, xmm23, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6261C7005C8200040000" , vsubsd(xmm24, xmm23, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6261C7005C4280" , vsubsd(xmm24, xmm23, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6261C7005C82F8FBFFFF" , vsubsd(xmm24, xmm23, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62215E005CD8" , vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62215E065CD8" , k(k6).vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62215E865CD8" , k(k6).z().vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62215E105CD8" , rn_sae().vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62215E505CD8" , ru_sae().vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62215E305CD8" , rd_sae().vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62215E705CD8" , rz_sae().vsubss(xmm27, xmm20, xmm16)); + TEST_INSTRUCTION("62615E005C19" , vsubss(xmm27, xmm20, dword_ptr(rcx))); + TEST_INSTRUCTION("62215E005C9CF034120000" , vsubss(xmm27, xmm20, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62615E005C5A7F" , vsubss(xmm27, xmm20, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62615E005C9A00020000" , vsubss(xmm27, xmm20, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62615E005C5A80" , vsubss(xmm27, xmm20, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62615E005C9AFCFDFFFF" , vsubss(xmm27, xmm20, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62A1FD082EEB" , vucomisd(xmm21, xmm19)); + TEST_INSTRUCTION("62A1FD182EEB" , sae().vucomisd(xmm21, xmm19)); + TEST_INSTRUCTION("62E1FD082E29" , vucomisd(xmm21, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1FD082EACF034120000" , vucomisd(xmm21, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1FD082E6A7F" , vucomisd(xmm21, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1FD082EAA00040000" , vucomisd(xmm21, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1FD082E6A80" , vucomisd(xmm21, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1FD082EAAF8FBFFFF" , vucomisd(xmm21, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62017C082EDD" , vucomiss(xmm27, xmm29)); + TEST_INSTRUCTION("62017C182EDD" , sae().vucomiss(xmm27, xmm29)); + TEST_INSTRUCTION("62617C082E19" , vucomiss(xmm27, dword_ptr(rcx))); + TEST_INSTRUCTION("62217C082E9CF034120000" , vucomiss(xmm27, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62617C082E5A7F" , vucomiss(xmm27, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62617C082E9A00020000" , vucomiss(xmm27, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62617C082E5A80" , vucomiss(xmm27, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62617C082E9AFCFDFFFF" , vucomiss(xmm27, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62D1C54015F4" , vunpckhpd(zmm6, zmm23, zmm12)); + TEST_INSTRUCTION("62D1C54715F4" , k(k7).vunpckhpd(zmm6, zmm23, zmm12)); + TEST_INSTRUCTION("62D1C5C715F4" , k(k7).z().vunpckhpd(zmm6, zmm23, zmm12)); + TEST_INSTRUCTION("62F1C5401531" , vunpckhpd(zmm6, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B1C54015B4F034120000" , vunpckhpd(zmm6, zmm23, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1C5501531" , vunpckhpd(zmm6, zmm23, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F1C54015727F" , vunpckhpd(zmm6, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F1C54015B200200000" , vunpckhpd(zmm6, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F1C540157280" , vunpckhpd(zmm6, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F1C54015B2C0DFFFFF" , vunpckhpd(zmm6, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F1C55015727F" , vunpckhpd(zmm6, zmm23, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F1C55015B200040000" , vunpckhpd(zmm6, zmm23, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F1C550157280" , vunpckhpd(zmm6, zmm23, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F1C55015B2F8FBFFFF" , vunpckhpd(zmm6, zmm23, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62616C4815EC" , vunpckhps(zmm29, zmm2, zmm4)); + TEST_INSTRUCTION("62616C4C15EC" , k(k4).vunpckhps(zmm29, zmm2, zmm4)); + TEST_INSTRUCTION("62616CCC15EC" , k(k4).z().vunpckhps(zmm29, zmm2, zmm4)); + TEST_INSTRUCTION("62616C481529" , vunpckhps(zmm29, zmm2, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62216C4815ACF034120000" , vunpckhps(zmm29, zmm2, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62616C581529" , vunpckhps(zmm29, zmm2, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62616C48156A7F" , vunpckhps(zmm29, zmm2, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62616C4815AA00200000" , vunpckhps(zmm29, zmm2, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62616C48156A80" , vunpckhps(zmm29, zmm2, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62616C4815AAC0DFFFFF" , vunpckhps(zmm29, zmm2, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62616C58156A7F" , vunpckhps(zmm29, zmm2, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62616C5815AA00020000" , vunpckhps(zmm29, zmm2, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62616C58156A80" , vunpckhps(zmm29, zmm2, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62616C5815AAFCFDFFFF" , vunpckhps(zmm29, zmm2, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62C19D4014D0" , vunpcklpd(zmm18, zmm28, zmm8)); + TEST_INSTRUCTION("62C19D4114D0" , k(k1).vunpcklpd(zmm18, zmm28, zmm8)); + TEST_INSTRUCTION("62C19DC114D0" , k(k1).z().vunpcklpd(zmm18, zmm28, zmm8)); + TEST_INSTRUCTION("62E19D401411" , vunpcklpd(zmm18, zmm28, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A19D401494F034120000" , vunpcklpd(zmm18, zmm28, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E19D501411" , vunpcklpd(zmm18, zmm28, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E19D4014527F" , vunpcklpd(zmm18, zmm28, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E19D40149200200000" , vunpcklpd(zmm18, zmm28, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E19D40145280" , vunpcklpd(zmm18, zmm28, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E19D401492C0DFFFFF" , vunpcklpd(zmm18, zmm28, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E19D5014527F" , vunpcklpd(zmm18, zmm28, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E19D50149200040000" , vunpcklpd(zmm18, zmm28, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E19D50145280" , vunpcklpd(zmm18, zmm28, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E19D501492F8FBFFFF" , vunpcklpd(zmm18, zmm28, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62610C4814CE" , vunpcklps(zmm25, zmm14, zmm6)); + TEST_INSTRUCTION("62610C4E14CE" , k(k6).vunpcklps(zmm25, zmm14, zmm6)); + TEST_INSTRUCTION("62610CCE14CE" , k(k6).z().vunpcklps(zmm25, zmm14, zmm6)); + TEST_INSTRUCTION("62610C481409" , vunpcklps(zmm25, zmm14, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62210C48148CF034120000" , vunpcklps(zmm25, zmm14, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62610C581409" , vunpcklps(zmm25, zmm14, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62610C48144A7F" , vunpcklps(zmm25, zmm14, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62610C48148A00200000" , vunpcklps(zmm25, zmm14, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62610C48144A80" , vunpcklps(zmm25, zmm14, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62610C48148AC0DFFFFF" , vunpcklps(zmm25, zmm14, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62610C58144A7F" , vunpcklps(zmm25, zmm14, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62610C58148A00020000" , vunpcklps(zmm25, zmm14, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62610C58144A80" , vunpcklps(zmm25, zmm14, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62610C58148AFCFDFFFF" , vunpcklps(zmm25, zmm14, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6253154825D2AB" , vpternlogd(zmm10, zmm13, zmm10, 171)); + TEST_INSTRUCTION("6253154F25D2AB" , k(k7).vpternlogd(zmm10, zmm13, zmm10, 171)); + TEST_INSTRUCTION("625315CF25D2AB" , k(k7).z().vpternlogd(zmm10, zmm13, zmm10, 171)); + TEST_INSTRUCTION("6253154825D27B" , vpternlogd(zmm10, zmm13, zmm10, 123)); + TEST_INSTRUCTION("6273154825117B" , vpternlogd(zmm10, zmm13, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("623315482594F0341200007B" , vpternlogd(zmm10, zmm13, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6273155825117B" , vpternlogd(zmm10, zmm13, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("6273154825527F7B" , vpternlogd(zmm10, zmm13, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("627315482592002000007B" , vpternlogd(zmm10, zmm13, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("627315482552807B" , vpternlogd(zmm10, zmm13, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("627315482592C0DFFFFF7B" , vpternlogd(zmm10, zmm13, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273155825527F7B" , vpternlogd(zmm10, zmm13, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("627315582592000200007B" , vpternlogd(zmm10, zmm13, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("627315582552807B" , vpternlogd(zmm10, zmm13, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("627315582592FCFDFFFF7B" , vpternlogd(zmm10, zmm13, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62C39D4825C5AB" , vpternlogq(zmm16, zmm12, zmm13, 171)); + TEST_INSTRUCTION("62C39D4A25C5AB" , k(k2).vpternlogq(zmm16, zmm12, zmm13, 171)); + TEST_INSTRUCTION("62C39DCA25C5AB" , k(k2).z().vpternlogq(zmm16, zmm12, zmm13, 171)); + TEST_INSTRUCTION("62C39D4825C57B" , vpternlogq(zmm16, zmm12, zmm13, 123)); + TEST_INSTRUCTION("62E39D4825017B" , vpternlogq(zmm16, zmm12, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A39D482584F0341200007B" , vpternlogq(zmm16, zmm12, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62E39D5825017B" , vpternlogq(zmm16, zmm12, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62E39D4825427F7B" , vpternlogq(zmm16, zmm12, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62E39D482582002000007B" , vpternlogq(zmm16, zmm12, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62E39D482542807B" , vpternlogq(zmm16, zmm12, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62E39D482582C0DFFFFF7B" , vpternlogq(zmm16, zmm12, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62E39D5825427F7B" , vpternlogq(zmm16, zmm12, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62E39D582582000400007B" , vpternlogq(zmm16, zmm12, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62E39D582542807B" , vpternlogq(zmm16, zmm12, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62E39D582582F8FBFFFF7B" , vpternlogq(zmm16, zmm12, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62327E4832F7" , vpmovqb(xmm23, zmm14)); + TEST_INSTRUCTION("62327E4A32F7" , k(k2).vpmovqb(xmm23, zmm14)); + TEST_INSTRUCTION("62327ECA32F7" , k(k2).z().vpmovqb(xmm23, zmm14)); + TEST_INSTRUCTION("62227E4822CC" , vpmovsqb(xmm20, zmm25)); + TEST_INSTRUCTION("62227E4922CC" , k(k1).vpmovsqb(xmm20, zmm25)); + TEST_INSTRUCTION("62227EC922CC" , k(k1).z().vpmovsqb(xmm20, zmm25)); + TEST_INSTRUCTION("62D27E4812D0" , vpmovusqb(xmm8, zmm2)); + TEST_INSTRUCTION("62D27E4C12D0" , k(k4).vpmovusqb(xmm8, zmm2)); + TEST_INSTRUCTION("62D27ECC12D0" , k(k4).z().vpmovusqb(xmm8, zmm2)); + TEST_INSTRUCTION("62A27E4834DD" , vpmovqw(xmm21, zmm19)); + TEST_INSTRUCTION("62A27E4A34DD" , k(k2).vpmovqw(xmm21, zmm19)); + TEST_INSTRUCTION("62A27ECA34DD" , k(k2).z().vpmovqw(xmm21, zmm19)); + TEST_INSTRUCTION("62B27E4824E0" , vpmovsqw(xmm16, zmm4)); + TEST_INSTRUCTION("62B27E4E24E0" , k(k6).vpmovsqw(xmm16, zmm4)); + TEST_INSTRUCTION("62B27ECE24E0" , k(k6).z().vpmovsqw(xmm16, zmm4)); + TEST_INSTRUCTION("62927E4814CD" , vpmovusqw(xmm29, zmm1)); + TEST_INSTRUCTION("62927E4A14CD" , k(k2).vpmovusqw(xmm29, zmm1)); + TEST_INSTRUCTION("62927ECA14CD" , k(k2).z().vpmovusqw(xmm29, zmm1)); + TEST_INSTRUCTION("62027E4835EC" , vpmovqd(ymm28, zmm29)); + TEST_INSTRUCTION("62027E4A35EC" , k(k2).vpmovqd(ymm28, zmm29)); + TEST_INSTRUCTION("62027ECA35EC" , k(k2).z().vpmovqd(ymm28, zmm29)); + TEST_INSTRUCTION("62327E4825CE" , vpmovsqd(ymm22, zmm9)); + TEST_INSTRUCTION("62327E4C25CE" , k(k4).vpmovsqd(ymm22, zmm9)); + TEST_INSTRUCTION("62327ECC25CE" , k(k4).z().vpmovsqd(ymm22, zmm9)); + TEST_INSTRUCTION("62627E4815D2" , vpmovusqd(ymm2, zmm26)); + TEST_INSTRUCTION("62627E4F15D2" , k(k7).vpmovusqd(ymm2, zmm26)); + TEST_INSTRUCTION("62627ECF15D2" , k(k7).z().vpmovusqd(ymm2, zmm26)); + TEST_INSTRUCTION("62727E4831D9" , vpmovdb(xmm1, zmm11)); + TEST_INSTRUCTION("62727E4F31D9" , k(k7).vpmovdb(xmm1, zmm11)); + TEST_INSTRUCTION("62727ECF31D9" , k(k7).z().vpmovdb(xmm1, zmm11)); + TEST_INSTRUCTION("62927E4821CB" , vpmovsdb(xmm27, zmm1)); + TEST_INSTRUCTION("62927E4F21CB" , k(k7).vpmovsdb(xmm27, zmm1)); + TEST_INSTRUCTION("62927ECF21CB" , k(k7).z().vpmovsdb(xmm27, zmm1)); + TEST_INSTRUCTION("62E27E4811DB" , vpmovusdb(xmm3, zmm19)); + TEST_INSTRUCTION("62E27E4A11DB" , k(k2).vpmovusdb(xmm3, zmm19)); + TEST_INSTRUCTION("62E27ECA11DB" , k(k2).z().vpmovusdb(xmm3, zmm19)); + TEST_INSTRUCTION("62527E4833D1" , vpmovdw(ymm9, zmm10)); + TEST_INSTRUCTION("62527E4C33D1" , k(k4).vpmovdw(ymm9, zmm10)); + TEST_INSTRUCTION("62527ECC33D1" , k(k4).z().vpmovdw(ymm9, zmm10)); + TEST_INSTRUCTION("62027E4823C0" , vpmovsdw(ymm24, zmm24)); + TEST_INSTRUCTION("62027E4E23C0" , k(k6).vpmovsdw(ymm24, zmm24)); + TEST_INSTRUCTION("62027ECE23C0" , k(k6).z().vpmovsdw(ymm24, zmm24)); + TEST_INSTRUCTION("62C27E4813CF" , vpmovusdw(ymm15, zmm17)); + TEST_INSTRUCTION("62C27E4F13CF" , k(k7).vpmovusdw(ymm15, zmm17)); + TEST_INSTRUCTION("62C27ECF13CF" , k(k7).z().vpmovusdw(ymm15, zmm17)); + TEST_INSTRUCTION("62E3254823CCAB" , vshuff32x4(zmm17, zmm11, zmm4, 171)); + TEST_INSTRUCTION("62E3254E23CCAB" , k(k6).vshuff32x4(zmm17, zmm11, zmm4, 171)); + TEST_INSTRUCTION("62E325CE23CCAB" , k(k6).z().vshuff32x4(zmm17, zmm11, zmm4, 171)); + TEST_INSTRUCTION("62E3254823CC7B" , vshuff32x4(zmm17, zmm11, zmm4, 123)); + TEST_INSTRUCTION("62E3254823097B" , vshuff32x4(zmm17, zmm11, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62A32548238CF0341200007B" , vshuff32x4(zmm17, zmm11, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62E3255823097B" , vshuff32x4(zmm17, zmm11, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62E32548234A7F7B" , vshuff32x4(zmm17, zmm11, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62E32548238A002000007B" , vshuff32x4(zmm17, zmm11, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62E32548234A807B" , vshuff32x4(zmm17, zmm11, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62E32548238AC0DFFFFF7B" , vshuff32x4(zmm17, zmm11, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62E32558234A7F7B" , vshuff32x4(zmm17, zmm11, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62E32558238A000200007B" , vshuff32x4(zmm17, zmm11, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62E32558234A807B" , vshuff32x4(zmm17, zmm11, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62E32558238AFCFDFFFF7B" , vshuff32x4(zmm17, zmm11, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62939D4823F0AB" , vshuff64x2(zmm6, zmm12, zmm24, 171)); + TEST_INSTRUCTION("62939D4B23F0AB" , k(k3).vshuff64x2(zmm6, zmm12, zmm24, 171)); + TEST_INSTRUCTION("62939DCB23F0AB" , k(k3).z().vshuff64x2(zmm6, zmm12, zmm24, 171)); + TEST_INSTRUCTION("62939D4823F07B" , vshuff64x2(zmm6, zmm12, zmm24, 123)); + TEST_INSTRUCTION("62F39D4823317B" , vshuff64x2(zmm6, zmm12, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B39D4823B4F0341200007B" , vshuff64x2(zmm6, zmm12, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F39D5823317B" , vshuff64x2(zmm6, zmm12, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F39D4823727F7B" , vshuff64x2(zmm6, zmm12, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F39D4823B2002000007B" , vshuff64x2(zmm6, zmm12, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F39D482372807B" , vshuff64x2(zmm6, zmm12, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F39D4823B2C0DFFFFF7B" , vshuff64x2(zmm6, zmm12, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F39D5823727F7B" , vshuff64x2(zmm6, zmm12, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F39D5823B2000400007B" , vshuff64x2(zmm6, zmm12, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F39D582372807B" , vshuff64x2(zmm6, zmm12, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F39D5823B2F8FBFFFF7B" , vshuff64x2(zmm6, zmm12, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62F33D4043DDAB" , vshufi32x4(zmm3, zmm24, zmm5, 171)); + TEST_INSTRUCTION("62F33D4443DDAB" , k(k4).vshufi32x4(zmm3, zmm24, zmm5, 171)); + TEST_INSTRUCTION("62F33DC443DDAB" , k(k4).z().vshufi32x4(zmm3, zmm24, zmm5, 171)); + TEST_INSTRUCTION("62F33D4043DD7B" , vshufi32x4(zmm3, zmm24, zmm5, 123)); + TEST_INSTRUCTION("62F33D4043197B" , vshufi32x4(zmm3, zmm24, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B33D40439CF0341200007B" , vshufi32x4(zmm3, zmm24, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F33D5043197B" , vshufi32x4(zmm3, zmm24, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F33D40435A7F7B" , vshufi32x4(zmm3, zmm24, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F33D40439A002000007B" , vshufi32x4(zmm3, zmm24, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F33D40435A807B" , vshufi32x4(zmm3, zmm24, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F33D40439AC0DFFFFF7B" , vshufi32x4(zmm3, zmm24, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F33D50435A7F7B" , vshufi32x4(zmm3, zmm24, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F33D50439A000200007B" , vshufi32x4(zmm3, zmm24, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F33D50435A807B" , vshufi32x4(zmm3, zmm24, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F33D50439AFCFDFFFF7B" , vshufi32x4(zmm3, zmm24, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62438D4843F1AB" , vshufi64x2(zmm30, zmm14, zmm9, 171)); + TEST_INSTRUCTION("62438D4943F1AB" , k(k1).vshufi64x2(zmm30, zmm14, zmm9, 171)); + TEST_INSTRUCTION("62438DC943F1AB" , k(k1).z().vshufi64x2(zmm30, zmm14, zmm9, 171)); + TEST_INSTRUCTION("62438D4843F17B" , vshufi64x2(zmm30, zmm14, zmm9, 123)); + TEST_INSTRUCTION("62638D4843317B" , vshufi64x2(zmm30, zmm14, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62238D4843B4F0341200007B" , vshufi64x2(zmm30, zmm14, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62638D5843317B" , vshufi64x2(zmm30, zmm14, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62638D4843727F7B" , vshufi64x2(zmm30, zmm14, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62638D4843B2002000007B" , vshufi64x2(zmm30, zmm14, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62638D484372807B" , vshufi64x2(zmm30, zmm14, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62638D4843B2C0DFFFFF7B" , vshufi64x2(zmm30, zmm14, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62638D5843727F7B" , vshufi64x2(zmm30, zmm14, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62638D5843B2000400007B" , vshufi64x2(zmm30, zmm14, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62638D584372807B" , vshufi64x2(zmm30, zmm14, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62638D5843B2F8FBFFFF7B" , vshufi64x2(zmm30, zmm14, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62A2CD4036D3" , vpermq(zmm18, zmm22, zmm19)); + TEST_INSTRUCTION("62A2CD4736D3" , k(k7).vpermq(zmm18, zmm22, zmm19)); + TEST_INSTRUCTION("62A2CDC736D3" , k(k7).z().vpermq(zmm18, zmm22, zmm19)); + TEST_INSTRUCTION("62E2CD403611" , vpermq(zmm18, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2CD403694F034120000" , vpermq(zmm18, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2CD503611" , vpermq(zmm18, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2CD4036527F" , vpermq(zmm18, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2CD40369200200000" , vpermq(zmm18, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2CD40365280" , vpermq(zmm18, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2CD403692C0DFFFFF" , vpermq(zmm18, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2CD5036527F" , vpermq(zmm18, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2CD50369200040000" , vpermq(zmm18, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2CD50365280" , vpermq(zmm18, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2CD503692F8FBFFFF" , vpermq(zmm18, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62629D4816DA" , vpermpd(zmm27, zmm12, zmm2)); + TEST_INSTRUCTION("62629D4B16DA" , k(k3).vpermpd(zmm27, zmm12, zmm2)); + TEST_INSTRUCTION("62629DCB16DA" , k(k3).z().vpermpd(zmm27, zmm12, zmm2)); + TEST_INSTRUCTION("62629D481619" , vpermpd(zmm27, zmm12, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62229D48169CF034120000" , vpermpd(zmm27, zmm12, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62629D581619" , vpermpd(zmm27, zmm12, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62629D48165A7F" , vpermpd(zmm27, zmm12, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62629D48169A00200000" , vpermpd(zmm27, zmm12, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62629D48165A80" , vpermpd(zmm27, zmm12, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62629D48169AC0DFFFFF" , vpermpd(zmm27, zmm12, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62629D58165A7F" , vpermpd(zmm27, zmm12, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62629D58169A00040000" , vpermpd(zmm27, zmm12, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62629D58165A80" , vpermpd(zmm27, zmm12, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62629D58169AF8FBFFFF" , vpermpd(zmm27, zmm12, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("628205487ED9" , vpermt2d(zmm19, zmm15, zmm25)); + TEST_INSTRUCTION("6282054A7ED9" , k(k2).vpermt2d(zmm19, zmm15, zmm25)); + TEST_INSTRUCTION("628205CA7ED9" , k(k2).z().vpermt2d(zmm19, zmm15, zmm25)); + TEST_INSTRUCTION("62E205487E19" , vpermt2d(zmm19, zmm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A205487E9CF034120000" , vpermt2d(zmm19, zmm15, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E205587E19" , vpermt2d(zmm19, zmm15, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62E205487E5A7F" , vpermt2d(zmm19, zmm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E205487E9A00200000" , vpermt2d(zmm19, zmm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E205487E5A80" , vpermt2d(zmm19, zmm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E205487E9AC0DFFFFF" , vpermt2d(zmm19, zmm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E205587E5A7F" , vpermt2d(zmm19, zmm15, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62E205587E9A00020000" , vpermt2d(zmm19, zmm15, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62E205587E5A80" , vpermt2d(zmm19, zmm15, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62E205587E9AFCFDFFFF" , vpermt2d(zmm19, zmm15, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62F2D5407ED4" , vpermt2q(zmm2, zmm21, zmm4)); + TEST_INSTRUCTION("62F2D5477ED4" , k(k7).vpermt2q(zmm2, zmm21, zmm4)); + TEST_INSTRUCTION("62F2D5C77ED4" , k(k7).z().vpermt2q(zmm2, zmm21, zmm4)); + TEST_INSTRUCTION("62F2D5407E11" , vpermt2q(zmm2, zmm21, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2D5407E94F034120000" , vpermt2q(zmm2, zmm21, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2D5507E11" , vpermt2q(zmm2, zmm21, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2D5407E527F" , vpermt2q(zmm2, zmm21, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2D5407E9200200000" , vpermt2q(zmm2, zmm21, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2D5407E5280" , vpermt2q(zmm2, zmm21, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2D5407E92C0DFFFFF" , vpermt2q(zmm2, zmm21, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2D5507E527F" , vpermt2q(zmm2, zmm21, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2D5507E9200040000" , vpermt2q(zmm2, zmm21, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2D5507E5280" , vpermt2q(zmm2, zmm21, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2D5507E92F8FBFFFF" , vpermt2q(zmm2, zmm21, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62F205487FFF" , vpermt2ps(zmm7, zmm15, zmm7)); + TEST_INSTRUCTION("62F2054F7FFF" , k(k7).vpermt2ps(zmm7, zmm15, zmm7)); + TEST_INSTRUCTION("62F205CF7FFF" , k(k7).z().vpermt2ps(zmm7, zmm15, zmm7)); + TEST_INSTRUCTION("62F205487F39" , vpermt2ps(zmm7, zmm15, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B205487FBCF034120000" , vpermt2ps(zmm7, zmm15, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F205587F39" , vpermt2ps(zmm7, zmm15, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F205487F7A7F" , vpermt2ps(zmm7, zmm15, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F205487FBA00200000" , vpermt2ps(zmm7, zmm15, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F205487F7A80" , vpermt2ps(zmm7, zmm15, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F205487FBAC0DFFFFF" , vpermt2ps(zmm7, zmm15, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F205587F7A7F" , vpermt2ps(zmm7, zmm15, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F205587FBA00020000" , vpermt2ps(zmm7, zmm15, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F205587F7A80" , vpermt2ps(zmm7, zmm15, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F205587FBAFCFDFFFF" , vpermt2ps(zmm7, zmm15, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6212CD407FE1" , vpermt2pd(zmm12, zmm22, zmm25)); + TEST_INSTRUCTION("6212CD417FE1" , k(k1).vpermt2pd(zmm12, zmm22, zmm25)); + TEST_INSTRUCTION("6212CDC17FE1" , k(k1).z().vpermt2pd(zmm12, zmm22, zmm25)); + TEST_INSTRUCTION("6272CD407F21" , vpermt2pd(zmm12, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6232CD407FA4F034120000" , vpermt2pd(zmm12, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6272CD507F21" , vpermt2pd(zmm12, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6272CD407F627F" , vpermt2pd(zmm12, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6272CD407FA200200000" , vpermt2pd(zmm12, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6272CD407F6280" , vpermt2pd(zmm12, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6272CD407FA2C0DFFFFF" , vpermt2pd(zmm12, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6272CD507F627F" , vpermt2pd(zmm12, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6272CD507FA200040000" , vpermt2pd(zmm12, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6272CD507F6280" , vpermt2pd(zmm12, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6272CD507FA2F8FBFFFF" , vpermt2pd(zmm12, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6223F54003C8AB" , valignq(zmm25, zmm17, zmm16, 171)); + TEST_INSTRUCTION("6223F54703C8AB" , k(k7).valignq(zmm25, zmm17, zmm16, 171)); + TEST_INSTRUCTION("6223F5C703C8AB" , k(k7).z().valignq(zmm25, zmm17, zmm16, 171)); + TEST_INSTRUCTION("6223F54003C87B" , valignq(zmm25, zmm17, zmm16, 123)); + TEST_INSTRUCTION("6263F54003097B" , valignq(zmm25, zmm17, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223F540038CF0341200007B" , valignq(zmm25, zmm17, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6263F55003097B" , valignq(zmm25, zmm17, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6263F540034A7F7B" , valignq(zmm25, zmm17, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6263F540038A002000007B" , valignq(zmm25, zmm17, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6263F540034A807B" , valignq(zmm25, zmm17, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6263F540038AC0DFFFFF7B" , valignq(zmm25, zmm17, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6263F550034A7F7B" , valignq(zmm25, zmm17, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6263F550038A000400007B" , valignq(zmm25, zmm17, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6263F550034A807B" , valignq(zmm25, zmm17, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6263F550038AF8FBFFFF7B" , valignq(zmm25, zmm17, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62D17F0879C3" , vcvtsd2usi(eax, xmm11)); + TEST_INSTRUCTION("62D17F1879C3" , rn_sae().vcvtsd2usi(eax, xmm11)); + TEST_INSTRUCTION("62D17F5879C3" , ru_sae().vcvtsd2usi(eax, xmm11)); + TEST_INSTRUCTION("62D17F3879C3" , rd_sae().vcvtsd2usi(eax, xmm11)); + TEST_INSTRUCTION("62D17F7879C3" , rz_sae().vcvtsd2usi(eax, xmm11)); + TEST_INSTRUCTION("62F17F087901" , vcvtsd2usi(eax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F087984F034120000" , vcvtsd2usi(eax, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17F0879427F" , vcvtsd2usi(eax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F08798200040000" , vcvtsd2usi(eax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08794280" , vcvtsd2usi(eax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F087982F8FBFFFF" , vcvtsd2usi(eax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62D17F0879EB" , vcvtsd2usi(ebp, xmm11)); + TEST_INSTRUCTION("62D17F1879EB" , rn_sae().vcvtsd2usi(ebp, xmm11)); + TEST_INSTRUCTION("62D17F5879EB" , ru_sae().vcvtsd2usi(ebp, xmm11)); + TEST_INSTRUCTION("62D17F3879EB" , rd_sae().vcvtsd2usi(ebp, xmm11)); + TEST_INSTRUCTION("62D17F7879EB" , rz_sae().vcvtsd2usi(ebp, xmm11)); + TEST_INSTRUCTION("62F17F087929" , vcvtsd2usi(ebp, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F0879ACF034120000" , vcvtsd2usi(ebp, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17F08796A7F" , vcvtsd2usi(ebp, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F0879AA00040000" , vcvtsd2usi(ebp, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08796A80" , vcvtsd2usi(ebp, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F0879AAF8FBFFFF" , vcvtsd2usi(ebp, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62517F0879EB" , vcvtsd2usi(r13d, xmm11)); + TEST_INSTRUCTION("62517F1879EB" , rn_sae().vcvtsd2usi(r13d, xmm11)); + TEST_INSTRUCTION("62517F5879EB" , ru_sae().vcvtsd2usi(r13d, xmm11)); + TEST_INSTRUCTION("62517F3879EB" , rd_sae().vcvtsd2usi(r13d, xmm11)); + TEST_INSTRUCTION("62517F7879EB" , rz_sae().vcvtsd2usi(r13d, xmm11)); + TEST_INSTRUCTION("62717F087929" , vcvtsd2usi(r13d, qword_ptr(rcx))); + TEST_INSTRUCTION("62317F0879ACF034120000" , vcvtsd2usi(r13d, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62717F08796A7F" , vcvtsd2usi(r13d, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62717F0879AA00040000" , vcvtsd2usi(r13d, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62717F08796A80" , vcvtsd2usi(r13d, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62717F0879AAF8FBFFFF" , vcvtsd2usi(r13d, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62D1FF0879C5" , vcvtsd2usi(rax, xmm13)); + TEST_INSTRUCTION("62D1FF1879C5" , rn_sae().vcvtsd2usi(rax, xmm13)); + TEST_INSTRUCTION("62D1FF5879C5" , ru_sae().vcvtsd2usi(rax, xmm13)); + TEST_INSTRUCTION("62D1FF3879C5" , rd_sae().vcvtsd2usi(rax, xmm13)); + TEST_INSTRUCTION("62D1FF7879C5" , rz_sae().vcvtsd2usi(rax, xmm13)); + TEST_INSTRUCTION("62F1FF087901" , vcvtsd2usi(rax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF087984F034120000" , vcvtsd2usi(rax, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FF0879427F" , vcvtsd2usi(rax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1FF08798200040000" , vcvtsd2usi(rax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1FF08794280" , vcvtsd2usi(rax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1FF087982F8FBFFFF" , vcvtsd2usi(rax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6251FF0879C5" , vcvtsd2usi(r8, xmm13)); + TEST_INSTRUCTION("6251FF1879C5" , rn_sae().vcvtsd2usi(r8, xmm13)); + TEST_INSTRUCTION("6251FF5879C5" , ru_sae().vcvtsd2usi(r8, xmm13)); + TEST_INSTRUCTION("6251FF3879C5" , rd_sae().vcvtsd2usi(r8, xmm13)); + TEST_INSTRUCTION("6251FF7879C5" , rz_sae().vcvtsd2usi(r8, xmm13)); + TEST_INSTRUCTION("6271FF087901" , vcvtsd2usi(r8, qword_ptr(rcx))); + TEST_INSTRUCTION("6231FF087984F034120000" , vcvtsd2usi(r8, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271FF0879427F" , vcvtsd2usi(r8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271FF08798200040000" , vcvtsd2usi(r8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271FF08794280" , vcvtsd2usi(r8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271FF087982F8FBFFFF" , vcvtsd2usi(r8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62F17E0879C1" , vcvtss2usi(eax, xmm1)); + TEST_INSTRUCTION("62F17E1879C1" , rn_sae().vcvtss2usi(eax, xmm1)); + TEST_INSTRUCTION("62F17E5879C1" , ru_sae().vcvtss2usi(eax, xmm1)); + TEST_INSTRUCTION("62F17E3879C1" , rd_sae().vcvtss2usi(eax, xmm1)); + TEST_INSTRUCTION("62F17E7879C1" , rz_sae().vcvtss2usi(eax, xmm1)); + TEST_INSTRUCTION("62F17E087901" , vcvtss2usi(eax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E087984F034120000" , vcvtss2usi(eax, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17E0879427F" , vcvtss2usi(eax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E08798200020000" , vcvtss2usi(eax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08794280" , vcvtss2usi(eax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E087982FCFDFFFF" , vcvtss2usi(eax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F17E0879E9" , vcvtss2usi(ebp, xmm1)); + TEST_INSTRUCTION("62F17E1879E9" , rn_sae().vcvtss2usi(ebp, xmm1)); + TEST_INSTRUCTION("62F17E5879E9" , ru_sae().vcvtss2usi(ebp, xmm1)); + TEST_INSTRUCTION("62F17E3879E9" , rd_sae().vcvtss2usi(ebp, xmm1)); + TEST_INSTRUCTION("62F17E7879E9" , rz_sae().vcvtss2usi(ebp, xmm1)); + TEST_INSTRUCTION("62F17E087929" , vcvtss2usi(ebp, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E0879ACF034120000" , vcvtss2usi(ebp, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17E08796A7F" , vcvtss2usi(ebp, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E0879AA00020000" , vcvtss2usi(ebp, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08796A80" , vcvtss2usi(ebp, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E0879AAFCFDFFFF" , vcvtss2usi(ebp, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62717E0879E9" , vcvtss2usi(r13d, xmm1)); + TEST_INSTRUCTION("62717E1879E9" , rn_sae().vcvtss2usi(r13d, xmm1)); + TEST_INSTRUCTION("62717E5879E9" , ru_sae().vcvtss2usi(r13d, xmm1)); + TEST_INSTRUCTION("62717E3879E9" , rd_sae().vcvtss2usi(r13d, xmm1)); + TEST_INSTRUCTION("62717E7879E9" , rz_sae().vcvtss2usi(r13d, xmm1)); + TEST_INSTRUCTION("62717E087929" , vcvtss2usi(r13d, dword_ptr(rcx))); + TEST_INSTRUCTION("62317E0879ACF034120000" , vcvtss2usi(r13d, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62717E08796A7F" , vcvtss2usi(r13d, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62717E0879AA00020000" , vcvtss2usi(r13d, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62717E08796A80" , vcvtss2usi(r13d, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62717E0879AAFCFDFFFF" , vcvtss2usi(r13d, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F1FE0879C3" , vcvtss2usi(rax, xmm3)); + TEST_INSTRUCTION("62F1FE1879C3" , rn_sae().vcvtss2usi(rax, xmm3)); + TEST_INSTRUCTION("62F1FE5879C3" , ru_sae().vcvtss2usi(rax, xmm3)); + TEST_INSTRUCTION("62F1FE3879C3" , rd_sae().vcvtss2usi(rax, xmm3)); + TEST_INSTRUCTION("62F1FE7879C3" , rz_sae().vcvtss2usi(rax, xmm3)); + TEST_INSTRUCTION("62F1FE087901" , vcvtss2usi(rax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B1FE087984F034120000" , vcvtss2usi(rax, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FE0879427F" , vcvtss2usi(rax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F1FE08798200020000" , vcvtss2usi(rax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F1FE08794280" , vcvtss2usi(rax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F1FE087982FCFDFFFF" , vcvtss2usi(rax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6271FE0879C3" , vcvtss2usi(r8, xmm3)); + TEST_INSTRUCTION("6271FE1879C3" , rn_sae().vcvtss2usi(r8, xmm3)); + TEST_INSTRUCTION("6271FE5879C3" , ru_sae().vcvtss2usi(r8, xmm3)); + TEST_INSTRUCTION("6271FE3879C3" , rd_sae().vcvtss2usi(r8, xmm3)); + TEST_INSTRUCTION("6271FE7879C3" , rz_sae().vcvtss2usi(r8, xmm3)); + TEST_INSTRUCTION("6271FE087901" , vcvtss2usi(r8, dword_ptr(rcx))); + TEST_INSTRUCTION("6231FE087984F034120000" , vcvtss2usi(r8, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271FE0879427F" , vcvtss2usi(r8, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("6271FE08798200020000" , vcvtss2usi(r8, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("6271FE08794280" , vcvtss2usi(r8, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("6271FE087982FCFDFFFF" , vcvtss2usi(r8, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("626177007BD0" , vcvtusi2sd(xmm26, xmm17, eax)); + TEST_INSTRUCTION("626177007BD5" , vcvtusi2sd(xmm26, xmm17, ebp)); + TEST_INSTRUCTION("624177007BD5" , vcvtusi2sd(xmm26, xmm17, r13d)); + TEST_INSTRUCTION("626177007B11" , vcvtusi2sd(xmm26, xmm17, dword_ptr(rcx))); + TEST_INSTRUCTION("622177007B94F034120000" , vcvtusi2sd(xmm26, xmm17, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626177007B527F" , vcvtusi2sd(xmm26, xmm17, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("626177007B9200020000" , vcvtusi2sd(xmm26, xmm17, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("626177007B5280" , vcvtusi2sd(xmm26, xmm17, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("626177007B92FCFDFFFF" , vcvtusi2sd(xmm26, xmm17, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6271CF087BD8" , vcvtusi2sd(xmm11, xmm6, rax)); + TEST_INSTRUCTION("6271CF187BD8" , rn_sae().vcvtusi2sd(xmm11, xmm6, rax)); + TEST_INSTRUCTION("6271CF587BD8" , ru_sae().vcvtusi2sd(xmm11, xmm6, rax)); + TEST_INSTRUCTION("6271CF387BD8" , rd_sae().vcvtusi2sd(xmm11, xmm6, rax)); + TEST_INSTRUCTION("6271CF787BD8" , rz_sae().vcvtusi2sd(xmm11, xmm6, rax)); + TEST_INSTRUCTION("6251CF087BD8" , vcvtusi2sd(xmm11, xmm6, r8)); + TEST_INSTRUCTION("6251CF187BD8" , rn_sae().vcvtusi2sd(xmm11, xmm6, r8)); + TEST_INSTRUCTION("6251CF587BD8" , ru_sae().vcvtusi2sd(xmm11, xmm6, r8)); + TEST_INSTRUCTION("6251CF387BD8" , rd_sae().vcvtusi2sd(xmm11, xmm6, r8)); + TEST_INSTRUCTION("6251CF787BD8" , rz_sae().vcvtusi2sd(xmm11, xmm6, r8)); + TEST_INSTRUCTION("6271CF087B19" , vcvtusi2sd(xmm11, xmm6, qword_ptr(rcx))); + TEST_INSTRUCTION("6231CF087B9CF034120000" , vcvtusi2sd(xmm11, xmm6, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271CF087B5A7F" , vcvtusi2sd(xmm11, xmm6, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271CF087B9A00040000" , vcvtusi2sd(xmm11, xmm6, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271CF087B5A80" , vcvtusi2sd(xmm11, xmm6, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271CF087B9AF8FBFFFF" , vcvtusi2sd(xmm11, xmm6, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("627146087BC8" , vcvtusi2ss(xmm9, xmm7, eax)); + TEST_INSTRUCTION("627146187BC8" , rn_sae().vcvtusi2ss(xmm9, xmm7, eax)); + TEST_INSTRUCTION("627146587BC8" , ru_sae().vcvtusi2ss(xmm9, xmm7, eax)); + TEST_INSTRUCTION("627146387BC8" , rd_sae().vcvtusi2ss(xmm9, xmm7, eax)); + TEST_INSTRUCTION("627146787BC8" , rz_sae().vcvtusi2ss(xmm9, xmm7, eax)); + TEST_INSTRUCTION("627146087BCD" , vcvtusi2ss(xmm9, xmm7, ebp)); + TEST_INSTRUCTION("627146187BCD" , rn_sae().vcvtusi2ss(xmm9, xmm7, ebp)); + TEST_INSTRUCTION("627146587BCD" , ru_sae().vcvtusi2ss(xmm9, xmm7, ebp)); + TEST_INSTRUCTION("627146387BCD" , rd_sae().vcvtusi2ss(xmm9, xmm7, ebp)); + TEST_INSTRUCTION("627146787BCD" , rz_sae().vcvtusi2ss(xmm9, xmm7, ebp)); + TEST_INSTRUCTION("625146087BCD" , vcvtusi2ss(xmm9, xmm7, r13d)); + TEST_INSTRUCTION("625146187BCD" , rn_sae().vcvtusi2ss(xmm9, xmm7, r13d)); + TEST_INSTRUCTION("625146587BCD" , ru_sae().vcvtusi2ss(xmm9, xmm7, r13d)); + TEST_INSTRUCTION("625146387BCD" , rd_sae().vcvtusi2ss(xmm9, xmm7, r13d)); + TEST_INSTRUCTION("625146787BCD" , rz_sae().vcvtusi2ss(xmm9, xmm7, r13d)); + TEST_INSTRUCTION("627146087B09" , vcvtusi2ss(xmm9, xmm7, dword_ptr(rcx))); + TEST_INSTRUCTION("623146087B8CF034120000" , vcvtusi2ss(xmm9, xmm7, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("627146087B4A7F" , vcvtusi2ss(xmm9, xmm7, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("627146087B8A00020000" , vcvtusi2ss(xmm9, xmm7, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("627146087B4A80" , vcvtusi2ss(xmm9, xmm7, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("627146087B8AFCFDFFFF" , vcvtusi2ss(xmm9, xmm7, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62E1AE087BE8" , vcvtusi2ss(xmm21, xmm10, rax)); + TEST_INSTRUCTION("62E1AE187BE8" , rn_sae().vcvtusi2ss(xmm21, xmm10, rax)); + TEST_INSTRUCTION("62E1AE587BE8" , ru_sae().vcvtusi2ss(xmm21, xmm10, rax)); + TEST_INSTRUCTION("62E1AE387BE8" , rd_sae().vcvtusi2ss(xmm21, xmm10, rax)); + TEST_INSTRUCTION("62E1AE787BE8" , rz_sae().vcvtusi2ss(xmm21, xmm10, rax)); + TEST_INSTRUCTION("62C1AE087BE8" , vcvtusi2ss(xmm21, xmm10, r8)); + TEST_INSTRUCTION("62C1AE187BE8" , rn_sae().vcvtusi2ss(xmm21, xmm10, r8)); + TEST_INSTRUCTION("62C1AE587BE8" , ru_sae().vcvtusi2ss(xmm21, xmm10, r8)); + TEST_INSTRUCTION("62C1AE387BE8" , rd_sae().vcvtusi2ss(xmm21, xmm10, r8)); + TEST_INSTRUCTION("62C1AE787BE8" , rz_sae().vcvtusi2ss(xmm21, xmm10, r8)); + TEST_INSTRUCTION("62E1AE087B29" , vcvtusi2ss(xmm21, xmm10, qword_ptr(rcx))); + TEST_INSTRUCTION("62A1AE087BACF034120000" , vcvtusi2ss(xmm21, xmm10, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1AE087B6A7F" , vcvtusi2ss(xmm21, xmm10, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62E1AE087BAA00040000" , vcvtusi2ss(xmm21, xmm10, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62E1AE087B6A80" , vcvtusi2ss(xmm21, xmm10, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62E1AE087BAAF8FBFFFF" , vcvtusi2ss(xmm21, xmm10, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B2DD482CF8" , vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62B2DD4D2CF8" , k(k5).vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62B2DDCD2CF8" , k(k5).z().vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62B2DD182CF8" , rn_sae().vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62B2DD582CF8" , ru_sae().vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62B2DD382CF8" , rd_sae().vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62B2DD782CF8" , rz_sae().vscalefpd(zmm7, zmm4, zmm16)); + TEST_INSTRUCTION("62F2DD482C39" , vscalefpd(zmm7, zmm4, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B2DD482CBCF034120000" , vscalefpd(zmm7, zmm4, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F2DD582C39" , vscalefpd(zmm7, zmm4, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62F2DD482C7A7F" , vscalefpd(zmm7, zmm4, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F2DD482CBA00200000" , vscalefpd(zmm7, zmm4, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F2DD482C7A80" , vscalefpd(zmm7, zmm4, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F2DD482CBAC0DFFFFF" , vscalefpd(zmm7, zmm4, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F2DD582C7A7F" , vscalefpd(zmm7, zmm4, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62F2DD582CBA00040000" , vscalefpd(zmm7, zmm4, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62F2DD582C7A80" , vscalefpd(zmm7, zmm4, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62F2DD582CBAF8FBFFFF" , vscalefpd(zmm7, zmm4, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B225482CE3" , vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62B2254A2CE3" , k(k2).vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62B225CA2CE3" , k(k2).z().vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62B225182CE3" , rn_sae().vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62B225582CE3" , ru_sae().vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62B225382CE3" , rd_sae().vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62B225782CE3" , rz_sae().vscalefps(zmm4, zmm11, zmm19)); + TEST_INSTRUCTION("62F225482C21" , vscalefps(zmm4, zmm11, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B225482CA4F034120000" , vscalefps(zmm4, zmm11, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F225582C21" , vscalefps(zmm4, zmm11, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F225482C627F" , vscalefps(zmm4, zmm11, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F225482CA200200000" , vscalefps(zmm4, zmm11, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F225482C6280" , vscalefps(zmm4, zmm11, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F225482CA2C0DFFFFF" , vscalefps(zmm4, zmm11, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F225582C627F" , vscalefps(zmm4, zmm11, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F225582CA200020000" , vscalefps(zmm4, zmm11, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F225582C6280" , vscalefps(zmm4, zmm11, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F225582CA2FCFDFFFF" , vscalefps(zmm4, zmm11, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6222E5002DEE" , vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6222E5042DEE" , k(k4).vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6222E5842DEE" , k(k4).z().vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6222E5102DEE" , rn_sae().vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6222E5502DEE" , ru_sae().vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6222E5302DEE" , rd_sae().vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6222E5702DEE" , rz_sae().vscalefsd(xmm29, xmm19, xmm22)); + TEST_INSTRUCTION("6262E5002D29" , vscalefsd(xmm29, xmm19, qword_ptr(rcx))); + TEST_INSTRUCTION("6222E5002DACF034120000" , vscalefsd(xmm29, xmm19, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262E5002D6A7F" , vscalefsd(xmm29, xmm19, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6262E5002DAA00040000" , vscalefsd(xmm29, xmm19, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6262E5002D6A80" , vscalefsd(xmm29, xmm19, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6262E5002DAAF8FBFFFF" , vscalefsd(xmm29, xmm19, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62E21D082DE6" , vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D0A2DE6" , k(k2).vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D8A2DE6" , k(k2).z().vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D182DE6" , rn_sae().vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D582DE6" , ru_sae().vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D382DE6" , rd_sae().vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D782DE6" , rz_sae().vscalefss(xmm20, xmm12, xmm6)); + TEST_INSTRUCTION("62E21D082D21" , vscalefss(xmm20, xmm12, dword_ptr(rcx))); + TEST_INSTRUCTION("62A21D082DA4F034120000" , vscalefss(xmm20, xmm12, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E21D082D627F" , vscalefss(xmm20, xmm12, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62E21D082DA200020000" , vscalefss(xmm20, xmm12, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62E21D082D6280" , vscalefss(xmm20, xmm12, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62E21D082DA2FCFDFFFF" , vscalefss(xmm20, xmm12, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F33D4854E7AB" , vfixupimmps(zmm4, zmm8, zmm7, 171)); + TEST_INSTRUCTION("62F33D4F54E7AB" , k(k7).vfixupimmps(zmm4, zmm8, zmm7, 171)); + TEST_INSTRUCTION("62F33DCF54E7AB" , k(k7).z().vfixupimmps(zmm4, zmm8, zmm7, 171)); + TEST_INSTRUCTION("62F33D1854E7AB" , sae().vfixupimmps(zmm4, zmm8, zmm7, 171)); + TEST_INSTRUCTION("62F33D4854E77B" , vfixupimmps(zmm4, zmm8, zmm7, 123)); + TEST_INSTRUCTION("62F33D1854E77B" , sae().vfixupimmps(zmm4, zmm8, zmm7, 123)); + TEST_INSTRUCTION("62F33D4854217B" , vfixupimmps(zmm4, zmm8, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B33D4854A4F0341200007B" , vfixupimmps(zmm4, zmm8, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F33D5854217B" , vfixupimmps(zmm4, zmm8, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F33D4854627F7B" , vfixupimmps(zmm4, zmm8, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F33D4854A2002000007B" , vfixupimmps(zmm4, zmm8, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F33D485462807B" , vfixupimmps(zmm4, zmm8, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F33D4854A2C0DFFFFF7B" , vfixupimmps(zmm4, zmm8, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F33D5854627F7B" , vfixupimmps(zmm4, zmm8, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F33D5854A2000200007B" , vfixupimmps(zmm4, zmm8, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F33D585462807B" , vfixupimmps(zmm4, zmm8, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F33D5854A2FCFDFFFF7B" , vfixupimmps(zmm4, zmm8, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6273D54854FDAB" , vfixupimmpd(zmm15, zmm5, zmm5, 171)); + TEST_INSTRUCTION("6273D54D54FDAB" , k(k5).vfixupimmpd(zmm15, zmm5, zmm5, 171)); + TEST_INSTRUCTION("6273D5CD54FDAB" , k(k5).z().vfixupimmpd(zmm15, zmm5, zmm5, 171)); + TEST_INSTRUCTION("6273D51854FDAB" , sae().vfixupimmpd(zmm15, zmm5, zmm5, 171)); + TEST_INSTRUCTION("6273D54854FD7B" , vfixupimmpd(zmm15, zmm5, zmm5, 123)); + TEST_INSTRUCTION("6273D51854FD7B" , sae().vfixupimmpd(zmm15, zmm5, zmm5, 123)); + TEST_INSTRUCTION("6273D54854397B" , vfixupimmpd(zmm15, zmm5, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233D54854BCF0341200007B" , vfixupimmpd(zmm15, zmm5, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6273D55854397B" , vfixupimmpd(zmm15, zmm5, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273D548547A7F7B" , vfixupimmpd(zmm15, zmm5, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273D54854BA002000007B" , vfixupimmpd(zmm15, zmm5, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273D548547A807B" , vfixupimmpd(zmm15, zmm5, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273D54854BAC0DFFFFF7B" , vfixupimmpd(zmm15, zmm5, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273D558547A7F7B" , vfixupimmpd(zmm15, zmm5, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273D55854BA000400007B" , vfixupimmpd(zmm15, zmm5, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273D558547A807B" , vfixupimmpd(zmm15, zmm5, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273D55854BAF8FBFFFF7B" , vfixupimmpd(zmm15, zmm5, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62633D0055CFAB" , vfixupimmss(xmm25, xmm24, xmm7, 171)); + TEST_INSTRUCTION("62633D0455CFAB" , k(k4).vfixupimmss(xmm25, xmm24, xmm7, 171)); + TEST_INSTRUCTION("62633D8455CFAB" , k(k4).z().vfixupimmss(xmm25, xmm24, xmm7, 171)); + TEST_INSTRUCTION("62633D1055CFAB" , sae().vfixupimmss(xmm25, xmm24, xmm7, 171)); + TEST_INSTRUCTION("62633D0055CF7B" , vfixupimmss(xmm25, xmm24, xmm7, 123)); + TEST_INSTRUCTION("62633D1055CF7B" , sae().vfixupimmss(xmm25, xmm24, xmm7, 123)); + TEST_INSTRUCTION("62633D0055097B" , vfixupimmss(xmm25, xmm24, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62233D00558CF0341200007B" , vfixupimmss(xmm25, xmm24, dword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62633D00554A7F7B" , vfixupimmss(xmm25, xmm24, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62633D00558A000200007B" , vfixupimmss(xmm25, xmm24, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62633D00554A807B" , vfixupimmss(xmm25, xmm24, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62633D00558AFCFDFFFF7B" , vfixupimmss(xmm25, xmm24, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62239D0855C0AB" , vfixupimmsd(xmm24, xmm12, xmm16, 171)); + TEST_INSTRUCTION("62239D0A55C0AB" , k(k2).vfixupimmsd(xmm24, xmm12, xmm16, 171)); + TEST_INSTRUCTION("62239D8A55C0AB" , k(k2).z().vfixupimmsd(xmm24, xmm12, xmm16, 171)); + TEST_INSTRUCTION("62239D1855C0AB" , sae().vfixupimmsd(xmm24, xmm12, xmm16, 171)); + TEST_INSTRUCTION("62239D0855C07B" , vfixupimmsd(xmm24, xmm12, xmm16, 123)); + TEST_INSTRUCTION("62239D1855C07B" , sae().vfixupimmsd(xmm24, xmm12, xmm16, 123)); + TEST_INSTRUCTION("62639D0855017B" , vfixupimmsd(xmm24, xmm12, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("62239D085584F0341200007B" , vfixupimmsd(xmm24, xmm12, qword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62639D0855427F7B" , vfixupimmsd(xmm24, xmm12, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("62639D085582000400007B" , vfixupimmsd(xmm24, xmm12, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("62639D085542807B" , vfixupimmsd(xmm24, xmm12, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("62639D085582F8FBFFFF7B" , vfixupimmsd(xmm24, xmm12, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62F1254072F5AB" , vpslld(zmm27, zmm5, 171)); + TEST_INSTRUCTION("62F1254172F5AB" , k(k1).vpslld(zmm27, zmm5, 171)); + TEST_INSTRUCTION("62F125C172F5AB" , k(k1).z().vpslld(zmm27, zmm5, 171)); + TEST_INSTRUCTION("62F1254072F57B" , vpslld(zmm27, zmm5, 123)); + TEST_INSTRUCTION("62F1254072317B" , vpslld(zmm27, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1254072B4F0341200007B" , vpslld(zmm27, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1255072317B" , vpslld(zmm27, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1254072727F7B" , vpslld(zmm27, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1254072B2002000007B" , vpslld(zmm27, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F125407272807B" , vpslld(zmm27, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1254072B2C0DFFFFF7B" , vpslld(zmm27, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1255072727F7B" , vpslld(zmm27, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F1255072B2000200007B" , vpslld(zmm27, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F125507272807B" , vpslld(zmm27, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F1255072B2FCFDFFFF7B" , vpslld(zmm27, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62F1DD4873F6AB" , vpsllq(zmm4, zmm6, 171)); + TEST_INSTRUCTION("62F1DD4C73F6AB" , k(k4).vpsllq(zmm4, zmm6, 171)); + TEST_INSTRUCTION("62F1DDCC73F6AB" , k(k4).z().vpsllq(zmm4, zmm6, 171)); + TEST_INSTRUCTION("62F1DD4873F67B" , vpsllq(zmm4, zmm6, 123)); + TEST_INSTRUCTION("62F1DD4873317B" , vpsllq(zmm4, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1DD4873B4F0341200007B" , vpsllq(zmm4, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1DD5873317B" , vpsllq(zmm4, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1DD4873727F7B" , vpsllq(zmm4, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1DD4873B2002000007B" , vpsllq(zmm4, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1DD487372807B" , vpsllq(zmm4, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1DD4873B2C0DFFFFF7B" , vpsllq(zmm4, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1DD5873727F7B" , vpsllq(zmm4, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1DD5873B2000400007B" , vpsllq(zmm4, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1DD587372807B" , vpsllq(zmm4, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1DD5873B2F8FBFFFF7B" , vpsllq(zmm4, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62B13D4872E4AB" , vpsrad(zmm8, zmm20, 171)); + TEST_INSTRUCTION("62B13D4A72E4AB" , k(k2).vpsrad(zmm8, zmm20, 171)); + TEST_INSTRUCTION("62B13DCA72E4AB" , k(k2).z().vpsrad(zmm8, zmm20, 171)); + TEST_INSTRUCTION("62B13D4872E47B" , vpsrad(zmm8, zmm20, 123)); + TEST_INSTRUCTION("62F13D4872217B" , vpsrad(zmm8, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B13D4872A4F0341200007B" , vpsrad(zmm8, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F13D5872217B" , vpsrad(zmm8, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F13D4872627F7B" , vpsrad(zmm8, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F13D4872A2002000007B" , vpsrad(zmm8, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F13D487262807B" , vpsrad(zmm8, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F13D4872A2C0DFFFFF7B" , vpsrad(zmm8, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F13D5872627F7B" , vpsrad(zmm8, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F13D5872A2000200007B" , vpsrad(zmm8, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F13D587262807B" , vpsrad(zmm8, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F13D5872A2FCFDFFFF7B" , vpsrad(zmm8, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("62B1E54872E2AB" , vpsraq(zmm3, zmm18, 171)); + TEST_INSTRUCTION("62B1E54E72E2AB" , k(k6).vpsraq(zmm3, zmm18, 171)); + TEST_INSTRUCTION("62B1E5CE72E2AB" , k(k6).z().vpsraq(zmm3, zmm18, 171)); + TEST_INSTRUCTION("62B1E54872E27B" , vpsraq(zmm3, zmm18, 123)); + TEST_INSTRUCTION("62F1E54872217B" , vpsraq(zmm3, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1E54872A4F0341200007B" , vpsraq(zmm3, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1E55872217B" , vpsraq(zmm3, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1E54872627F7B" , vpsraq(zmm3, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1E54872A2002000007B" , vpsraq(zmm3, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1E5487262807B" , vpsraq(zmm3, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1E54872A2C0DFFFFF7B" , vpsraq(zmm3, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1E55872627F7B" , vpsraq(zmm3, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1E55872A2000400007B" , vpsraq(zmm3, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1E5587262807B" , vpsraq(zmm3, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1E55872A2F8FBFFFF7B" , vpsraq(zmm3, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("6242754815E2" , vprolvd(zmm28, zmm1, zmm10)); + TEST_INSTRUCTION("6242754E15E2" , k(k6).vprolvd(zmm28, zmm1, zmm10)); + TEST_INSTRUCTION("624275CE15E2" , k(k6).z().vprolvd(zmm28, zmm1, zmm10)); + TEST_INSTRUCTION("626275481521" , vprolvd(zmm28, zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222754815A4F034120000" , vprolvd(zmm28, zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("626275581521" , vprolvd(zmm28, zmm1, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("6262754815627F" , vprolvd(zmm28, zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262754815A200200000" , vprolvd(zmm28, zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62627548156280" , vprolvd(zmm28, zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262754815A2C0DFFFFF" , vprolvd(zmm28, zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262755815627F" , vprolvd(zmm28, zmm1, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("6262755815A200020000" , vprolvd(zmm28, zmm1, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62627558156280" , vprolvd(zmm28, zmm1, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("6262755815A2FCFDFFFF" , vprolvd(zmm28, zmm1, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6291654072CBAB" , vprold(zmm19, zmm27, 171)); + TEST_INSTRUCTION("6291654472CBAB" , k(k4).vprold(zmm19, zmm27, 171)); + TEST_INSTRUCTION("629165C472CBAB" , k(k4).z().vprold(zmm19, zmm27, 171)); + TEST_INSTRUCTION("6291654072CB7B" , vprold(zmm19, zmm27, 123)); + TEST_INSTRUCTION("62F1654072097B" , vprold(zmm19, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B16540728CF0341200007B" , vprold(zmm19, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1655072097B" , vprold(zmm19, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F16540724A7F7B" , vprold(zmm19, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F16540728A002000007B" , vprold(zmm19, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F16540724A807B" , vprold(zmm19, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F16540728AC0DFFFFF7B" , vprold(zmm19, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F16550724A7F7B" , vprold(zmm19, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F16550728A000200007B" , vprold(zmm19, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F16550724A807B" , vprold(zmm19, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F16550728AFCFDFFFF7B" , vprold(zmm19, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6222F54815CE" , vprolvq(zmm25, zmm1, zmm22)); + TEST_INSTRUCTION("6222F54F15CE" , k(k7).vprolvq(zmm25, zmm1, zmm22)); + TEST_INSTRUCTION("6222F5CF15CE" , k(k7).z().vprolvq(zmm25, zmm1, zmm22)); + TEST_INSTRUCTION("6262F5481509" , vprolvq(zmm25, zmm1, zmmword_ptr(rcx))); + TEST_INSTRUCTION("6222F548158CF034120000" , vprolvq(zmm25, zmm1, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6262F5581509" , vprolvq(zmm25, zmm1, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("6262F548154A7F" , vprolvq(zmm25, zmm1, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("6262F548158A00200000" , vprolvq(zmm25, zmm1, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("6262F548154A80" , vprolvq(zmm25, zmm1, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("6262F548158AC0DFFFFF" , vprolvq(zmm25, zmm1, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("6262F558154A7F" , vprolvq(zmm25, zmm1, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("6262F558158A00040000" , vprolvq(zmm25, zmm1, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("6262F558154A80" , vprolvq(zmm25, zmm1, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("6262F558158AF8FBFFFF" , vprolvq(zmm25, zmm1, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D1F54072CAAB" , vprolq(zmm17, zmm10, 171)); + TEST_INSTRUCTION("62D1F54472CAAB" , k(k4).vprolq(zmm17, zmm10, 171)); + TEST_INSTRUCTION("62D1F5C472CAAB" , k(k4).z().vprolq(zmm17, zmm10, 171)); + TEST_INSTRUCTION("62D1F54072CA7B" , vprolq(zmm17, zmm10, 123)); + TEST_INSTRUCTION("62F1F54072097B" , vprolq(zmm17, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1F540728CF0341200007B" , vprolq(zmm17, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1F55072097B" , vprolq(zmm17, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1F540724A7F7B" , vprolq(zmm17, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1F540728A002000007B" , vprolq(zmm17, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1F540724A807B" , vprolq(zmm17, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1F540728AC0DFFFFF7B" , vprolq(zmm17, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1F550724A7F7B" , vprolq(zmm17, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1F550728A000400007B" , vprolq(zmm17, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1F550724A807B" , vprolq(zmm17, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1F550728AF8FBFFFF7B" , vprolq(zmm17, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62D23D4814CD" , vprorvd(zmm1, zmm8, zmm13)); + TEST_INSTRUCTION("62D23D4A14CD" , k(k2).vprorvd(zmm1, zmm8, zmm13)); + TEST_INSTRUCTION("62D23DCA14CD" , k(k2).z().vprorvd(zmm1, zmm8, zmm13)); + TEST_INSTRUCTION("62F23D481409" , vprorvd(zmm1, zmm8, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B23D48148CF034120000" , vprorvd(zmm1, zmm8, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F23D581409" , vprorvd(zmm1, zmm8, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F23D48144A7F" , vprorvd(zmm1, zmm8, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F23D48148A00200000" , vprorvd(zmm1, zmm8, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F23D48144A80" , vprorvd(zmm1, zmm8, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F23D48148AC0DFFFFF" , vprorvd(zmm1, zmm8, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F23D58144A7F" , vprorvd(zmm1, zmm8, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F23D58148A00020000" , vprorvd(zmm1, zmm8, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F23D58144A80" , vprorvd(zmm1, zmm8, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F23D58148AFCFDFFFF" , vprorvd(zmm1, zmm8, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62D1454872C7AB" , vprord(zmm7, zmm15, 171)); + TEST_INSTRUCTION("62D1454972C7AB" , k(k1).vprord(zmm7, zmm15, 171)); + TEST_INSTRUCTION("62D145C972C7AB" , k(k1).z().vprord(zmm7, zmm15, 171)); + TEST_INSTRUCTION("62D1454872C77B" , vprord(zmm7, zmm15, 123)); + TEST_INSTRUCTION("62F1454872017B" , vprord(zmm7, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B145487284F0341200007B" , vprord(zmm7, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1455872017B" , vprord(zmm7, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62F1454872427F7B" , vprord(zmm7, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F145487282002000007B" , vprord(zmm7, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F145487242807B" , vprord(zmm7, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F145487282C0DFFFFF7B" , vprord(zmm7, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1455872427F7B" , vprord(zmm7, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62F145587282000200007B" , vprord(zmm7, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62F145587242807B" , vprord(zmm7, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62F145587282FCFDFFFF7B" , vprord(zmm7, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6282C54014E8" , vprorvq(zmm21, zmm23, zmm24)); + TEST_INSTRUCTION("6282C54714E8" , k(k7).vprorvq(zmm21, zmm23, zmm24)); + TEST_INSTRUCTION("6282C5C714E8" , k(k7).z().vprorvq(zmm21, zmm23, zmm24)); + TEST_INSTRUCTION("62E2C5401429" , vprorvq(zmm21, zmm23, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2C54014ACF034120000" , vprorvq(zmm21, zmm23, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2C5501429" , vprorvq(zmm21, zmm23, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2C540146A7F" , vprorvq(zmm21, zmm23, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2C54014AA00200000" , vprorvq(zmm21, zmm23, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2C540146A80" , vprorvq(zmm21, zmm23, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2C54014AAC0DFFFFF" , vprorvq(zmm21, zmm23, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2C550146A7F" , vprorvq(zmm21, zmm23, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2C55014AA00040000" , vprorvq(zmm21, zmm23, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2C550146A80" , vprorvq(zmm21, zmm23, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2C55014AAF8FBFFFF" , vprorvq(zmm21, zmm23, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("6291FD4072C3AB" , vprorq(zmm16, zmm27, 171)); + TEST_INSTRUCTION("6291FD4372C3AB" , k(k3).vprorq(zmm16, zmm27, 171)); + TEST_INSTRUCTION("6291FDC372C3AB" , k(k3).z().vprorq(zmm16, zmm27, 171)); + TEST_INSTRUCTION("6291FD4072C37B" , vprorq(zmm16, zmm27, 123)); + TEST_INSTRUCTION("62F1FD4072017B" , vprorq(zmm16, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B1FD407284F0341200007B" , vprorq(zmm16, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F1FD5072017B" , vprorq(zmm16, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("62F1FD4072427F7B" , vprorq(zmm16, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62F1FD407282002000007B" , vprorq(zmm16, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62F1FD407242807B" , vprorq(zmm16, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62F1FD407282C0DFFFFF7B" , vprorq(zmm16, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62F1FD5072427F7B" , vprorq(zmm16, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("62F1FD507282000400007B" , vprorq(zmm16, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1FD507242807B" , vprorq(zmm16, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("62F1FD507282F8FBFFFF7B" , vprorq(zmm16, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("6213FD4809EAAB" , vrndscalepd(zmm13, zmm26, 171)); + TEST_INSTRUCTION("6213FD4A09EAAB" , k(k2).vrndscalepd(zmm13, zmm26, 171)); + TEST_INSTRUCTION("6213FDCA09EAAB" , k(k2).z().vrndscalepd(zmm13, zmm26, 171)); + TEST_INSTRUCTION("6213FD1809EAAB" , sae().vrndscalepd(zmm13, zmm26, 171)); + TEST_INSTRUCTION("6213FD4809EA7B" , vrndscalepd(zmm13, zmm26, 123)); + TEST_INSTRUCTION("6213FD1809EA7B" , sae().vrndscalepd(zmm13, zmm26, 123)); + TEST_INSTRUCTION("6273FD4809297B" , vrndscalepd(zmm13, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("6233FD4809ACF0341200007B" , vrndscalepd(zmm13, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6273FD5809297B" , vrndscalepd(zmm13, qword_ptr(rcx)._1to8(), 123)); + TEST_INSTRUCTION("6273FD48096A7F7B" , vrndscalepd(zmm13, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("6273FD4809AA002000007B" , vrndscalepd(zmm13, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("6273FD48096A807B" , vrndscalepd(zmm13, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("6273FD4809AAC0DFFFFF7B" , vrndscalepd(zmm13, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("6273FD58096A7F7B" , vrndscalepd(zmm13, qword_ptr(rdx, 1016)._1to8(), 123)); + TEST_INSTRUCTION("6273FD5809AA000400007B" , vrndscalepd(zmm13, qword_ptr(rdx, 1024)._1to8(), 123)); + TEST_INSTRUCTION("6273FD58096A807B" , vrndscalepd(zmm13, qword_ptr(rdx, -1024)._1to8(), 123)); + TEST_INSTRUCTION("6273FD5809AAF8FBFFFF7B" , vrndscalepd(zmm13, qword_ptr(rdx, -1032)._1to8(), 123)); + TEST_INSTRUCTION("62637D4808C7AB" , vrndscaleps(zmm24, zmm7, 171)); + TEST_INSTRUCTION("62637D4908C7AB" , k(k1).vrndscaleps(zmm24, zmm7, 171)); + TEST_INSTRUCTION("62637DC908C7AB" , k(k1).z().vrndscaleps(zmm24, zmm7, 171)); + TEST_INSTRUCTION("62637D1808C7AB" , sae().vrndscaleps(zmm24, zmm7, 171)); + TEST_INSTRUCTION("62637D4808C77B" , vrndscaleps(zmm24, zmm7, 123)); + TEST_INSTRUCTION("62637D1808C77B" , sae().vrndscaleps(zmm24, zmm7, 123)); + TEST_INSTRUCTION("62637D4808017B" , vrndscaleps(zmm24, zmmword_ptr(rcx), 123)); + TEST_INSTRUCTION("62237D480884F0341200007B" , vrndscaleps(zmm24, zmmword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62637D5808017B" , vrndscaleps(zmm24, dword_ptr(rcx)._1to16(), 123)); + TEST_INSTRUCTION("62637D4808427F7B" , vrndscaleps(zmm24, zmmword_ptr(rdx, 8128), 123)); + TEST_INSTRUCTION("62637D480882002000007B" , vrndscaleps(zmm24, zmmword_ptr(rdx, 8192), 123)); + TEST_INSTRUCTION("62637D480842807B" , vrndscaleps(zmm24, zmmword_ptr(rdx, -8192), 123)); + TEST_INSTRUCTION("62637D480882C0DFFFFF7B" , vrndscaleps(zmm24, zmmword_ptr(rdx, -8256), 123)); + TEST_INSTRUCTION("62637D5808427F7B" , vrndscaleps(zmm24, dword_ptr(rdx, 508)._1to16(), 123)); + TEST_INSTRUCTION("62637D580882000200007B" , vrndscaleps(zmm24, dword_ptr(rdx, 512)._1to16(), 123)); + TEST_INSTRUCTION("62637D580842807B" , vrndscaleps(zmm24, dword_ptr(rdx, -512)._1to16(), 123)); + TEST_INSTRUCTION("62637D580882FCFDFFFF7B" , vrndscaleps(zmm24, dword_ptr(rdx, -516)._1to16(), 123)); + TEST_INSTRUCTION("6223C5080BD2AB" , vrndscalesd(xmm26, xmm7, xmm18, 171)); + TEST_INSTRUCTION("6223C5090BD2AB" , k(k1).vrndscalesd(xmm26, xmm7, xmm18, 171)); + TEST_INSTRUCTION("6223C5890BD2AB" , k(k1).z().vrndscalesd(xmm26, xmm7, xmm18, 171)); + TEST_INSTRUCTION("6223C5180BD2AB" , sae().vrndscalesd(xmm26, xmm7, xmm18, 171)); + TEST_INSTRUCTION("6223C5080BD27B" , vrndscalesd(xmm26, xmm7, xmm18, 123)); + TEST_INSTRUCTION("6223C5180BD27B" , sae().vrndscalesd(xmm26, xmm7, xmm18, 123)); + TEST_INSTRUCTION("6263C5080B117B" , vrndscalesd(xmm26, xmm7, qword_ptr(rcx), 123)); + TEST_INSTRUCTION("6223C5080B94F0341200007B" , vrndscalesd(xmm26, xmm7, qword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("6263C5080B527F7B" , vrndscalesd(xmm26, xmm7, qword_ptr(rdx, 1016), 123)); + TEST_INSTRUCTION("6263C5080B92000400007B" , vrndscalesd(xmm26, xmm7, qword_ptr(rdx, 1024), 123)); + TEST_INSTRUCTION("6263C5080B52807B" , vrndscalesd(xmm26, xmm7, qword_ptr(rdx, -1024), 123)); + TEST_INSTRUCTION("6263C5080B92F8FBFFFF7B" , vrndscalesd(xmm26, xmm7, qword_ptr(rdx, -1032), 123)); + TEST_INSTRUCTION("62F345000AFEAB" , vrndscaless(xmm7, xmm23, xmm6, 171)); + TEST_INSTRUCTION("62F345040AFEAB" , k(k4).vrndscaless(xmm7, xmm23, xmm6, 171)); + TEST_INSTRUCTION("62F345840AFEAB" , k(k4).z().vrndscaless(xmm7, xmm23, xmm6, 171)); + TEST_INSTRUCTION("62F345100AFEAB" , sae().vrndscaless(xmm7, xmm23, xmm6, 171)); + TEST_INSTRUCTION("62F345000AFE7B" , vrndscaless(xmm7, xmm23, xmm6, 123)); + TEST_INSTRUCTION("62F345100AFE7B" , sae().vrndscaless(xmm7, xmm23, xmm6, 123)); + TEST_INSTRUCTION("62F345000A397B" , vrndscaless(xmm7, xmm23, dword_ptr(rcx), 123)); + TEST_INSTRUCTION("62B345000ABCF0341200007B" , vrndscaless(xmm7, xmm23, dword_ptr(rax, r14, 3, 4660), 123)); + TEST_INSTRUCTION("62F345000A7A7F7B" , vrndscaless(xmm7, xmm23, dword_ptr(rdx, 508), 123)); + TEST_INSTRUCTION("62F345000ABA000200007B" , vrndscaless(xmm7, xmm23, dword_ptr(rdx, 512), 123)); + TEST_INSTRUCTION("62F345000A7A807B" , vrndscaless(xmm7, xmm23, dword_ptr(rdx, -512), 123)); + TEST_INSTRUCTION("62F345000ABAFCFDFFFF7B" , vrndscaless(xmm7, xmm23, dword_ptr(rdx, -516), 123)); + TEST_INSTRUCTION("62E2FD488B19" , vpcompressq(zmmword_ptr(rcx), zmm19)); + TEST_INSTRUCTION("62E2FD4B8B19" , k(k3).vpcompressq(zmmword_ptr(rcx), zmm19)); + TEST_INSTRUCTION("62A2FD488B9CF034120000" , vpcompressq(zmmword_ptr(rax, r14, 3, 4660), zmm19)); + TEST_INSTRUCTION("62E2FD488B5A7F" , vpcompressq(zmmword_ptr(rdx, 1016), zmm19)); + TEST_INSTRUCTION("62E2FD488B9A00040000" , vpcompressq(zmmword_ptr(rdx, 1024), zmm19)); + TEST_INSTRUCTION("62E2FD488B5A80" , vpcompressq(zmmword_ptr(rdx, -1024), zmm19)); + TEST_INSTRUCTION("62E2FD488B9AF8FBFFFF" , vpcompressq(zmmword_ptr(rdx, -1032), zmm19)); + TEST_INSTRUCTION("6252FD488BC4" , vpcompressq(zmm12, zmm8)); + TEST_INSTRUCTION("6252FD4E8BC4" , k(k6).vpcompressq(zmm12, zmm8)); + TEST_INSTRUCTION("6252FDCE8BC4" , k(k6).z().vpcompressq(zmm12, zmm8)); + TEST_INSTRUCTION("C5DC41EE" , kandw(k5, k4, k6)); + TEST_INSTRUCTION("C5DC42EE" , kandnw(k5, k4, k6)); + TEST_INSTRUCTION("C5E445D5" , korw(k2, k3, k5)); + TEST_INSTRUCTION("C5CC46D7" , kxnorw(k2, k6, k7)); + TEST_INSTRUCTION("C5DC47DE" , kxorw(k3, k4, k6)); + TEST_INSTRUCTION("C5F844E3" , knotw(k4, k3)); + TEST_INSTRUCTION("C5F898DE" , kortestw(k3, k6)); + TEST_INSTRUCTION("C4E3F930DDAB" , kshiftrw(k3, k5, 171)); + TEST_INSTRUCTION("C4E3F930DD7B" , kshiftrw(k3, k5, 123)); + TEST_INSTRUCTION("C4E3F932DBAB" , kshiftlw(k3, k3, 171)); + TEST_INSTRUCTION("C4E3F932DB7B" , kshiftlw(k3, k3, 123)); + TEST_INSTRUCTION("C5F890D5" , kmovw(k2, k5)); + TEST_INSTRUCTION("C5F89011" , kmovw(k2, word_ptr(rcx))); + TEST_INSTRUCTION("C4A1789094F034120000" , kmovw(k2, word_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("C5F89129" , kmovw(word_ptr(rcx), k5)); + TEST_INSTRUCTION("C4A17891ACF034120000" , kmovw(word_ptr(rax, r14, 3, 4660), k5)); + TEST_INSTRUCTION("C5F892D8" , kmovw(k3, eax)); + TEST_INSTRUCTION("C5F892DD" , kmovw(k3, ebp)); + TEST_INSTRUCTION("C4C17892DD" , kmovw(k3, r13d)); + TEST_INSTRUCTION("C5F893C3" , kmovw(eax, k3)); + TEST_INSTRUCTION("C5F893EB" , kmovw(ebp, k3)); + TEST_INSTRUCTION("C57893EB" , kmovw(r13d, k3)); + TEST_INSTRUCTION("C5E54BD7" , kunpckbw(k2, k3, k7)); + TEST_INSTRUCTION("62F37D481D31AB" , vcvtps2ph(ymmword_ptr(rcx), zmm6, 171)); + TEST_INSTRUCTION("62F37D491D31AB" , k(k1).vcvtps2ph(ymmword_ptr(rcx), zmm6, 171)); + TEST_INSTRUCTION("62F37D481D317B" , vcvtps2ph(ymmword_ptr(rcx), zmm6, 123)); + TEST_INSTRUCTION("62B37D481DB4F0341200007B" , vcvtps2ph(ymmword_ptr(rax, r14, 3, 4660), zmm6, 123)); + TEST_INSTRUCTION("62F37D481D727F7B" , vcvtps2ph(ymmword_ptr(rdx, 4064), zmm6, 123)); + TEST_INSTRUCTION("62F37D481DB2001000007B" , vcvtps2ph(ymmword_ptr(rdx, 4096), zmm6, 123)); + TEST_INSTRUCTION("62F37D481D72807B" , vcvtps2ph(ymmword_ptr(rdx, -4096), zmm6, 123)); + TEST_INSTRUCTION("62F37D481DB2E0EFFFFF7B" , vcvtps2ph(ymmword_ptr(rdx, -4128), zmm6, 123)); + TEST_INSTRUCTION("62E37D481931AB" , vextractf32x4(xmmword_ptr(rcx), zmm22, 171)); + TEST_INSTRUCTION("62E37D4B1931AB" , k(k3).vextractf32x4(xmmword_ptr(rcx), zmm22, 171)); + TEST_INSTRUCTION("62E37D4819317B" , vextractf32x4(xmmword_ptr(rcx), zmm22, 123)); + TEST_INSTRUCTION("62A37D4819B4F0341200007B" , vextractf32x4(xmmword_ptr(rax, r14, 3, 4660), zmm22, 123)); + TEST_INSTRUCTION("62E37D4819727F7B" , vextractf32x4(xmmword_ptr(rdx, 2032), zmm22, 123)); + TEST_INSTRUCTION("62E37D4819B2000800007B" , vextractf32x4(xmmword_ptr(rdx, 2048), zmm22, 123)); + TEST_INSTRUCTION("62E37D481972807B" , vextractf32x4(xmmword_ptr(rdx, -2048), zmm22, 123)); + TEST_INSTRUCTION("62E37D4819B2F0F7FFFF7B" , vextractf32x4(xmmword_ptr(rdx, -2064), zmm22, 123)); + TEST_INSTRUCTION("6273FD481B21AB" , vextractf64x4(ymmword_ptr(rcx), zmm12, 171)); + TEST_INSTRUCTION("6273FD4F1B21AB" , k(k7).vextractf64x4(ymmword_ptr(rcx), zmm12, 171)); + TEST_INSTRUCTION("6273FD481B217B" , vextractf64x4(ymmword_ptr(rcx), zmm12, 123)); + TEST_INSTRUCTION("6233FD481BA4F0341200007B" , vextractf64x4(ymmword_ptr(rax, r14, 3, 4660), zmm12, 123)); + TEST_INSTRUCTION("6273FD481B627F7B" , vextractf64x4(ymmword_ptr(rdx, 4064), zmm12, 123)); + TEST_INSTRUCTION("6273FD481BA2001000007B" , vextractf64x4(ymmword_ptr(rdx, 4096), zmm12, 123)); + TEST_INSTRUCTION("6273FD481B62807B" , vextractf64x4(ymmword_ptr(rdx, -4096), zmm12, 123)); + TEST_INSTRUCTION("6273FD481BA2E0EFFFFF7B" , vextractf64x4(ymmword_ptr(rdx, -4128), zmm12, 123)); + TEST_INSTRUCTION("62F37D483909AB" , vextracti32x4(xmmword_ptr(rcx), zmm1, 171)); + TEST_INSTRUCTION("62F37D4B3909AB" , k(k3).vextracti32x4(xmmword_ptr(rcx), zmm1, 171)); + TEST_INSTRUCTION("62F37D4839097B" , vextracti32x4(xmmword_ptr(rcx), zmm1, 123)); + TEST_INSTRUCTION("62B37D48398CF0341200007B" , vextracti32x4(xmmword_ptr(rax, r14, 3, 4660), zmm1, 123)); + TEST_INSTRUCTION("62F37D48394A7F7B" , vextracti32x4(xmmword_ptr(rdx, 2032), zmm1, 123)); + TEST_INSTRUCTION("62F37D48398A000800007B" , vextracti32x4(xmmword_ptr(rdx, 2048), zmm1, 123)); + TEST_INSTRUCTION("62F37D48394A807B" , vextracti32x4(xmmword_ptr(rdx, -2048), zmm1, 123)); + TEST_INSTRUCTION("62F37D48398AF0F7FFFF7B" , vextracti32x4(xmmword_ptr(rdx, -2064), zmm1, 123)); + TEST_INSTRUCTION("62F3FD483B11AB" , vextracti64x4(ymmword_ptr(rcx), zmm2, 171)); + TEST_INSTRUCTION("62F3FD4A3B11AB" , k(k2).vextracti64x4(ymmword_ptr(rcx), zmm2, 171)); + TEST_INSTRUCTION("62F3FD483B117B" , vextracti64x4(ymmword_ptr(rcx), zmm2, 123)); + TEST_INSTRUCTION("62B3FD483B94F0341200007B" , vextracti64x4(ymmword_ptr(rax, r14, 3, 4660), zmm2, 123)); + TEST_INSTRUCTION("62F3FD483B527F7B" , vextracti64x4(ymmword_ptr(rdx, 4064), zmm2, 123)); + TEST_INSTRUCTION("62F3FD483B92001000007B" , vextracti64x4(ymmword_ptr(rdx, 4096), zmm2, 123)); + TEST_INSTRUCTION("62F3FD483B52807B" , vextracti64x4(ymmword_ptr(rdx, -4096), zmm2, 123)); + TEST_INSTRUCTION("62F3FD483B92E0EFFFFF7B" , vextracti64x4(ymmword_ptr(rdx, -4128), zmm2, 123)); + TEST_INSTRUCTION("6261FD482919" , vmovapd(zmmword_ptr(rcx), zmm27)); + TEST_INSTRUCTION("6261FD492919" , k(k1).vmovapd(zmmword_ptr(rcx), zmm27)); + TEST_INSTRUCTION("6221FD48299CF034120000" , vmovapd(zmmword_ptr(rax, r14, 3, 4660), zmm27)); + TEST_INSTRUCTION("6261FD48295A7F" , vmovapd(zmmword_ptr(rdx, 8128), zmm27)); + TEST_INSTRUCTION("6261FD48299A00200000" , vmovapd(zmmword_ptr(rdx, 8192), zmm27)); + TEST_INSTRUCTION("6261FD48295A80" , vmovapd(zmmword_ptr(rdx, -8192), zmm27)); + TEST_INSTRUCTION("6261FD48299AC0DFFFFF" , vmovapd(zmmword_ptr(rdx, -8256), zmm27)); + TEST_INSTRUCTION("62E17C482909" , vmovaps(zmmword_ptr(rcx), zmm17)); + TEST_INSTRUCTION("62E17C4D2909" , k(k5).vmovaps(zmmword_ptr(rcx), zmm17)); + TEST_INSTRUCTION("62A17C48298CF034120000" , vmovaps(zmmword_ptr(rax, r14, 3, 4660), zmm17)); + TEST_INSTRUCTION("62E17C48294A7F" , vmovaps(zmmword_ptr(rdx, 8128), zmm17)); + TEST_INSTRUCTION("62E17C48298A00200000" , vmovaps(zmmword_ptr(rdx, 8192), zmm17)); + TEST_INSTRUCTION("62E17C48294A80" , vmovaps(zmmword_ptr(rdx, -8192), zmm17)); + TEST_INSTRUCTION("62E17C48298AC0DFFFFF" , vmovaps(zmmword_ptr(rdx, -8256), zmm17)); + TEST_INSTRUCTION("62F17D487F19" , vmovdqa32(zmmword_ptr(rcx), zmm3)); + TEST_INSTRUCTION("62F17D497F19" , k(k1).vmovdqa32(zmmword_ptr(rcx), zmm3)); + TEST_INSTRUCTION("62B17D487F9CF034120000" , vmovdqa32(zmmword_ptr(rax, r14, 3, 4660), zmm3)); + TEST_INSTRUCTION("62F17D487F5A7F" , vmovdqa32(zmmword_ptr(rdx, 8128), zmm3)); + TEST_INSTRUCTION("62F17D487F9A00200000" , vmovdqa32(zmmword_ptr(rdx, 8192), zmm3)); + TEST_INSTRUCTION("62F17D487F5A80" , vmovdqa32(zmmword_ptr(rdx, -8192), zmm3)); + TEST_INSTRUCTION("62F17D487F9AC0DFFFFF" , vmovdqa32(zmmword_ptr(rdx, -8256), zmm3)); + TEST_INSTRUCTION("62E1FD487F11" , vmovdqa64(zmmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62E1FD497F11" , k(k1).vmovdqa64(zmmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62A1FD487F94F034120000" , vmovdqa64(zmmword_ptr(rax, r14, 3, 4660), zmm18)); + TEST_INSTRUCTION("62E1FD487F527F" , vmovdqa64(zmmword_ptr(rdx, 8128), zmm18)); + TEST_INSTRUCTION("62E1FD487F9200200000" , vmovdqa64(zmmword_ptr(rdx, 8192), zmm18)); + TEST_INSTRUCTION("62E1FD487F5280" , vmovdqa64(zmmword_ptr(rdx, -8192), zmm18)); + TEST_INSTRUCTION("62E1FD487F92C0DFFFFF" , vmovdqa64(zmmword_ptr(rdx, -8256), zmm18)); + TEST_INSTRUCTION("62F17E487F11" , vmovdqu32(zmmword_ptr(rcx), zmm2)); + TEST_INSTRUCTION("62F17E4F7F11" , k(k7).vmovdqu32(zmmword_ptr(rcx), zmm2)); + TEST_INSTRUCTION("62B17E487F94F034120000" , vmovdqu32(zmmword_ptr(rax, r14, 3, 4660), zmm2)); + TEST_INSTRUCTION("62F17E487F527F" , vmovdqu32(zmmword_ptr(rdx, 8128), zmm2)); + TEST_INSTRUCTION("62F17E487F9200200000" , vmovdqu32(zmmword_ptr(rdx, 8192), zmm2)); + TEST_INSTRUCTION("62F17E487F5280" , vmovdqu32(zmmword_ptr(rdx, -8192), zmm2)); + TEST_INSTRUCTION("62F17E487F92C0DFFFFF" , vmovdqu32(zmmword_ptr(rdx, -8256), zmm2)); + TEST_INSTRUCTION("62F1FE487F39" , vmovdqu64(zmmword_ptr(rcx), zmm7)); + TEST_INSTRUCTION("62F1FE497F39" , k(k1).vmovdqu64(zmmword_ptr(rcx), zmm7)); + TEST_INSTRUCTION("62B1FE487FBCF034120000" , vmovdqu64(zmmword_ptr(rax, r14, 3, 4660), zmm7)); + TEST_INSTRUCTION("62F1FE487F7A7F" , vmovdqu64(zmmword_ptr(rdx, 8128), zmm7)); + TEST_INSTRUCTION("62F1FE487FBA00200000" , vmovdqu64(zmmword_ptr(rdx, 8192), zmm7)); + TEST_INSTRUCTION("62F1FE487F7A80" , vmovdqu64(zmmword_ptr(rdx, -8192), zmm7)); + TEST_INSTRUCTION("62F1FE487FBAC0DFFFFF" , vmovdqu64(zmmword_ptr(rdx, -8256), zmm7)); + TEST_INSTRUCTION("6271FD481101" , vmovupd(zmmword_ptr(rcx), zmm8)); + TEST_INSTRUCTION("6271FD4C1101" , k(k4).vmovupd(zmmword_ptr(rcx), zmm8)); + TEST_INSTRUCTION("6231FD481184F034120000" , vmovupd(zmmword_ptr(rax, r14, 3, 4660), zmm8)); + TEST_INSTRUCTION("6271FD4811427F" , vmovupd(zmmword_ptr(rdx, 8128), zmm8)); + TEST_INSTRUCTION("6271FD48118200200000" , vmovupd(zmmword_ptr(rdx, 8192), zmm8)); + TEST_INSTRUCTION("6271FD48114280" , vmovupd(zmmword_ptr(rdx, -8192), zmm8)); + TEST_INSTRUCTION("6271FD481182C0DFFFFF" , vmovupd(zmmword_ptr(rdx, -8256), zmm8)); + TEST_INSTRUCTION("62F17C481121" , vmovups(zmmword_ptr(rcx), zmm4)); + TEST_INSTRUCTION("62F17C491121" , k(k1).vmovups(zmmword_ptr(rcx), zmm4)); + TEST_INSTRUCTION("62B17C4811A4F034120000" , vmovups(zmmword_ptr(rax, r14, 3, 4660), zmm4)); + TEST_INSTRUCTION("62F17C4811627F" , vmovups(zmmword_ptr(rdx, 8128), zmm4)); + TEST_INSTRUCTION("62F17C4811A200200000" , vmovups(zmmword_ptr(rdx, 8192), zmm4)); + TEST_INSTRUCTION("62F17C48116280" , vmovups(zmmword_ptr(rdx, -8192), zmm4)); + TEST_INSTRUCTION("62F17C4811A2C0DFFFFF" , vmovups(zmmword_ptr(rdx, -8256), zmm4)); + TEST_INSTRUCTION("62727E483231" , vpmovqb(qword_ptr(rcx), zmm14)); + TEST_INSTRUCTION("62727E4A3231" , k(k2).vpmovqb(qword_ptr(rcx), zmm14)); + TEST_INSTRUCTION("62327E4832B4F034120000" , vpmovqb(qword_ptr(rax, r14, 3, 4660), zmm14)); + TEST_INSTRUCTION("62727E4832727F" , vpmovqb(qword_ptr(rdx, 1016), zmm14)); + TEST_INSTRUCTION("62727E4832B200040000" , vpmovqb(qword_ptr(rdx, 1024), zmm14)); + TEST_INSTRUCTION("62727E48327280" , vpmovqb(qword_ptr(rdx, -1024), zmm14)); + TEST_INSTRUCTION("62727E4832B2F8FBFFFF" , vpmovqb(qword_ptr(rdx, -1032), zmm14)); + TEST_INSTRUCTION("62E27E482211" , vpmovsqb(qword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62E27E4E2211" , k(k6).vpmovsqb(qword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62A27E482294F034120000" , vpmovsqb(qword_ptr(rax, r14, 3, 4660), zmm18)); + TEST_INSTRUCTION("62E27E4822527F" , vpmovsqb(qword_ptr(rdx, 1016), zmm18)); + TEST_INSTRUCTION("62E27E48229200040000" , vpmovsqb(qword_ptr(rdx, 1024), zmm18)); + TEST_INSTRUCTION("62E27E48225280" , vpmovsqb(qword_ptr(rdx, -1024), zmm18)); + TEST_INSTRUCTION("62E27E482292F8FBFFFF" , vpmovsqb(qword_ptr(rdx, -1032), zmm18)); + TEST_INSTRUCTION("62727E481229" , vpmovusqb(qword_ptr(rcx), zmm13)); + TEST_INSTRUCTION("62727E4A1229" , k(k2).vpmovusqb(qword_ptr(rcx), zmm13)); + TEST_INSTRUCTION("62327E4812ACF034120000" , vpmovusqb(qword_ptr(rax, r14, 3, 4660), zmm13)); + TEST_INSTRUCTION("62727E48126A7F" , vpmovusqb(qword_ptr(rdx, 1016), zmm13)); + TEST_INSTRUCTION("62727E4812AA00040000" , vpmovusqb(qword_ptr(rdx, 1024), zmm13)); + TEST_INSTRUCTION("62727E48126A80" , vpmovusqb(qword_ptr(rdx, -1024), zmm13)); + TEST_INSTRUCTION("62727E4812AAF8FBFFFF" , vpmovusqb(qword_ptr(rdx, -1032), zmm13)); + TEST_INSTRUCTION("62E27E483431" , vpmovqw(xmmword_ptr(rcx), zmm22)); + TEST_INSTRUCTION("62E27E4E3431" , k(k6).vpmovqw(xmmword_ptr(rcx), zmm22)); + TEST_INSTRUCTION("62A27E4834B4F034120000" , vpmovqw(xmmword_ptr(rax, r14, 3, 4660), zmm22)); + TEST_INSTRUCTION("62E27E4834727F" , vpmovqw(xmmword_ptr(rdx, 2032), zmm22)); + TEST_INSTRUCTION("62E27E4834B200080000" , vpmovqw(xmmword_ptr(rdx, 2048), zmm22)); + TEST_INSTRUCTION("62E27E48347280" , vpmovqw(xmmword_ptr(rdx, -2048), zmm22)); + TEST_INSTRUCTION("62E27E4834B2F0F7FFFF" , vpmovqw(xmmword_ptr(rdx, -2064), zmm22)); + TEST_INSTRUCTION("62627E482411" , vpmovsqw(xmmword_ptr(rcx), zmm26)); + TEST_INSTRUCTION("62627E4A2411" , k(k2).vpmovsqw(xmmword_ptr(rcx), zmm26)); + TEST_INSTRUCTION("62227E482494F034120000" , vpmovsqw(xmmword_ptr(rax, r14, 3, 4660), zmm26)); + TEST_INSTRUCTION("62627E4824527F" , vpmovsqw(xmmword_ptr(rdx, 2032), zmm26)); + TEST_INSTRUCTION("62627E48249200080000" , vpmovsqw(xmmword_ptr(rdx, 2048), zmm26)); + TEST_INSTRUCTION("62627E48245280" , vpmovsqw(xmmword_ptr(rdx, -2048), zmm26)); + TEST_INSTRUCTION("62627E482492F0F7FFFF" , vpmovsqw(xmmword_ptr(rdx, -2064), zmm26)); + TEST_INSTRUCTION("62F27E481431" , vpmovusqw(xmmword_ptr(rcx), zmm6)); + TEST_INSTRUCTION("62F27E4F1431" , k(k7).vpmovusqw(xmmword_ptr(rcx), zmm6)); + TEST_INSTRUCTION("62B27E4814B4F034120000" , vpmovusqw(xmmword_ptr(rax, r14, 3, 4660), zmm6)); + TEST_INSTRUCTION("62F27E4814727F" , vpmovusqw(xmmword_ptr(rdx, 2032), zmm6)); + TEST_INSTRUCTION("62F27E4814B200080000" , vpmovusqw(xmmword_ptr(rdx, 2048), zmm6)); + TEST_INSTRUCTION("62F27E48147280" , vpmovusqw(xmmword_ptr(rdx, -2048), zmm6)); + TEST_INSTRUCTION("62F27E4814B2F0F7FFFF" , vpmovusqw(xmmword_ptr(rdx, -2064), zmm6)); + TEST_INSTRUCTION("62727E483511" , vpmovqd(ymmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("62727E4D3511" , k(k5).vpmovqd(ymmword_ptr(rcx), zmm10)); + TEST_INSTRUCTION("62327E483594F034120000" , vpmovqd(ymmword_ptr(rax, r14, 3, 4660), zmm10)); + TEST_INSTRUCTION("62727E4835527F" , vpmovqd(ymmword_ptr(rdx, 4064), zmm10)); + TEST_INSTRUCTION("62727E48359200100000" , vpmovqd(ymmword_ptr(rdx, 4096), zmm10)); + TEST_INSTRUCTION("62727E48355280" , vpmovqd(ymmword_ptr(rdx, -4096), zmm10)); + TEST_INSTRUCTION("62727E483592E0EFFFFF" , vpmovqd(ymmword_ptr(rdx, -4128), zmm10)); + TEST_INSTRUCTION("62E27E482511" , vpmovsqd(ymmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62E27E4D2511" , k(k5).vpmovsqd(ymmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62A27E482594F034120000" , vpmovsqd(ymmword_ptr(rax, r14, 3, 4660), zmm18)); + TEST_INSTRUCTION("62E27E4825527F" , vpmovsqd(ymmword_ptr(rdx, 4064), zmm18)); + TEST_INSTRUCTION("62E27E48259200100000" , vpmovsqd(ymmword_ptr(rdx, 4096), zmm18)); + TEST_INSTRUCTION("62E27E48255280" , vpmovsqd(ymmword_ptr(rdx, -4096), zmm18)); + TEST_INSTRUCTION("62E27E482592E0EFFFFF" , vpmovsqd(ymmword_ptr(rdx, -4128), zmm18)); + TEST_INSTRUCTION("62E27E481509" , vpmovusqd(ymmword_ptr(rcx), zmm17)); + TEST_INSTRUCTION("62E27E4C1509" , k(k4).vpmovusqd(ymmword_ptr(rcx), zmm17)); + TEST_INSTRUCTION("62A27E48158CF034120000" , vpmovusqd(ymmword_ptr(rax, r14, 3, 4660), zmm17)); + TEST_INSTRUCTION("62E27E48154A7F" , vpmovusqd(ymmword_ptr(rdx, 4064), zmm17)); + TEST_INSTRUCTION("62E27E48158A00100000" , vpmovusqd(ymmword_ptr(rdx, 4096), zmm17)); + TEST_INSTRUCTION("62E27E48154A80" , vpmovusqd(ymmword_ptr(rdx, -4096), zmm17)); + TEST_INSTRUCTION("62E27E48158AE0EFFFFF" , vpmovusqd(ymmword_ptr(rdx, -4128), zmm17)); + TEST_INSTRUCTION("62627E483129" , vpmovdb(xmmword_ptr(rcx), zmm29)); + TEST_INSTRUCTION("62627E4C3129" , k(k4).vpmovdb(xmmword_ptr(rcx), zmm29)); + TEST_INSTRUCTION("62227E4831ACF034120000" , vpmovdb(xmmword_ptr(rax, r14, 3, 4660), zmm29)); + TEST_INSTRUCTION("62627E48316A7F" , vpmovdb(xmmword_ptr(rdx, 2032), zmm29)); + TEST_INSTRUCTION("62627E4831AA00080000" , vpmovdb(xmmword_ptr(rdx, 2048), zmm29)); + TEST_INSTRUCTION("62627E48316A80" , vpmovdb(xmmword_ptr(rdx, -2048), zmm29)); + TEST_INSTRUCTION("62627E4831AAF0F7FFFF" , vpmovdb(xmmword_ptr(rdx, -2064), zmm29)); + TEST_INSTRUCTION("62627E482121" , vpmovsdb(xmmword_ptr(rcx), zmm28)); + TEST_INSTRUCTION("62627E4D2121" , k(k5).vpmovsdb(xmmword_ptr(rcx), zmm28)); + TEST_INSTRUCTION("62227E4821A4F034120000" , vpmovsdb(xmmword_ptr(rax, r14, 3, 4660), zmm28)); + TEST_INSTRUCTION("62627E4821627F" , vpmovsdb(xmmword_ptr(rdx, 2032), zmm28)); + TEST_INSTRUCTION("62627E4821A200080000" , vpmovsdb(xmmword_ptr(rdx, 2048), zmm28)); + TEST_INSTRUCTION("62627E48216280" , vpmovsdb(xmmword_ptr(rdx, -2048), zmm28)); + TEST_INSTRUCTION("62627E4821A2F0F7FFFF" , vpmovsdb(xmmword_ptr(rdx, -2064), zmm28)); + TEST_INSTRUCTION("62627E481131" , vpmovusdb(xmmword_ptr(rcx), zmm30)); + TEST_INSTRUCTION("62627E491131" , k(k1).vpmovusdb(xmmword_ptr(rcx), zmm30)); + TEST_INSTRUCTION("62227E4811B4F034120000" , vpmovusdb(xmmword_ptr(rax, r14, 3, 4660), zmm30)); + TEST_INSTRUCTION("62627E4811727F" , vpmovusdb(xmmword_ptr(rdx, 2032), zmm30)); + TEST_INSTRUCTION("62627E4811B200080000" , vpmovusdb(xmmword_ptr(rdx, 2048), zmm30)); + TEST_INSTRUCTION("62627E48117280" , vpmovusdb(xmmword_ptr(rdx, -2048), zmm30)); + TEST_INSTRUCTION("62627E4811B2F0F7FFFF" , vpmovusdb(xmmword_ptr(rdx, -2064), zmm30)); + TEST_INSTRUCTION("62F27E483329" , vpmovdw(ymmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62F27E4F3329" , k(k7).vpmovdw(ymmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62B27E4833ACF034120000" , vpmovdw(ymmword_ptr(rax, r14, 3, 4660), zmm5)); + TEST_INSTRUCTION("62F27E48336A7F" , vpmovdw(ymmword_ptr(rdx, 4064), zmm5)); + TEST_INSTRUCTION("62F27E4833AA00100000" , vpmovdw(ymmword_ptr(rdx, 4096), zmm5)); + TEST_INSTRUCTION("62F27E48336A80" , vpmovdw(ymmword_ptr(rdx, -4096), zmm5)); + TEST_INSTRUCTION("62F27E4833AAE0EFFFFF" , vpmovdw(ymmword_ptr(rdx, -4128), zmm5)); + TEST_INSTRUCTION("62E27E482311" , vpmovsdw(ymmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62E27E4F2311" , k(k7).vpmovsdw(ymmword_ptr(rcx), zmm18)); + TEST_INSTRUCTION("62A27E482394F034120000" , vpmovsdw(ymmword_ptr(rax, r14, 3, 4660), zmm18)); + TEST_INSTRUCTION("62E27E4823527F" , vpmovsdw(ymmword_ptr(rdx, 4064), zmm18)); + TEST_INSTRUCTION("62E27E48239200100000" , vpmovsdw(ymmword_ptr(rdx, 4096), zmm18)); + TEST_INSTRUCTION("62E27E48235280" , vpmovsdw(ymmword_ptr(rdx, -4096), zmm18)); + TEST_INSTRUCTION("62E27E482392E0EFFFFF" , vpmovsdw(ymmword_ptr(rdx, -4128), zmm18)); + TEST_INSTRUCTION("62F27E481329" , vpmovusdw(ymmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62F27E4C1329" , k(k4).vpmovusdw(ymmword_ptr(rcx), zmm5)); + TEST_INSTRUCTION("62B27E4813ACF034120000" , vpmovusdw(ymmword_ptr(rax, r14, 3, 4660), zmm5)); + TEST_INSTRUCTION("62F27E48136A7F" , vpmovusdw(ymmword_ptr(rdx, 4064), zmm5)); + TEST_INSTRUCTION("62F27E4813AA00100000" , vpmovusdw(ymmword_ptr(rdx, 4096), zmm5)); + TEST_INSTRUCTION("62F27E48136A80" , vpmovusdw(ymmword_ptr(rdx, -4096), zmm5)); + TEST_INSTRUCTION("62F27E4813AAE0EFFFFF" , vpmovusdw(ymmword_ptr(rdx, -4128), zmm5)); + TEST_INSTRUCTION("62C1FC4878E6" , vcvttpd2udq(ymm20, zmm14)); + TEST_INSTRUCTION("62C1FC4B78E6" , k(k3).vcvttpd2udq(ymm20, zmm14)); + TEST_INSTRUCTION("62C1FCCB78E6" , k(k3).z().vcvttpd2udq(ymm20, zmm14)); + TEST_INSTRUCTION("62C1FC1878E6" , sae().vcvttpd2udq(ymm20, zmm14)); + TEST_INSTRUCTION("62E1FC487821" , vcvttpd2udq(ymm20, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A1FC4878A4F034120000" , vcvttpd2udq(ymm20, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E1FC587821" , vcvttpd2udq(ymm20, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E1FC4878627F" , vcvttpd2udq(ymm20, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E1FC4878A200200000" , vcvttpd2udq(ymm20, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E1FC48786280" , vcvttpd2udq(ymm20, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E1FC4878A2C0DFFFFF" , vcvttpd2udq(ymm20, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E1FC5878627F" , vcvttpd2udq(ymm20, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E1FC5878A200040000" , vcvttpd2udq(ymm20, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E1FC58786280" , vcvttpd2udq(ymm20, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E1FC5878A2F8FBFFFF" , vcvttpd2udq(ymm20, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62B17C4878EC" , vcvttps2udq(zmm5, zmm20)); + TEST_INSTRUCTION("62B17C4A78EC" , k(k2).vcvttps2udq(zmm5, zmm20)); + TEST_INSTRUCTION("62B17CCA78EC" , k(k2).z().vcvttps2udq(zmm5, zmm20)); + TEST_INSTRUCTION("62B17C1878EC" , sae().vcvttps2udq(zmm5, zmm20)); + TEST_INSTRUCTION("62F17C487829" , vcvttps2udq(zmm5, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62B17C4878ACF034120000" , vcvttps2udq(zmm5, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17C587829" , vcvttps2udq(zmm5, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62F17C48786A7F" , vcvttps2udq(zmm5, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62F17C4878AA00200000" , vcvttps2udq(zmm5, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62F17C48786A80" , vcvttps2udq(zmm5, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62F17C4878AAC0DFFFFF" , vcvttps2udq(zmm5, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62F17C58786A7F" , vcvttps2udq(zmm5, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62F17C5878AA00020000" , vcvttps2udq(zmm5, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62F17C58786A80" , vcvttps2udq(zmm5, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62F17C5878AAFCFDFFFF" , vcvttps2udq(zmm5, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62B17F0878C7" , vcvttsd2usi(eax, xmm23)); + TEST_INSTRUCTION("62B17F1878C7" , sae().vcvttsd2usi(eax, xmm23)); + TEST_INSTRUCTION("62F17F087801" , vcvttsd2usi(eax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F087884F034120000" , vcvttsd2usi(eax, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17F0878427F" , vcvttsd2usi(eax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F08788200040000" , vcvttsd2usi(eax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08784280" , vcvttsd2usi(eax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F087882F8FBFFFF" , vcvttsd2usi(eax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B17F0878EF" , vcvttsd2usi(ebp, xmm23)); + TEST_INSTRUCTION("62B17F1878EF" , sae().vcvttsd2usi(ebp, xmm23)); + TEST_INSTRUCTION("62F17F087829" , vcvttsd2usi(ebp, qword_ptr(rcx))); + TEST_INSTRUCTION("62B17F0878ACF034120000" , vcvttsd2usi(ebp, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17F08786A7F" , vcvttsd2usi(ebp, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F17F0878AA00040000" , vcvttsd2usi(ebp, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F17F08786A80" , vcvttsd2usi(ebp, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F17F0878AAF8FBFFFF" , vcvttsd2usi(ebp, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62317F0878EF" , vcvttsd2usi(r13d, xmm23)); + TEST_INSTRUCTION("62317F1878EF" , sae().vcvttsd2usi(r13d, xmm23)); + TEST_INSTRUCTION("62717F087829" , vcvttsd2usi(r13d, qword_ptr(rcx))); + TEST_INSTRUCTION("62317F0878ACF034120000" , vcvttsd2usi(r13d, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62717F08786A7F" , vcvttsd2usi(r13d, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62717F0878AA00040000" , vcvttsd2usi(r13d, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62717F08786A80" , vcvttsd2usi(r13d, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62717F0878AAF8FBFFFF" , vcvttsd2usi(r13d, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B1FF0878C3" , vcvttsd2usi(rax, xmm19)); + TEST_INSTRUCTION("62B1FF1878C3" , sae().vcvttsd2usi(rax, xmm19)); + TEST_INSTRUCTION("62F1FF087801" , vcvttsd2usi(rax, qword_ptr(rcx))); + TEST_INSTRUCTION("62B1FF087884F034120000" , vcvttsd2usi(rax, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FF0878427F" , vcvttsd2usi(rax, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("62F1FF08788200040000" , vcvttsd2usi(rax, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("62F1FF08784280" , vcvttsd2usi(rax, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("62F1FF087882F8FBFFFF" , vcvttsd2usi(rax, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("6231FF0878C3" , vcvttsd2usi(r8, xmm19)); + TEST_INSTRUCTION("6231FF1878C3" , sae().vcvttsd2usi(r8, xmm19)); + TEST_INSTRUCTION("6271FF087801" , vcvttsd2usi(r8, qword_ptr(rcx))); + TEST_INSTRUCTION("6231FF087884F034120000" , vcvttsd2usi(r8, qword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271FF0878427F" , vcvttsd2usi(r8, qword_ptr(rdx, 1016))); + TEST_INSTRUCTION("6271FF08788200040000" , vcvttsd2usi(r8, qword_ptr(rdx, 1024))); + TEST_INSTRUCTION("6271FF08784280" , vcvttsd2usi(r8, qword_ptr(rdx, -1024))); + TEST_INSTRUCTION("6271FF087882F8FBFFFF" , vcvttsd2usi(r8, qword_ptr(rdx, -1032))); + TEST_INSTRUCTION("62B17E0878C5" , vcvttss2usi(eax, xmm21)); + TEST_INSTRUCTION("62B17E1878C5" , sae().vcvttss2usi(eax, xmm21)); + TEST_INSTRUCTION("62F17E087801" , vcvttss2usi(eax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E087884F034120000" , vcvttss2usi(eax, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17E0878427F" , vcvttss2usi(eax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E08788200020000" , vcvttss2usi(eax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08784280" , vcvttss2usi(eax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E087882FCFDFFFF" , vcvttss2usi(eax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62B17E0878ED" , vcvttss2usi(ebp, xmm21)); + TEST_INSTRUCTION("62B17E1878ED" , sae().vcvttss2usi(ebp, xmm21)); + TEST_INSTRUCTION("62F17E087829" , vcvttss2usi(ebp, dword_ptr(rcx))); + TEST_INSTRUCTION("62B17E0878ACF034120000" , vcvttss2usi(ebp, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F17E08786A7F" , vcvttss2usi(ebp, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F17E0878AA00020000" , vcvttss2usi(ebp, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F17E08786A80" , vcvttss2usi(ebp, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F17E0878AAFCFDFFFF" , vcvttss2usi(ebp, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62317E0878ED" , vcvttss2usi(r13d, xmm21)); + TEST_INSTRUCTION("62317E1878ED" , sae().vcvttss2usi(r13d, xmm21)); + TEST_INSTRUCTION("62717E087829" , vcvttss2usi(r13d, dword_ptr(rcx))); + TEST_INSTRUCTION("62317E0878ACF034120000" , vcvttss2usi(r13d, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62717E08786A7F" , vcvttss2usi(r13d, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62717E0878AA00020000" , vcvttss2usi(r13d, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62717E08786A80" , vcvttss2usi(r13d, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62717E0878AAFCFDFFFF" , vcvttss2usi(r13d, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("62F1FE0878C7" , vcvttss2usi(rax, xmm7)); + TEST_INSTRUCTION("62F1FE1878C7" , sae().vcvttss2usi(rax, xmm7)); + TEST_INSTRUCTION("62F1FE087801" , vcvttss2usi(rax, dword_ptr(rcx))); + TEST_INSTRUCTION("62B1FE087884F034120000" , vcvttss2usi(rax, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62F1FE0878427F" , vcvttss2usi(rax, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("62F1FE08788200020000" , vcvttss2usi(rax, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("62F1FE08784280" , vcvttss2usi(rax, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("62F1FE087882FCFDFFFF" , vcvttss2usi(rax, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6271FE0878C7" , vcvttss2usi(r8, xmm7)); + TEST_INSTRUCTION("6271FE1878C7" , sae().vcvttss2usi(r8, xmm7)); + TEST_INSTRUCTION("6271FE087801" , vcvttss2usi(r8, dword_ptr(rcx))); + TEST_INSTRUCTION("6231FE087884F034120000" , vcvttss2usi(r8, dword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("6271FE0878427F" , vcvttss2usi(r8, dword_ptr(rdx, 508))); + TEST_INSTRUCTION("6271FE08788200020000" , vcvttss2usi(r8, dword_ptr(rdx, 512))); + TEST_INSTRUCTION("6271FE08784280" , vcvttss2usi(r8, dword_ptr(rdx, -512))); + TEST_INSTRUCTION("6271FE087882FCFDFFFF" , vcvttss2usi(r8, dword_ptr(rdx, -516))); + TEST_INSTRUCTION("6252654876C9" , vpermi2d(zmm9, zmm3, zmm9)); + TEST_INSTRUCTION("6252654976C9" , k(k1).vpermi2d(zmm9, zmm3, zmm9)); + TEST_INSTRUCTION("625265C976C9" , k(k1).z().vpermi2d(zmm9, zmm3, zmm9)); + TEST_INSTRUCTION("627265487609" , vpermi2d(zmm9, zmm3, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62326548768CF034120000" , vpermi2d(zmm9, zmm3, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("627265587609" , vpermi2d(zmm9, zmm3, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62726548764A7F" , vpermi2d(zmm9, zmm3, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62726548768A00200000" , vpermi2d(zmm9, zmm3, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62726548764A80" , vpermi2d(zmm9, zmm3, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62726548768AC0DFFFFF" , vpermi2d(zmm9, zmm3, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62726558764A7F" , vpermi2d(zmm9, zmm3, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62726558768A00020000" , vpermi2d(zmm9, zmm3, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62726558764A80" , vpermi2d(zmm9, zmm3, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62726558768AFCFDFFFF" , vpermi2d(zmm9, zmm3, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("6282CD4076E9" , vpermi2q(zmm21, zmm22, zmm25)); + TEST_INSTRUCTION("6282CD4276E9" , k(k2).vpermi2q(zmm21, zmm22, zmm25)); + TEST_INSTRUCTION("6282CDC276E9" , k(k2).z().vpermi2q(zmm21, zmm22, zmm25)); + TEST_INSTRUCTION("62E2CD407629" , vpermi2q(zmm21, zmm22, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2CD4076ACF034120000" , vpermi2q(zmm21, zmm22, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2CD507629" , vpermi2q(zmm21, zmm22, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2CD40766A7F" , vpermi2q(zmm21, zmm22, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2CD4076AA00200000" , vpermi2q(zmm21, zmm22, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2CD40766A80" , vpermi2q(zmm21, zmm22, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2CD4076AAC0DFFFFF" , vpermi2q(zmm21, zmm22, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2CD50766A7F" , vpermi2q(zmm21, zmm22, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2CD5076AA00040000" , vpermi2q(zmm21, zmm22, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2CD50766A80" , vpermi2q(zmm21, zmm22, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2CD5076AAF8FBFFFF" , vpermi2q(zmm21, zmm22, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62622D4077D1" , vpermi2ps(zmm26, zmm26, zmm1)); + TEST_INSTRUCTION("62622D4577D1" , k(k5).vpermi2ps(zmm26, zmm26, zmm1)); + TEST_INSTRUCTION("62622DC577D1" , k(k5).z().vpermi2ps(zmm26, zmm26, zmm1)); + TEST_INSTRUCTION("62622D407711" , vpermi2ps(zmm26, zmm26, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62222D407794F034120000" , vpermi2ps(zmm26, zmm26, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62622D507711" , vpermi2ps(zmm26, zmm26, dword_ptr(rcx)._1to16())); + TEST_INSTRUCTION("62622D4077527F" , vpermi2ps(zmm26, zmm26, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62622D40779200200000" , vpermi2ps(zmm26, zmm26, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62622D40775280" , vpermi2ps(zmm26, zmm26, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62622D407792C0DFFFFF" , vpermi2ps(zmm26, zmm26, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62622D5077527F" , vpermi2ps(zmm26, zmm26, dword_ptr(rdx, 508)._1to16())); + TEST_INSTRUCTION("62622D50779200020000" , vpermi2ps(zmm26, zmm26, dword_ptr(rdx, 512)._1to16())); + TEST_INSTRUCTION("62622D50775280" , vpermi2ps(zmm26, zmm26, dword_ptr(rdx, -512)._1to16())); + TEST_INSTRUCTION("62622D507792FCFDFFFF" , vpermi2ps(zmm26, zmm26, dword_ptr(rdx, -516)._1to16())); + TEST_INSTRUCTION("62A2A54077ED" , vpermi2pd(zmm21, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A54477ED" , k(k4).vpermi2pd(zmm21, zmm27, zmm21)); + TEST_INSTRUCTION("62A2A5C477ED" , k(k4).z().vpermi2pd(zmm21, zmm27, zmm21)); + TEST_INSTRUCTION("62E2A5407729" , vpermi2pd(zmm21, zmm27, zmmword_ptr(rcx))); + TEST_INSTRUCTION("62A2A54077ACF034120000" , vpermi2pd(zmm21, zmm27, zmmword_ptr(rax, r14, 3, 4660))); + TEST_INSTRUCTION("62E2A5507729" , vpermi2pd(zmm21, zmm27, qword_ptr(rcx)._1to8())); + TEST_INSTRUCTION("62E2A540776A7F" , vpermi2pd(zmm21, zmm27, zmmword_ptr(rdx, 8128))); + TEST_INSTRUCTION("62E2A54077AA00200000" , vpermi2pd(zmm21, zmm27, zmmword_ptr(rdx, 8192))); + TEST_INSTRUCTION("62E2A540776A80" , vpermi2pd(zmm21, zmm27, zmmword_ptr(rdx, -8192))); + TEST_INSTRUCTION("62E2A54077AAC0DFFFFF" , vpermi2pd(zmm21, zmm27, zmmword_ptr(rdx, -8256))); + TEST_INSTRUCTION("62E2A550776A7F" , vpermi2pd(zmm21, zmm27, qword_ptr(rdx, 1016)._1to8())); + TEST_INSTRUCTION("62E2A55077AA00040000" , vpermi2pd(zmm21, zmm27, qword_ptr(rdx, 1024)._1to8())); + TEST_INSTRUCTION("62E2A550776A80" , vpermi2pd(zmm21, zmm27, qword_ptr(rdx, -1024)._1to8())); + TEST_INSTRUCTION("62E2A55077AAF8FBFFFF" , vpermi2pd(zmm21, zmm27, qword_ptr(rdx, -1032)._1to8())); + TEST_INSTRUCTION("62D2FD4192B4C67B000000" , k(k1).vgatherdpd(zmm6, zmmword_ptr(r14, ymm16, 3, 123))); + TEST_INSTRUCTION("62D2FD4192740120" , k(k1).vgatherdpd(zmm6, zmmword_ptr(r9, ymm16, 0, 256))); + TEST_INSTRUCTION("62F2FD4192B48100040000" , k(k1).vgatherdpd(zmm6, zmmword_ptr(rcx, ymm16, 2, 1024))); + TEST_INSTRUCTION("62527D41928CDE7B000000" , k(k1).vgatherdps(zmm9, zmmword_ptr(r14, zmm19, 3, 123))); + TEST_INSTRUCTION("62527D41924C1940" , k(k1).vgatherdps(zmm9, zmmword_ptr(r9, zmm19, 0, 256))); + TEST_INSTRUCTION("62727D41928C9900040000" , k(k1).vgatherdps(zmm9, zmmword_ptr(rcx, zmm19, 2, 1024))); + TEST_INSTRUCTION("6242FD4993ACD67B000000" , k(k1).vgatherqpd(zmm29, zmmword_ptr(r14, zmm2, 3, 123))); + TEST_INSTRUCTION("6242FD49936C1120" , k(k1).vgatherqpd(zmm29, zmmword_ptr(r9, zmm2, 0, 256))); + TEST_INSTRUCTION("6262FD4993AC9100040000" , k(k1).vgatherqpd(zmm29, zmmword_ptr(rcx, zmm2, 2, 1024))); + TEST_INSTRUCTION("62C27D499394E67B000000" , k(k1).vgatherqps(ymm18, ymmword_ptr(r14, zmm4, 3, 123))); + TEST_INSTRUCTION("62C27D4993542140" , k(k1).vgatherqps(ymm18, ymmword_ptr(r9, zmm4, 0, 256))); + TEST_INSTRUCTION("62E27D499394A100040000" , k(k1).vgatherqps(ymm18, ymmword_ptr(rcx, zmm4, 2, 1024))); + TEST_INSTRUCTION("62827D49908CDE7B000000" , k(k1).vpgatherdd(zmm17, zmmword_ptr(r14, zmm11, 3, 123))); + TEST_INSTRUCTION("62827D49904C1940" , k(k1).vpgatherdd(zmm17, zmmword_ptr(r9, zmm11, 0, 256))); + TEST_INSTRUCTION("62A27D49908C9900040000" , k(k1).vpgatherdd(zmm17, zmmword_ptr(rcx, zmm11, 2, 1024))); + TEST_INSTRUCTION("6212FD499084F67B000000" , k(k1).vpgatherdq(zmm8, zmmword_ptr(r14, ymm14, 3, 123))); + TEST_INSTRUCTION("6212FD4990443120" , k(k1).vpgatherdq(zmm8, zmmword_ptr(r9, ymm14, 0, 256))); + TEST_INSTRUCTION("6232FD499084B100040000" , k(k1).vpgatherdq(zmm8, zmmword_ptr(rcx, ymm14, 2, 1024))); + TEST_INSTRUCTION("62D27D41919CCE7B000000" , k(k1).vpgatherqd(ymm3, ymmword_ptr(r14, zmm17, 3, 123))); + TEST_INSTRUCTION("62D27D41915C0940" , k(k1).vpgatherqd(ymm3, ymmword_ptr(r9, zmm17, 0, 256))); + TEST_INSTRUCTION("62F27D41919C8900040000" , k(k1).vpgatherqd(ymm3, ymmword_ptr(rcx, zmm17, 2, 1024))); + TEST_INSTRUCTION("62C2FD41918CEE7B000000" , k(k1).vpgatherqq(zmm17, zmmword_ptr(r14, zmm21, 3, 123))); + TEST_INSTRUCTION("62C2FD41914C2920" , k(k1).vpgatherqq(zmm17, zmmword_ptr(r9, zmm21, 0, 256))); + TEST_INSTRUCTION("62E2FD41918CA900040000" , k(k1).vpgatherqq(zmm17, zmmword_ptr(rcx, zmm21, 2, 1024))); + TEST_INSTRUCTION("62C27D41A09CC67B000000" , k(k1).vpscatterdd(zmmword_ptr(r14, zmm16, 3, 123), zmm19)); + TEST_INSTRUCTION("62C27D41A09CC67B000000" , k(k1).vpscatterdd(zmmword_ptr(r14, zmm16, 3, 123), zmm19)); + TEST_INSTRUCTION("62C27D41A05C0140" , k(k1).vpscatterdd(zmmword_ptr(r9, zmm16, 0, 256), zmm19)); + TEST_INSTRUCTION("62E27D41A09C8100040000" , k(k1).vpscatterdd(zmmword_ptr(rcx, zmm16, 2, 1024), zmm19)); + TEST_INSTRUCTION("62D2FD49A0ACF67B000000" , k(k1).vpscatterdq(zmmword_ptr(r14, ymm6, 3, 123), zmm5)); + TEST_INSTRUCTION("62D2FD49A0ACF67B000000" , k(k1).vpscatterdq(zmmword_ptr(r14, ymm6, 3, 123), zmm5)); + TEST_INSTRUCTION("62D2FD49A06C3120" , k(k1).vpscatterdq(zmmword_ptr(r9, ymm6, 0, 256), zmm5)); + TEST_INSTRUCTION("62F2FD49A0ACB100040000" , k(k1).vpscatterdq(zmmword_ptr(rcx, ymm6, 2, 1024), zmm5)); + TEST_INSTRUCTION("62C27D49A1A4D67B000000" , k(k1).vpscatterqd(ymmword_ptr(r14, zmm2, 3, 123), ymm20)); + TEST_INSTRUCTION("62C27D49A1A4D67B000000" , k(k1).vpscatterqd(ymmword_ptr(r14, zmm2, 3, 123), ymm20)); + TEST_INSTRUCTION("62C27D49A1641140" , k(k1).vpscatterqd(ymmword_ptr(r9, zmm2, 0, 256), ymm20)); + TEST_INSTRUCTION("62E27D49A1A49100040000" , k(k1).vpscatterqd(ymmword_ptr(rcx, zmm2, 2, 1024), ymm20)); + TEST_INSTRUCTION("6252FD41A1B4E67B000000" , k(k1).vpscatterqq(zmmword_ptr(r14, zmm20, 3, 123), zmm14)); + TEST_INSTRUCTION("6252FD41A1B4E67B000000" , k(k1).vpscatterqq(zmmword_ptr(r14, zmm20, 3, 123), zmm14)); + TEST_INSTRUCTION("6252FD41A1742120" , k(k1).vpscatterqq(zmmword_ptr(r9, zmm20, 0, 256), zmm14)); + TEST_INSTRUCTION("6272FD41A1B4A100040000" , k(k1).vpscatterqq(zmmword_ptr(rcx, zmm20, 2, 1024), zmm14)); + TEST_INSTRUCTION("6282FD41A294C67B000000" , k(k1).vscatterdpd(zmmword_ptr(r14, ymm24, 3, 123), zmm18)); + TEST_INSTRUCTION("6282FD41A294C67B000000" , k(k1).vscatterdpd(zmmword_ptr(r14, ymm24, 3, 123), zmm18)); + TEST_INSTRUCTION("6282FD41A2540120" , k(k1).vscatterdpd(zmmword_ptr(r9, ymm24, 0, 256), zmm18)); + TEST_INSTRUCTION("62A2FD41A2948100040000" , k(k1).vscatterdpd(zmmword_ptr(rcx, ymm24, 2, 1024), zmm18)); + TEST_INSTRUCTION("62C27D41A28CDE7B000000" , k(k1).vscatterdps(zmmword_ptr(r14, zmm19, 3, 123), zmm17)); + TEST_INSTRUCTION("62C27D41A28CDE7B000000" , k(k1).vscatterdps(zmmword_ptr(r14, zmm19, 3, 123), zmm17)); + TEST_INSTRUCTION("62C27D41A24C1940" , k(k1).vscatterdps(zmmword_ptr(r9, zmm19, 0, 256), zmm17)); + TEST_INSTRUCTION("62E27D41A28C9900040000" , k(k1).vscatterdps(zmmword_ptr(rcx, zmm19, 2, 1024), zmm17)); + TEST_INSTRUCTION("6282FD41A3B4E67B000000" , k(k1).vscatterqpd(zmmword_ptr(r14, zmm28, 3, 123), zmm22)); + TEST_INSTRUCTION("6282FD41A3B4E67B000000" , k(k1).vscatterqpd(zmmword_ptr(r14, zmm28, 3, 123), zmm22)); + TEST_INSTRUCTION("6282FD41A3742120" , k(k1).vscatterqpd(zmmword_ptr(r9, zmm28, 0, 256), zmm22)); + TEST_INSTRUCTION("62A2FD41A3B4A100040000" , k(k1).vscatterqpd(zmmword_ptr(rcx, zmm28, 2, 1024), zmm22)); + TEST_INSTRUCTION("62927D41A3B4DE7B000000" , k(k1).vscatterqps(ymmword_ptr(r14, zmm27, 3, 123), ymm6)); + TEST_INSTRUCTION("62927D41A3B4DE7B000000" , k(k1).vscatterqps(ymmword_ptr(r14, zmm27, 3, 123), ymm6)); + TEST_INSTRUCTION("62927D41A3741940" , k(k1).vscatterqps(ymmword_ptr(r9, zmm27, 0, 256), ymm6)); + TEST_INSTRUCTION("62B27D41A3B49900040000" , k(k1).vscatterqps(ymmword_ptr(rcx, zmm27, 2, 1024), ymm6)); + TEST_INSTRUCTION("6282FD41A294DE85FFFFFF" , k(k1).vscatterdpd(zmmword_ptr(r14, ymm27, 3, -123), zmm18)); + TEST_INSTRUCTION("6282FD41A294DE85FFFFFF" , k(k1).vscatterdpd(zmmword_ptr(r14, ymm27, 3, -123), zmm18)); + TEST_INSTRUCTION("6282FD41A2541920" , k(k1).vscatterdpd(zmmword_ptr(r9, ymm27, 0, 256), zmm18)); + TEST_INSTRUCTION("62A2FD41A2949900040000" , k(k1).vscatterdpd(zmmword_ptr(rcx, ymm27, 2, 1024), zmm18)); + TEST_INSTRUCTION("62D27D41A28CCE85FFFFFF" , k(k1).vscatterdps(zmmword_ptr(r14, zmm17, 3, -123), zmm1)); + TEST_INSTRUCTION("62D27D41A28CCE85FFFFFF" , k(k1).vscatterdps(zmmword_ptr(r14, zmm17, 3, -123), zmm1)); + TEST_INSTRUCTION("62D27D41A24C0940" , k(k1).vscatterdps(zmmword_ptr(r9, zmm17, 0, 256), zmm1)); + TEST_INSTRUCTION("62F27D41A28C8900040000" , k(k1).vscatterdps(zmmword_ptr(rcx, zmm17, 2, 1024), zmm1)); + TEST_INSTRUCTION("6212FD41A384CE85FFFFFF" , k(k1).vscatterqpd(zmmword_ptr(r14, zmm25, 3, -123), zmm8)); + TEST_INSTRUCTION("6212FD41A384CE85FFFFFF" , k(k1).vscatterqpd(zmmword_ptr(r14, zmm25, 3, -123), zmm8)); + TEST_INSTRUCTION("6212FD41A3440920" , k(k1).vscatterqpd(zmmword_ptr(r9, zmm25, 0, 256), zmm8)); + TEST_INSTRUCTION("6232FD41A3848900040000" , k(k1).vscatterqpd(zmmword_ptr(rcx, zmm25, 2, 1024), zmm8)); + TEST_INSTRUCTION("62127D49A3ACD685FFFFFF" , k(k1).vscatterqps(ymmword_ptr(r14, zmm10, 3, -123), ymm13)); + TEST_INSTRUCTION("62127D49A3ACD685FFFFFF" , k(k1).vscatterqps(ymmword_ptr(r14, zmm10, 3, -123), ymm13)); + TEST_INSTRUCTION("62127D49A36C1140" , k(k1).vscatterqps(ymmword_ptr(r9, zmm10, 0, 256), ymm13)); + TEST_INSTRUCTION("62327D49A3AC9100040000" , k(k1).vscatterqps(ymmword_ptr(rcx, zmm10, 2, 1024), ymm13)); + TEST_INSTRUCTION("6242FD4992B4EE85FFFFFF" , k(k1).vgatherdpd(zmm30, zmmword_ptr(r14, ymm5, 3, -123))); + TEST_INSTRUCTION("6242FD4992742920" , k(k1).vgatherdpd(zmm30, zmmword_ptr(r9, ymm5, 0, 256))); + TEST_INSTRUCTION("6262FD4992B4A900040000" , k(k1).vgatherdpd(zmm30, zmmword_ptr(rcx, ymm5, 2, 1024))); + TEST_INSTRUCTION("62127D419284D685FFFFFF" , k(k1).vgatherdps(zmm8, zmmword_ptr(r14, zmm26, 3, -123))); + TEST_INSTRUCTION("62127D4192441140" , k(k1).vgatherdps(zmm8, zmmword_ptr(r9, zmm26, 0, 256))); + TEST_INSTRUCTION("62327D4192849100040000" , k(k1).vgatherdps(zmm8, zmmword_ptr(rcx, zmm26, 2, 1024))); + TEST_INSTRUCTION("6202FD49939CEE85FFFFFF" , k(k1).vgatherqpd(zmm27, zmmword_ptr(r14, zmm13, 3, -123))); + TEST_INSTRUCTION("6202FD49935C2920" , k(k1).vgatherqpd(zmm27, zmmword_ptr(r9, zmm13, 0, 256))); + TEST_INSTRUCTION("6222FD49939CA900040000" , k(k1).vgatherqpd(zmm27, zmmword_ptr(rcx, zmm13, 2, 1024))); + TEST_INSTRUCTION("62027D49939CF685FFFFFF" , k(k1).vgatherqps(ymm27, ymmword_ptr(r14, zmm14, 3, -123))); + TEST_INSTRUCTION("62027D49935C3140" , k(k1).vgatherqps(ymm27, ymmword_ptr(r9, zmm14, 0, 256))); + TEST_INSTRUCTION("62227D49939CB100040000" , k(k1).vgatherqps(ymm27, ymmword_ptr(rcx, zmm14, 2, 1024))); + TEST_INSTRUCTION("62D27D4190BCC685FFFFFF" , k(k1).vpgatherdd(zmm7, zmmword_ptr(r14, zmm16, 3, -123))); + TEST_INSTRUCTION("62D27D41907C0140" , k(k1).vpgatherdd(zmm7, zmmword_ptr(r9, zmm16, 0, 256))); + TEST_INSTRUCTION("62F27D4190BC8100040000" , k(k1).vpgatherdd(zmm7, zmmword_ptr(rcx, zmm16, 2, 1024))); + TEST_INSTRUCTION("6242FD49908CFE85FFFFFF" , k(k1).vpgatherdq(zmm25, zmmword_ptr(r14, ymm7, 3, -123))); + TEST_INSTRUCTION("6242FD49904C3920" , k(k1).vpgatherdq(zmm25, zmmword_ptr(r9, ymm7, 0, 256))); + TEST_INSTRUCTION("6262FD49908CB900040000" , k(k1).vpgatherdq(zmm25, zmmword_ptr(rcx, ymm7, 2, 1024))); + TEST_INSTRUCTION("62C27D41919CCE85FFFFFF" , k(k1).vpgatherqd(ymm19, ymmword_ptr(r14, zmm17, 3, -123))); + TEST_INSTRUCTION("62C27D41915C0940" , k(k1).vpgatherqd(ymm19, ymmword_ptr(r9, zmm17, 0, 256))); + TEST_INSTRUCTION("62E27D41919C8900040000" , k(k1).vpgatherqd(ymm19, ymmword_ptr(rcx, zmm17, 2, 1024))); + TEST_INSTRUCTION("6212FD499194EE85FFFFFF" , k(k1).vpgatherqq(zmm10, zmmword_ptr(r14, zmm13, 3, -123))); + TEST_INSTRUCTION("6212FD4991542920" , k(k1).vpgatherqq(zmm10, zmmword_ptr(r9, zmm13, 0, 256))); + TEST_INSTRUCTION("6232FD499194A900040000" , k(k1).vpgatherqq(zmm10, zmmword_ptr(rcx, zmm13, 2, 1024))); + TEST_INSTRUCTION("62C27D49A0BCE685FFFFFF" , k(k1).vpscatterdd(zmmword_ptr(r14, zmm4, 3, -123), zmm23)); + TEST_INSTRUCTION("62C27D49A0BCE685FFFFFF" , k(k1).vpscatterdd(zmmword_ptr(r14, zmm4, 3, -123), zmm23)); + TEST_INSTRUCTION("62C27D49A07C2140" , k(k1).vpscatterdd(zmmword_ptr(r9, zmm4, 0, 256), zmm23)); + TEST_INSTRUCTION("62E27D49A0BCA100040000" , k(k1).vpscatterdd(zmmword_ptr(rcx, zmm4, 2, 1024), zmm23)); + TEST_INSTRUCTION("6292FD41A08CCE85FFFFFF" , k(k1).vpscatterdq(zmmword_ptr(r14, ymm25, 3, -123), zmm1)); + TEST_INSTRUCTION("6292FD41A08CCE85FFFFFF" , k(k1).vpscatterdq(zmmword_ptr(r14, ymm25, 3, -123), zmm1)); + TEST_INSTRUCTION("6292FD41A04C0920" , k(k1).vpscatterdq(zmmword_ptr(r9, ymm25, 0, 256), zmm1)); + TEST_INSTRUCTION("62B2FD41A08C8900040000" , k(k1).vpscatterdq(zmmword_ptr(rcx, ymm25, 2, 1024), zmm1)); + TEST_INSTRUCTION("62C27D41A1BCF685FFFFFF" , k(k1).vpscatterqd(ymmword_ptr(r14, zmm22, 3, -123), ymm23)); + TEST_INSTRUCTION("62C27D41A1BCF685FFFFFF" , k(k1).vpscatterqd(ymmword_ptr(r14, zmm22, 3, -123), ymm23)); + TEST_INSTRUCTION("62C27D41A17C3140" , k(k1).vpscatterqd(ymmword_ptr(r9, zmm22, 0, 256), ymm23)); + TEST_INSTRUCTION("62E27D41A1BCB100040000" , k(k1).vpscatterqd(ymmword_ptr(rcx, zmm22, 2, 1024), ymm23)); + TEST_INSTRUCTION("6292FD49A194C685FFFFFF" , k(k1).vpscatterqq(zmmword_ptr(r14, zmm8, 3, -123), zmm2)); + TEST_INSTRUCTION("6292FD49A194C685FFFFFF" , k(k1).vpscatterqq(zmmword_ptr(r14, zmm8, 3, -123), zmm2)); + TEST_INSTRUCTION("6292FD49A1540120" , k(k1).vpscatterqq(zmmword_ptr(r9, zmm8, 0, 256), zmm2)); + TEST_INSTRUCTION("62B2FD49A1948100040000" , k(k1).vpscatterqq(zmmword_ptr(rcx, zmm8, 2, 1024), zmm2)); + +} + static void ASMJIT_NOINLINE testX64AssemblerAMX(AssemblerTester<x86::Assembler>& tester) noexcept { using namespace x86; @@ -8181,7 +17782,7 @@ static void ASMJIT_NOINLINE testX64AssemblerExtras(AssemblerTester<x86::Assemble TEST_INSTRUCTION("62F16C1FC25498400F" , k(k7).vcmpps(k2, xmm2, dword_ptr(rax, rbx, 2, 256)._1to4(), 15)); TEST_INSTRUCTION("62F16C3FC25498400F" , k(k7).vcmpps(k2, ymm2, dword_ptr(rax, rbx, 2, 256)._1to8(), 15)); TEST_INSTRUCTION("62F16C5FC25498400F" , k(k7).vcmpps(k2, zmm2, dword_ptr(rax, rbx, 2, 256)._1to16(), 15)); - TEST_INSTRUCTION("62F1FD58C2C100" , sae().vcmppd(k0, zmm0, zmm1, 0x00)); + TEST_INSTRUCTION("62F1FD18C2C100" , sae().vcmppd(k0, zmm0, zmm1, 0x00)); TEST_INSTRUCTION("6201FD182EF5" , sae().vucomisd(xmm30, xmm29)); TEST_INSTRUCTION("62017C182EF5" , sae().vucomiss(xmm30, xmm29)); TEST_INSTRUCTION("C4E2FD91040500000000" , vpgatherqq(ymm0, ptr(0, ymm0), ymm0)); @@ -8210,12 +17811,16 @@ static void ASMJIT_NOINLINE testX64AssemblerExtras(AssemblerTester<x86::Assemble bool testX64Assembler(const TestSettings& settings) noexcept { using namespace x86; - AssemblerTester<Assembler> tester(Environment::kArchX64, settings); + AssemblerTester<Assembler> tester(Arch::kX64, settings); tester.printHeader("X64"); + TEST_INSTRUCTION("62919D18C2D2AB" , sae().vcmppd(k2, zmm12, zmm26, 171)); + testX64AssemblerBase(tester); testX64AssemblerMMX_SSE(tester); testX64AssemblerAVX(tester); + testX64AssemblerAVX512_FP16(tester); + testX64AssemblerAVX512_LLVM(tester); testX64AssemblerAMX(tester); testX64AssemblerExtras(tester); diff --git a/test/asmjit_test_assembler_x86.cpp b/test/asmjit_test_assembler_x86.cpp index 4a23fa9..a5ea03a 100644 --- a/test/asmjit_test_assembler_x86.cpp +++ b/test/asmjit_test_assembler_x86.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> #if !defined(ASMJIT_NO_X86) @@ -7532,6 +7514,650 @@ static void ASMJIT_NOINLINE testX86AssemblerAVX(AssemblerTester<x86::Assembler>& TEST_INSTRUCTION("C5F877" , vzeroupper()); } +static void ASMJIT_NOINLINE testX86AssemblerAVX512_FP16(AssemblerTester<x86::Assembler>& tester) noexcept { + using namespace x86; + + TEST_INSTRUCTION("62F5560810F4" , vmovsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F57E0F10B4F400000010" , k(k7).vmovsh(xmm6, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E081031" , vmovsh(xmm6, word_ptr(ecx))); + TEST_INSTRUCTION("62F57E0810717F" , vmovsh(xmm6, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57E8F107280" , k(k7).z().vmovsh(xmm6, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57E0F11B4F400000010" , k(k7).vmovsh(word_ptr(esp, esi, 3, 268435456), xmm6)); + TEST_INSTRUCTION("62F57E081131" , vmovsh(word_ptr(ecx), xmm6)); + TEST_INSTRUCTION("62F57E0811717F" , vmovsh(word_ptr(ecx, 254), xmm6)); + TEST_INSTRUCTION("62F57E0F117280" , k(k7).vmovsh(word_ptr(edx, -256), xmm6)); + TEST_INSTRUCTION("62F57D086EF2" , vmovw(xmm6, edx)); + TEST_INSTRUCTION("62F57D087EF2" , vmovw(edx, xmm6)); + TEST_INSTRUCTION("62F57D086EB4F400000010" , vmovw(xmm6, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D086E31" , vmovw(xmm6, word_ptr(ecx))); + TEST_INSTRUCTION("62F57D086E717F" , vmovw(xmm6, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57D086E717F" , vmovw(xmm6, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57D086E7280" , vmovw(xmm6, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57D087EB4F400000010" , vmovw(word_ptr(esp, esi, 3, 268435456), xmm6)); + TEST_INSTRUCTION("62F57D087E31" , vmovw(word_ptr(ecx), xmm6)); + TEST_INSTRUCTION("62F57D087E717F" , vmovw(word_ptr(ecx, 254), xmm6)); + TEST_INSTRUCTION("62F57D087E7280" , vmovw(word_ptr(edx, -256), xmm6)); + + TEST_INSTRUCTION("62F5544858F4" , vaddph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5541858F4" , rn_sae().vaddph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5544F58B4F400000010" , k(k7).vaddph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554585831" , vaddph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F5544858717F" , vaddph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F554DF587280" , k(k7).z().vaddph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F5560858F4" , vaddsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5561858F4" , rn_sae().vaddsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F58B4F400000010" , k(k7).vaddsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085831" , vaddsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F5560858717F" , vaddsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F587280" , k(k7).z().vaddsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F35448C2EC7B" , vcmpph(k5, zmm5, zmm4, 123)); + TEST_INSTRUCTION("62F35418C2EC7B" , sae().vcmpph(k5, zmm5, zmm4, 123)); + TEST_INSTRUCTION("62F3544FC2ACF4000000107B" , k(k7).vcmpph(k5, zmm5, zmmword_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F35458C2297B" , vcmpph(k5, zmm5, word_ptr(ecx)._1to32(), 123)); + TEST_INSTRUCTION("62F35448C2697F7B" , vcmpph(k5, zmm5, zmmword_ptr(ecx, 8128), 123)); + TEST_INSTRUCTION("62F3545FC26A807B" , k(k7).vcmpph(k5, zmm5, word_ptr(edx, -256)._1to32(), 123)); + TEST_INSTRUCTION("62F35608C2EC7B" , vcmpsh(k5, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F35618C2EC7B" , sae().vcmpsh(k5, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F3560FC2ACF4000000107B" , k(k7).vcmpsh(k5, xmm5, word_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F35608C2297B" , vcmpsh(k5, xmm5, word_ptr(ecx), 123)); + TEST_INSTRUCTION("62F35608C2697F7B" , vcmpsh(k5, xmm5, word_ptr(ecx, 254), 123)); + TEST_INSTRUCTION("62F3560FC26A807B" , k(k7).vcmpsh(k5, xmm5, word_ptr(edx, -256), 123)); + TEST_INSTRUCTION("62F57C082FF5" , vcomish(xmm6, xmm5)); + TEST_INSTRUCTION("62F57C182FF5" , sae().vcomish(xmm6, xmm5)); + TEST_INSTRUCTION("62F57C082FB4F400000010" , vcomish(xmm6, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C082F31" , vcomish(xmm6, word_ptr(ecx))); + TEST_INSTRUCTION("62F57C082F717F" , vcomish(xmm6, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57C082F7280" , vcomish(xmm6, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57C485BF5" , vcvtdq2ph(ymm6, zmm5)); + TEST_INSTRUCTION("62F57C185BF5" , rn_sae().vcvtdq2ph(ymm6, zmm5)); + TEST_INSTRUCTION("62F57C4F5BB4F400000010" , k(k7).vcvtdq2ph(ymm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C585B31" , vcvtdq2ph(ymm6, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57C485B717F" , vcvtdq2ph(ymm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57CDF5B7280" , k(k7).z().vcvtdq2ph(ymm6, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F5FD485AF5" , vcvtpd2ph(xmm6, zmm5)); + TEST_INSTRUCTION("62F5FD185AF5" , rn_sae().vcvtpd2ph(xmm6, zmm5)); + TEST_INSTRUCTION("62F5FD4F5AB4F400000010" , k(k7).vcvtpd2ph(xmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F5FD585A31" , vcvtpd2ph(xmm6, qword_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F5FD485A717F" , vcvtpd2ph(xmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F5FDDF5A7280" , k(k7).z().vcvtpd2ph(xmm6, qword_ptr(edx, -1024)._1to8())); + TEST_INSTRUCTION("62F57D485BF5" , vcvtph2dq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57D185BF5" , rn_sae().vcvtph2dq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57D4F5BB4F400000010" , k(k7).vcvtph2dq(zmm6, ymmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D585B31" , vcvtph2dq(zmm6, word_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57D485B717F" , vcvtph2dq(zmm6, ymmword_ptr(ecx, 4064))); + TEST_INSTRUCTION("62F57DDF5B7280" , k(k7).z().vcvtph2dq(zmm6, word_ptr(edx, -256)._1to16())); + TEST_INSTRUCTION("62F57C485AF5" , vcvtph2pd(zmm6, xmm5)); + TEST_INSTRUCTION("62F57C185AF5" , sae().vcvtph2pd(zmm6, xmm5)); + TEST_INSTRUCTION("62F57C4F5AB4F400000010" , k(k7).vcvtph2pd(zmm6, xmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C585A31" , vcvtph2pd(zmm6, word_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F57C485A717F" , vcvtph2pd(zmm6, xmmword_ptr(ecx, 2032))); + TEST_INSTRUCTION("62F57CDF5A7280" , k(k7).z().vcvtph2pd(zmm6, word_ptr(edx, -256)._1to8())); + TEST_INSTRUCTION("62F67D4813F5" , vcvtph2psx(zmm6, ymm5)); + TEST_INSTRUCTION("62F67D1813F5" , sae().vcvtph2psx(zmm6, ymm5)); + TEST_INSTRUCTION("62F67D4F13B4F400000010" , k(k7).vcvtph2psx(zmm6, ymmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F67D581331" , vcvtph2psx(zmm6, word_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F67D4813717F" , vcvtph2psx(zmm6, ymmword_ptr(ecx, 4064))); + TEST_INSTRUCTION("62F67DDF137280" , k(k7).z().vcvtph2psx(zmm6, word_ptr(edx, -256)._1to16())); + TEST_INSTRUCTION("62F57D487BF5" , vcvtph2qq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D187BF5" , rn_sae().vcvtph2qq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D4F7BB4F400000010" , k(k7).vcvtph2qq(zmm6, xmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D587B31" , vcvtph2qq(zmm6, word_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F57D487B717F" , vcvtph2qq(zmm6, xmmword_ptr(ecx, 2032))); + TEST_INSTRUCTION("62F57DDF7B7280" , k(k7).z().vcvtph2qq(zmm6, word_ptr(edx, -256)._1to8())); + TEST_INSTRUCTION("62F57C4879F5" , vcvtph2udq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57C1879F5" , rn_sae().vcvtph2udq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57C4F79B4F400000010" , k(k7).vcvtph2udq(zmm6, ymmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C587931" , vcvtph2udq(zmm6, word_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57C4879717F" , vcvtph2udq(zmm6, ymmword_ptr(ecx, 4064))); + TEST_INSTRUCTION("62F57CDF797280" , k(k7).z().vcvtph2udq(zmm6, word_ptr(edx, -256)._1to16())); + TEST_INSTRUCTION("62F57D4879F5" , vcvtph2uqq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D1879F5" , rn_sae().vcvtph2uqq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D4F79B4F400000010" , k(k7).vcvtph2uqq(zmm6, xmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D587931" , vcvtph2uqq(zmm6, word_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F57D4879717F" , vcvtph2uqq(zmm6, xmmword_ptr(ecx, 2032))); + TEST_INSTRUCTION("62F57DDF797280" , k(k7).z().vcvtph2uqq(zmm6, word_ptr(edx, -256)._1to8())); + TEST_INSTRUCTION("62F57C487DF5" , vcvtph2uw(zmm6, zmm5)); + TEST_INSTRUCTION("62F57C187DF5" , rn_sae().vcvtph2uw(zmm6, zmm5)); + TEST_INSTRUCTION("62F57C4F7DB4F400000010" , k(k7).vcvtph2uw(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C587D31" , vcvtph2uw(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57C487D717F" , vcvtph2uw(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57CDF7D7280" , k(k7).z().vcvtph2uw(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F57D487DF5" , vcvtph2w(zmm6, zmm5)); + TEST_INSTRUCTION("62F57D187DF5" , rn_sae().vcvtph2w(zmm6, zmm5)); + TEST_INSTRUCTION("62F57D4F7DB4F400000010" , k(k7).vcvtph2w(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D587D31" , vcvtph2w(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57D487D717F" , vcvtph2w(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57DDF7D7280" , k(k7).z().vcvtph2w(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F57D481DF5" , vcvtps2phx(ymm6, zmm5)); + TEST_INSTRUCTION("62F57D181DF5" , rn_sae().vcvtps2phx(ymm6, zmm5)); + TEST_INSTRUCTION("62F57D4F1DB4F400000010" , k(k7).vcvtps2phx(ymm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D581D31" , vcvtps2phx(ymm6, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57D481D717F" , vcvtps2phx(ymm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57DDF1D7280" , k(k7).z().vcvtps2phx(ymm6, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F5FC485BF5" , vcvtqq2ph(xmm6, zmm5)); + TEST_INSTRUCTION("62F5FC185BF5" , rn_sae().vcvtqq2ph(xmm6, zmm5)); + TEST_INSTRUCTION("62F5FC4F5BB4F400000010" , k(k7).vcvtqq2ph(xmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F5FC585B31" , vcvtqq2ph(xmm6, qword_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F5FC485B717F" , vcvtqq2ph(xmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F5FCDF5B7280" , k(k7).z().vcvtqq2ph(xmm6, qword_ptr(edx, -1024)._1to8())); + TEST_INSTRUCTION("62F5D7085AF4" , vcvtsd2sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5D7185AF4" , rn_sae().vcvtsd2sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5D70F5AB4F400000010" , k(k7).vcvtsd2sh(xmm6, xmm5, qword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F5D7085A31" , vcvtsd2sh(xmm6, xmm5, qword_ptr(ecx))); + TEST_INSTRUCTION("62F5D7085A717F" , vcvtsd2sh(xmm6, xmm5, qword_ptr(ecx, 1016))); + TEST_INSTRUCTION("62F5D78F5A7280" , k(k7).z().vcvtsd2sh(xmm6, xmm5, qword_ptr(edx, -1024))); + TEST_INSTRUCTION("62F556085AF4" , vcvtsh2sd(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F556185AF4" , sae().vcvtsh2sd(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F5AB4F400000010" , k(k7).vcvtsh2sd(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085A31" , vcvtsh2sd(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F556085A717F" , vcvtsh2sd(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F5A7280" , k(k7).z().vcvtsh2sd(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57E082DD6" , vcvtsh2si(edx, xmm6)); + TEST_INSTRUCTION("62F57E182DD6" , rn_sae().vcvtsh2si(edx, xmm6)); + TEST_INSTRUCTION("62F57E082D94F400000010" , vcvtsh2si(edx, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E082D11" , vcvtsh2si(edx, word_ptr(ecx))); + TEST_INSTRUCTION("62F57E082D517F" , vcvtsh2si(edx, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57E082D5280" , vcvtsh2si(edx, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F6540813F4" , vcvtsh2ss(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6541813F4" , sae().vcvtsh2ss(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6540F13B4F400000010" , k(k7).vcvtsh2ss(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F654081331" , vcvtsh2ss(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F6540813717F" , vcvtsh2ss(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6548F137280" , k(k7).z().vcvtsh2ss(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57E0879D6" , vcvtsh2usi(edx, xmm6)); + TEST_INSTRUCTION("62F57E1879D6" , rn_sae().vcvtsh2usi(edx, xmm6)); + TEST_INSTRUCTION("62F57E087994F400000010" , vcvtsh2usi(edx, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E087911" , vcvtsh2usi(edx, word_ptr(ecx))); + TEST_INSTRUCTION("62F57E0879517F" , vcvtsh2usi(edx, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57E08795280" , vcvtsh2usi(edx, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F556082AF2" , vcvtsi2sh(xmm6, xmm5, edx)); + TEST_INSTRUCTION("62F556182AF2" , rn_sae().vcvtsi2sh(xmm6, xmm5, edx)); + TEST_INSTRUCTION("62F556082AB4F400000010" , vcvtsi2sh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556082A31" , vcvtsi2sh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F556082A717F" , vcvtsi2sh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F556082A7280" , vcvtsi2sh(xmm6, xmm5, dword_ptr(edx, -512))); + TEST_INSTRUCTION("62F554081DF4" , vcvtss2sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F554181DF4" , rn_sae().vcvtss2sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5540F1DB4F400000010" , k(k7).vcvtss2sh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554081D31" , vcvtss2sh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F554081D717F" , vcvtss2sh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F5548F1D7280" , k(k7).z().vcvtss2sh(xmm6, xmm5, dword_ptr(edx, -512))); + TEST_INSTRUCTION("62F57E485BF5" , vcvttph2dq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57E185BF5" , sae().vcvttph2dq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57E4F5BB4F400000010" , k(k7).vcvttph2dq(zmm6, ymmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E585B31" , vcvttph2dq(zmm6, word_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57E485B717F" , vcvttph2dq(zmm6, ymmword_ptr(ecx, 4064))); + TEST_INSTRUCTION("62F57EDF5B7280" , k(k7).z().vcvttph2dq(zmm6, word_ptr(edx, -256)._1to16())); + TEST_INSTRUCTION("62F57D487AF5" , vcvttph2qq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D187AF5" , sae().vcvttph2qq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D4F7AB4F400000010" , k(k7).vcvttph2qq(zmm6, xmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D587A31" , vcvttph2qq(zmm6, word_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F57D487A717F" , vcvttph2qq(zmm6, xmmword_ptr(ecx, 2032))); + TEST_INSTRUCTION("62F57DDF7A7280" , k(k7).z().vcvttph2qq(zmm6, word_ptr(edx, -256)._1to8())); + TEST_INSTRUCTION("62F57C4878F5" , vcvttph2udq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57C1878F5" , sae().vcvttph2udq(zmm6, ymm5)); + TEST_INSTRUCTION("62F57C4F78B4F400000010" , k(k7).vcvttph2udq(zmm6, ymmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C587831" , vcvttph2udq(zmm6, word_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57C4878717F" , vcvttph2udq(zmm6, ymmword_ptr(ecx, 4064))); + TEST_INSTRUCTION("62F57CDF787280" , k(k7).z().vcvttph2udq(zmm6, word_ptr(edx, -256)._1to16())); + TEST_INSTRUCTION("62F57D4878F5" , vcvttph2uqq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D1878F5" , sae().vcvttph2uqq(zmm6, xmm5)); + TEST_INSTRUCTION("62F57D4F78B4F400000010" , k(k7).vcvttph2uqq(zmm6, xmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D587831" , vcvttph2uqq(zmm6, word_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F57D4878717F" , vcvttph2uqq(zmm6, xmmword_ptr(ecx, 2032))); + TEST_INSTRUCTION("62F57DDF787280" , k(k7).z().vcvttph2uqq(zmm6, word_ptr(edx, -256)._1to8())); + TEST_INSTRUCTION("62F57C487CF5" , vcvttph2uw(zmm6, zmm5)); + TEST_INSTRUCTION("62F57C187CF5" , sae().vcvttph2uw(zmm6, zmm5)); + TEST_INSTRUCTION("62F57C4F7CB4F400000010" , k(k7).vcvttph2uw(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C587C31" , vcvttph2uw(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57C487C717F" , vcvttph2uw(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57CDF7C7280" , k(k7).z().vcvttph2uw(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F57D487CF5" , vcvttph2w(zmm6, zmm5)); + TEST_INSTRUCTION("62F57D187CF5" , sae().vcvttph2w(zmm6, zmm5)); + TEST_INSTRUCTION("62F57D4F7CB4F400000010" , k(k7).vcvttph2w(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57D587C31" , vcvttph2w(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57D487C717F" , vcvttph2w(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57DDF7C7280" , k(k7).z().vcvttph2w(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F57E082CD6" , vcvttsh2si(edx, xmm6)); + TEST_INSTRUCTION("62F57E182CD6" , sae().vcvttsh2si(edx, xmm6)); + TEST_INSTRUCTION("62F57E082C94F400000010" , vcvttsh2si(edx, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E082C11" , vcvttsh2si(edx, word_ptr(ecx))); + TEST_INSTRUCTION("62F57E082C517F" , vcvttsh2si(edx, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57E082C5280" , vcvttsh2si(edx, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57E0878D6" , vcvttsh2usi(edx, xmm6)); + TEST_INSTRUCTION("62F57E1878D6" , sae().vcvttsh2usi(edx, xmm6)); + TEST_INSTRUCTION("62F57E087894F400000010" , vcvttsh2usi(edx, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E087811" , vcvttsh2usi(edx, word_ptr(ecx))); + TEST_INSTRUCTION("62F57E0878517F" , vcvttsh2usi(edx, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57E08785280" , vcvttsh2usi(edx, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57F487AF5" , vcvtudq2ph(ymm6, zmm5)); + TEST_INSTRUCTION("62F57F187AF5" , rn_sae().vcvtudq2ph(ymm6, zmm5)); + TEST_INSTRUCTION("62F57F4F7AB4F400000010" , k(k7).vcvtudq2ph(ymm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57F587A31" , vcvtudq2ph(ymm6, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F57F487A717F" , vcvtudq2ph(ymm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57FDF7A7280" , k(k7).z().vcvtudq2ph(ymm6, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F5FF487AF5" , vcvtuqq2ph(xmm6, zmm5)); + TEST_INSTRUCTION("62F5FF187AF5" , rn_sae().vcvtuqq2ph(xmm6, zmm5)); + TEST_INSTRUCTION("62F5FF4F7AB4F400000010" , k(k7).vcvtuqq2ph(xmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F5FF587A31" , vcvtuqq2ph(xmm6, qword_ptr(ecx)._1to8())); + TEST_INSTRUCTION("62F5FF487A717F" , vcvtuqq2ph(xmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F5FFDF7A7280" , k(k7).z().vcvtuqq2ph(xmm6, qword_ptr(edx, -1024)._1to8())); + TEST_INSTRUCTION("62F556087BF2" , vcvtusi2sh(xmm6, xmm5, edx)); + TEST_INSTRUCTION("62F556187BF2" , rn_sae().vcvtusi2sh(xmm6, xmm5, edx)); + TEST_INSTRUCTION("62F556087BB4F400000010" , vcvtusi2sh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556087B31" , vcvtusi2sh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F556087B717F" , vcvtusi2sh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F556087B7280" , vcvtusi2sh(xmm6, xmm5, dword_ptr(edx, -512))); + TEST_INSTRUCTION("62F57F487DF5" , vcvtuw2ph(zmm6, zmm5)); + TEST_INSTRUCTION("62F57F187DF5" , rn_sae().vcvtuw2ph(zmm6, zmm5)); + TEST_INSTRUCTION("62F57F4F7DB4F400000010" , k(k7).vcvtuw2ph(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57F587D31" , vcvtuw2ph(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57F487D717F" , vcvtuw2ph(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57FDF7D7280" , k(k7).z().vcvtuw2ph(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F57E487DF5" , vcvtw2ph(zmm6, zmm5)); + TEST_INSTRUCTION("62F57E187DF5" , rn_sae().vcvtw2ph(zmm6, zmm5)); + TEST_INSTRUCTION("62F57E4F7DB4F400000010" , k(k7).vcvtw2ph(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57E587D31" , vcvtw2ph(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57E487D717F" , vcvtw2ph(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57EDF7D7280" , k(k7).z().vcvtw2ph(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F554485EF4" , vdivph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F554185EF4" , rn_sae().vdivph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5544F5EB4F400000010" , k(k7).vdivph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554585E31" , vdivph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F554485E717F" , vdivph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F554DF5E7280" , k(k7).z().vdivph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F556085EF4" , vdivsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F556185EF4" , rn_sae().vdivsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F5EB4F400000010" , k(k7).vdivsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085E31" , vdivsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F556085E717F" , vdivsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F5E7280" , k(k7).z().vdivsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F554485FF4" , vmaxph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F554185FF4" , sae().vmaxph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5544F5FB4F400000010" , k(k7).vmaxph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554585F31" , vmaxph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F554485F717F" , vmaxph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F554DF5F7280" , k(k7).z().vmaxph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F556085FF4" , vmaxsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F556185FF4" , sae().vmaxsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F5FB4F400000010" , k(k7).vmaxsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085F31" , vmaxsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F556085F717F" , vmaxsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F5F7280" , k(k7).z().vmaxsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F554485DF4" , vminph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F554185DF4" , sae().vminph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5544F5DB4F400000010" , k(k7).vminph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554585D31" , vminph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F554485D717F" , vminph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F554DF5D7280" , k(k7).z().vminph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F556085DF4" , vminsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F556185DF4" , sae().vminsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F5DB4F400000010" , k(k7).vminsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085D31" , vminsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F556085D717F" , vminsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F5D7280" , k(k7).z().vminsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F5544859F4" , vmulph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5541859F4" , rn_sae().vmulph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5544F59B4F400000010" , k(k7).vmulph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554585931" , vmulph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F5544859717F" , vmulph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F554DF597280" , k(k7).z().vmulph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F5560859F4" , vmulsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5561859F4" , rn_sae().vmulsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F59B4F400000010" , k(k7).vmulsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085931" , vmulsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F5560859717F" , vmulsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F597280" , k(k7).z().vmulsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F554485CF4" , vsubph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F554185CF4" , rn_sae().vsubph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F5544F5CB4F400000010" , k(k7).vsubph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F554585C31" , vsubph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F554485C717F" , vsubph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F554DF5C7280" , k(k7).z().vsubph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F556085CF4" , vsubsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F556185CF4" , rn_sae().vsubsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F5CB4F400000010" , k(k7).vsubsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085C31" , vsubsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F556085C717F" , vsubsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F5C7280" , k(k7).z().vsubsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57C082EF5" , vucomish(xmm6, xmm5)); + TEST_INSTRUCTION("62F57C182EF5" , sae().vucomish(xmm6, xmm5)); + TEST_INSTRUCTION("62F57C082EB4F400000010" , vucomish(xmm6, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C082E31" , vucomish(xmm6, word_ptr(ecx))); + TEST_INSTRUCTION("62F57C082E717F" , vucomish(xmm6, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F57C082E7280" , vucomish(xmm6, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F37C4866EE7B" , vfpclassph(k5, zmm6, 123)); + TEST_INSTRUCTION("62F37C4F66ACF4000000107B" , k(k7).vfpclassph(k5, zmmword_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F37C5866297B" , vfpclassph(k5, word_ptr(ecx)._1to32(), 123)); + TEST_INSTRUCTION("62F37C4866697F7B" , vfpclassph(k5, zmmword_ptr(ecx, 8128), 123)); + TEST_INSTRUCTION("62F37C5F666A807B" , k(k7).vfpclassph(k5, word_ptr(edx, -256)._1to32(), 123)); + TEST_INSTRUCTION("62F37C0867EE7B" , vfpclasssh(k5, xmm6, 123)); + TEST_INSTRUCTION("62F37C0F67ACF4000000107B" , k(k7).vfpclasssh(k5, word_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F37C0867297B" , vfpclasssh(k5, word_ptr(ecx), 123)); + TEST_INSTRUCTION("62F37C0867697F7B" , vfpclasssh(k5, word_ptr(ecx, 254), 123)); + TEST_INSTRUCTION("62F37C0F676A807B" , k(k7).vfpclasssh(k5, word_ptr(edx, -256), 123)); + TEST_INSTRUCTION("62F67D4842F5" , vgetexpph(zmm6, zmm5)); + TEST_INSTRUCTION("62F67D1842F5" , sae().vgetexpph(zmm6, zmm5)); + TEST_INSTRUCTION("62F67D4F42B4F400000010" , k(k7).vgetexpph(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F67D584231" , vgetexpph(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F67D4842717F" , vgetexpph(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F67DDF427280" , k(k7).z().vgetexpph(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F6550843F4" , vgetexpsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6551843F4" , sae().vgetexpsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F43B4F400000010" , k(k7).vgetexpsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655084331" , vgetexpsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F6550843717F" , vgetexpsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F437280" , k(k7).z().vgetexpsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F37C4826F57B" , vgetmantph(zmm6, zmm5, 123)); + TEST_INSTRUCTION("62F37C1826F57B" , sae().vgetmantph(zmm6, zmm5, 123)); + TEST_INSTRUCTION("62F37C4F26B4F4000000107B" , k(k7).vgetmantph(zmm6, zmmword_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F37C5826317B" , vgetmantph(zmm6, word_ptr(ecx)._1to32(), 123)); + TEST_INSTRUCTION("62F37C4826717F7B" , vgetmantph(zmm6, zmmword_ptr(ecx, 8128), 123)); + TEST_INSTRUCTION("62F37CDF2672807B" , k(k7).z().vgetmantph(zmm6, word_ptr(edx, -256)._1to32(), 123)); + TEST_INSTRUCTION("62F3540827F47B" , vgetmantsh(xmm6, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F3541827F47B" , sae().vgetmantsh(xmm6, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F3540F27B4F4000000107B" , k(k7).vgetmantsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F3540827317B" , vgetmantsh(xmm6, xmm5, word_ptr(ecx), 123)); + TEST_INSTRUCTION("62F3540827717F7B" , vgetmantsh(xmm6, xmm5, word_ptr(ecx, 254), 123)); + TEST_INSTRUCTION("62F3548F2772807B" , k(k7).z().vgetmantsh(xmm6, xmm5, word_ptr(edx, -256), 123)); + TEST_INSTRUCTION("62F67D484CF5" , vrcpph(zmm6, zmm5)); + TEST_INSTRUCTION("62F67D4F4CB4F400000010" , k(k7).vrcpph(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F67D584C31" , vrcpph(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F67D484C717F" , vrcpph(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F67DDF4C7280" , k(k7).z().vrcpph(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655084DF4" , vrcpsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F4DB4F400000010" , k(k7).vrcpsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655084D31" , vrcpsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F655084D717F" , vrcpsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F4D7280" , k(k7).z().vrcpsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F37C4856F57B" , vreduceph(zmm6, zmm5, 123)); + TEST_INSTRUCTION("62F37C1856F57B" , sae().vreduceph(zmm6, zmm5, 123)); + TEST_INSTRUCTION("62F37C4F56B4F4000000107B" , k(k7).vreduceph(zmm6, zmmword_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F37C5856317B" , vreduceph(zmm6, word_ptr(ecx)._1to32(), 123)); + TEST_INSTRUCTION("62F37C4856717F7B" , vreduceph(zmm6, zmmword_ptr(ecx, 8128), 123)); + TEST_INSTRUCTION("62F37CDF5672807B" , k(k7).z().vreduceph(zmm6, word_ptr(edx, -256)._1to32(), 123)); + TEST_INSTRUCTION("62F3540857F47B" , vreducesh(xmm6, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F3541857F47B" , sae().vreducesh(xmm6, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F3540F57B4F4000000107B" , k(k7).vreducesh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F3540857317B" , vreducesh(xmm6, xmm5, word_ptr(ecx), 123)); + TEST_INSTRUCTION("62F3540857717F7B" , vreducesh(xmm6, xmm5, word_ptr(ecx, 254), 123)); + TEST_INSTRUCTION("62F3548F5772807B" , k(k7).z().vreducesh(xmm6, xmm5, word_ptr(edx, -256), 123)); + TEST_INSTRUCTION("62F37C4808F57B" , vrndscaleph(zmm6, zmm5, 123)); + TEST_INSTRUCTION("62F37C1808F57B" , sae().vrndscaleph(zmm6, zmm5, 123)); + TEST_INSTRUCTION("62F37C4F08B4F4000000107B" , k(k7).vrndscaleph(zmm6, zmmword_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F37C5808317B" , vrndscaleph(zmm6, word_ptr(ecx)._1to32(), 123)); + TEST_INSTRUCTION("62F37C4808717F7B" , vrndscaleph(zmm6, zmmword_ptr(ecx, 8128), 123)); + TEST_INSTRUCTION("62F37CDF0872807B" , k(k7).z().vrndscaleph(zmm6, word_ptr(edx, -256)._1to32(), 123)); + TEST_INSTRUCTION("62F354080AF47B" , vrndscalesh(xmm6, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F354180AF47B" , sae().vrndscalesh(xmm6, xmm5, xmm4, 123)); + TEST_INSTRUCTION("62F3540F0AB4F4000000107B" , k(k7).vrndscalesh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456), 123)); + TEST_INSTRUCTION("62F354080A317B" , vrndscalesh(xmm6, xmm5, word_ptr(ecx), 123)); + TEST_INSTRUCTION("62F354080A717F7B" , vrndscalesh(xmm6, xmm5, word_ptr(ecx, 254), 123)); + TEST_INSTRUCTION("62F3548F0A72807B" , k(k7).z().vrndscalesh(xmm6, xmm5, word_ptr(edx, -256), 123)); + TEST_INSTRUCTION("62F67D484EF5" , vrsqrtph(zmm6, zmm5)); + TEST_INSTRUCTION("62F67D4F4EB4F400000010" , k(k7).vrsqrtph(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F67D584E31" , vrsqrtph(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F67D484E717F" , vrsqrtph(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F67DDF4E7280" , k(k7).z().vrsqrtph(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655084FF4" , vrsqrtsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F4FB4F400000010" , k(k7).vrsqrtsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655084F31" , vrsqrtsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F655084F717F" , vrsqrtsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F4F7280" , k(k7).z().vrsqrtsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F655482CF4" , vscalefph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F655182CF4" , rn_sae().vscalefph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F2CB4F400000010" , k(k7).vscalefph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655582C31" , vscalefph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F655482C717F" , vscalefph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF2C7280" , k(k7).z().vscalefph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655082DF4" , vscalefsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F655182DF4" , rn_sae().vscalefsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F2DB4F400000010" , k(k7).vscalefsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655082D31" , vscalefsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F655082D717F" , vscalefsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F2D7280" , k(k7).z().vscalefsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F57C4851F5" , vsqrtph(zmm6, zmm5)); + TEST_INSTRUCTION("62F57C1851F5" , rn_sae().vsqrtph(zmm6, zmm5)); + TEST_INSTRUCTION("62F57C4F51B4F400000010" , k(k7).vsqrtph(zmm6, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F57C585131" , vsqrtph(zmm6, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F57C4851717F" , vsqrtph(zmm6, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F57CDF517280" , k(k7).z().vsqrtph(zmm6, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F5560851F4" , vsqrtsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5561851F4" , rn_sae().vsqrtsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F5560F51B4F400000010" , k(k7).vsqrtsh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F556085131" , vsqrtsh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F5560851717F" , vsqrtsh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F5568F517280" , k(k7).z().vsqrtsh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F6554898F4" , vfmadd132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6551898F4" , rn_sae().vfmadd132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F98B4F400000010" , k(k7).vfmadd132ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655589831" , vfmadd132ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F6554898717F" , vfmadd132ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF987280" , k(k7).z().vfmadd132ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F6550899F4" , vfmadd132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6551899F4" , rn_sae().vfmadd132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F99B4F400000010" , k(k7).vfmadd132sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655089931" , vfmadd132sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F6550899717F" , vfmadd132sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F997280" , k(k7).z().vfmadd132sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548A8F4" , vfmadd213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518A8F4" , rn_sae().vfmadd213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FA8B4F400000010" , k(k7).vfmadd213ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558A831" , vfmadd213ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548A8717F" , vfmadd213ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFA87280" , k(k7).z().vfmadd213ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508A9F4" , vfmadd213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518A9F4" , rn_sae().vfmadd213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FA9B4F400000010" , k(k7).vfmadd213sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508A931" , vfmadd213sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508A9717F" , vfmadd213sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FA97280" , k(k7).z().vfmadd213sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548B8F4" , vfmadd231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518B8F4" , rn_sae().vfmadd231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FB8B4F400000010" , k(k7).vfmadd231ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558B831" , vfmadd231ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548B8717F" , vfmadd231ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFB87280" , k(k7).z().vfmadd231ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508B9F4" , vfmadd231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518B9F4" , rn_sae().vfmadd231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FB9B4F400000010" , k(k7).vfmadd231sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508B931" , vfmadd231sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508B9717F" , vfmadd231sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FB97280" , k(k7).z().vfmadd231sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F6554896F4" , vfmaddsub132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6551896F4" , rn_sae().vfmaddsub132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F96B4F400000010" , k(k7).vfmaddsub132ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655589631" , vfmaddsub132ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F6554896717F" , vfmaddsub132ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF967280" , k(k7).z().vfmaddsub132ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65548A6F4" , vfmaddsub213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518A6F4" , rn_sae().vfmaddsub213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FA6B4F400000010" , k(k7).vfmaddsub213ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558A631" , vfmaddsub213ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548A6717F" , vfmaddsub213ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFA67280" , k(k7).z().vfmaddsub213ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65548B6F4" , vfmaddsub231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518B6F4" , rn_sae().vfmaddsub231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FB6B4F400000010" , k(k7).vfmaddsub231ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558B631" , vfmaddsub231ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548B6717F" , vfmaddsub231ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFB67280" , k(k7).z().vfmaddsub231ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655489AF4" , vfmsub132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F655189AF4" , rn_sae().vfmsub132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F9AB4F400000010" , k(k7).vfmsub132ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655589A31" , vfmsub132ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F655489A717F" , vfmsub132ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF9A7280" , k(k7).z().vfmsub132ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655089BF4" , vfmsub132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F655189BF4" , rn_sae().vfmsub132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F9BB4F400000010" , k(k7).vfmsub132sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655089B31" , vfmsub132sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F655089B717F" , vfmsub132sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F9B7280" , k(k7).z().vfmsub132sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548AAF4" , vfmsub213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518AAF4" , rn_sae().vfmsub213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FAAB4F400000010" , k(k7).vfmsub213ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558AA31" , vfmsub213ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548AA717F" , vfmsub213ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFAA7280" , k(k7).z().vfmsub213ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508ABF4" , vfmsub213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518ABF4" , rn_sae().vfmsub213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FABB4F400000010" , k(k7).vfmsub213sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508AB31" , vfmsub213sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508AB717F" , vfmsub213sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FAB7280" , k(k7).z().vfmsub213sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548BAF4" , vfmsub231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518BAF4" , rn_sae().vfmsub231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FBAB4F400000010" , k(k7).vfmsub231ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558BA31" , vfmsub231ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548BA717F" , vfmsub231ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFBA7280" , k(k7).z().vfmsub231ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508BBF4" , vfmsub231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518BBF4" , rn_sae().vfmsub231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FBBB4F400000010" , k(k7).vfmsub231sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508BB31" , vfmsub231sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508BB717F" , vfmsub231sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FBB7280" , k(k7).z().vfmsub231sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F6554897F4" , vfmsubadd132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6551897F4" , rn_sae().vfmsubadd132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F97B4F400000010" , k(k7).vfmsubadd132ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655589731" , vfmsubadd132ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F6554897717F" , vfmsubadd132ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF977280" , k(k7).z().vfmsubadd132ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65548A7F4" , vfmsubadd213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518A7F4" , rn_sae().vfmsubadd213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FA7B4F400000010" , k(k7).vfmsubadd213ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558A731" , vfmsubadd213ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548A7717F" , vfmsubadd213ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFA77280" , k(k7).z().vfmsubadd213ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65548B7F4" , vfmsubadd231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518B7F4" , rn_sae().vfmsubadd231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FB7B4F400000010" , k(k7).vfmsubadd231ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558B731" , vfmsubadd231ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548B7717F" , vfmsubadd231ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFB77280" , k(k7).z().vfmsubadd231ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655489CF4" , vfnmadd132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F655189CF4" , rn_sae().vfnmadd132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F9CB4F400000010" , k(k7).vfnmadd132ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655589C31" , vfnmadd132ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F655489C717F" , vfnmadd132ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF9C7280" , k(k7).z().vfnmadd132ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655089DF4" , vfnmadd132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F655189DF4" , rn_sae().vfnmadd132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F9DB4F400000010" , k(k7).vfnmadd132sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655089D31" , vfnmadd132sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F655089D717F" , vfnmadd132sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F9D7280" , k(k7).z().vfnmadd132sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548ACF4" , vfnmadd213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518ACF4" , rn_sae().vfnmadd213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FACB4F400000010" , k(k7).vfnmadd213ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558AC31" , vfnmadd213ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548AC717F" , vfnmadd213ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFAC7280" , k(k7).z().vfnmadd213ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508ADF4" , vfnmadd213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518ADF4" , rn_sae().vfnmadd213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FADB4F400000010" , k(k7).vfnmadd213sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508AD31" , vfnmadd213sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508AD717F" , vfnmadd213sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FAD7280" , k(k7).z().vfnmadd213sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548BCF4" , vfnmadd231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518BCF4" , rn_sae().vfnmadd231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FBCB4F400000010" , k(k7).vfnmadd231ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558BC31" , vfnmadd231ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548BC717F" , vfnmadd231ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFBC7280" , k(k7).z().vfnmadd231ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508BDF4" , vfnmadd231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518BDF4" , rn_sae().vfnmadd231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FBDB4F400000010" , k(k7).vfnmadd231sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508BD31" , vfnmadd231sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508BD717F" , vfnmadd231sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FBD7280" , k(k7).z().vfnmadd231sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F655489EF4" , vfnmsub132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F655189EF4" , rn_sae().vfnmsub132ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554F9EB4F400000010" , k(k7).vfnmsub132ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655589E31" , vfnmsub132ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F655489E717F" , vfnmsub132ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DF9E7280" , k(k7).z().vfnmsub132ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F655089FF4" , vfnmsub132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F655189FF4" , rn_sae().vfnmsub132sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550F9FB4F400000010" , k(k7).vfnmsub132sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F655089F31" , vfnmsub132sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F655089F717F" , vfnmsub132sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558F9F7280" , k(k7).z().vfnmsub132sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548AEF4" , vfnmsub213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518AEF4" , rn_sae().vfnmsub213ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FAEB4F400000010" , k(k7).vfnmsub213ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558AE31" , vfnmsub213ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548AE717F" , vfnmsub213ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFAE7280" , k(k7).z().vfnmsub213ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508AFF4" , vfnmsub213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518AFF4" , rn_sae().vfnmsub213sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FAFB4F400000010" , k(k7).vfnmsub213sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508AF31" , vfnmsub213sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508AF717F" , vfnmsub213sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FAF7280" , k(k7).z().vfnmsub213sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F65548BEF4" , vfnmsub231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65518BEF4" , rn_sae().vfnmsub231ph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6554FBEB4F400000010" , k(k7).vfnmsub231ph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65558BE31" , vfnmsub231ph(zmm6, zmm5, word_ptr(ecx)._1to32())); + TEST_INSTRUCTION("62F65548BE717F" , vfnmsub231ph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F655DFBE7280" , k(k7).z().vfnmsub231ph(zmm6, zmm5, word_ptr(edx, -256)._1to32())); + TEST_INSTRUCTION("62F65508BFF4" , vfnmsub231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65518BFF4" , rn_sae().vfnmsub231sh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6550FBFB4F400000010" , k(k7).vfnmsub231sh(xmm6, xmm5, word_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65508BF31" , vfnmsub231sh(xmm6, xmm5, word_ptr(ecx))); + TEST_INSTRUCTION("62F65508BF717F" , vfnmsub231sh(xmm6, xmm5, word_ptr(ecx, 254))); + TEST_INSTRUCTION("62F6558FBF7280" , k(k7).z().vfnmsub231sh(xmm6, xmm5, word_ptr(edx, -256))); + TEST_INSTRUCTION("62F6574856F4" , vfcmaddcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6571856F4" , rn_sae().vfcmaddcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6574F56B4F400000010" , k(k7).vfcmaddcph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F657585631" , vfcmaddcph(zmm6, zmm5, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F6574856717F" , vfcmaddcph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F657DF567280" , k(k7).z().vfcmaddcph(zmm6, zmm5, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F6570857F4" , vfcmaddcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6571857F4" , rn_sae().vfcmaddcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6570F57B4F400000010" , k(k7).vfcmaddcsh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F657085731" , vfcmaddcsh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F6570857717F" , vfcmaddcsh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F6578F577280" , k(k7).z().vfcmaddcsh(xmm6, xmm5, dword_ptr(edx, -512))); + TEST_INSTRUCTION("62F65748D6F4" , vfcmulcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65718D6F4" , rn_sae().vfcmulcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6574FD6B4F400000010" , k(k7).vfcmulcph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65758D631" , vfcmulcph(zmm6, zmm5, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F65748D6717F" , vfcmulcph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F657DFD67280" , k(k7).z().vfcmulcph(zmm6, zmm5, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F65708D7F4" , vfcmulcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65718D7F4" , rn_sae().vfcmulcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6570FD7B4F400000010" , k(k7).vfcmulcsh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65708D731" , vfcmulcsh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F65708D7717F" , vfcmulcsh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F6578FD77280" , k(k7).z().vfcmulcsh(xmm6, xmm5, dword_ptr(edx, -512))); + TEST_INSTRUCTION("62F6564856F4" , vfmaddcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6561856F4" , rn_sae().vfmaddcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6564F56B4F400000010" , k(k7).vfmaddcph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F656585631" , vfmaddcph(zmm6, zmm5, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F6564856717F" , vfmaddcph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F656DF567280" , k(k7).z().vfmaddcph(zmm6, zmm5, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F6560857F4" , vfmaddcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6561857F4" , rn_sae().vfmaddcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6560F57B4F400000010" , k(k7).vfmaddcsh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F656085731" , vfmaddcsh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F6560857717F" , vfmaddcsh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F6568F577280" , k(k7).z().vfmaddcsh(xmm6, xmm5, dword_ptr(edx, -512))); + TEST_INSTRUCTION("62F65648D6F4" , vfmulcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F65618D6F4" , rn_sae().vfmulcph(zmm6, zmm5, zmm4)); + TEST_INSTRUCTION("62F6564FD6B4F400000010" , k(k7).vfmulcph(zmm6, zmm5, zmmword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65658D631" , vfmulcph(zmm6, zmm5, dword_ptr(ecx)._1to16())); + TEST_INSTRUCTION("62F65648D6717F" , vfmulcph(zmm6, zmm5, zmmword_ptr(ecx, 8128))); + TEST_INSTRUCTION("62F656DFD67280" , k(k7).z().vfmulcph(zmm6, zmm5, dword_ptr(edx, -512)._1to16())); + TEST_INSTRUCTION("62F65608D7F4" , vfmulcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F65618D7F4" , rn_sae().vfmulcsh(xmm6, xmm5, xmm4)); + TEST_INSTRUCTION("62F6560FD7B4F400000010" , k(k7).vfmulcsh(xmm6, xmm5, dword_ptr(esp, esi, 3, 268435456))); + TEST_INSTRUCTION("62F65608D731" , vfmulcsh(xmm6, xmm5, dword_ptr(ecx))); + TEST_INSTRUCTION("62F65608D7717F" , vfmulcsh(xmm6, xmm5, dword_ptr(ecx, 508))); + TEST_INSTRUCTION("62F6568FD77280" , k(k7).z().vfmulcsh(xmm6, xmm5, dword_ptr(edx, -512))); +} + static void ASMJIT_NOINLINE testX86AssemblerExtras(AssemblerTester<x86::Assembler>& tester) noexcept { using namespace x86; @@ -7656,12 +8282,13 @@ static void ASMJIT_NOINLINE testX86AssemblerExtras(AssemblerTester<x86::Assemble bool testX86Assembler(const TestSettings& settings) noexcept { using namespace x86; - AssemblerTester<Assembler> tester(Environment::kArchX86, settings); + AssemblerTester<Assembler> tester(Arch::kX86, settings); tester.printHeader("X86"); testX86AssemblerBase(tester); testX86AssemblerMMX_SSE(tester); testX86AssemblerAVX(tester); + testX86AssemblerAVX512_FP16(tester); testX86AssemblerExtras(tester); tester.printSummary(); diff --git a/test/asmjit_test_compiler.cpp b/test/asmjit_test_compiler.cpp index 96b5eeb..70a24a9 100644 --- a/test/asmjit_test_compiler.cpp +++ b/test/asmjit_test_compiler.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> @@ -32,6 +14,7 @@ #include <chrono> #include "cmdline.h" +#include "asmjitutils.h" #include "performancetimer.h" #include "asmjit_test_compiler.h" @@ -56,21 +39,6 @@ void compiler_add_a64_tests(TestApp& app); using namespace asmjit; -// ============================================================================ -// [TestApp] -// ============================================================================ - -static const char* archAsString(uint32_t arch) { - switch (arch) { - case Environment::kArchX86: return "X86"; - case Environment::kArchX64: return "X64"; - case Environment::kArchARM: return "A32"; - case Environment::kArchThumb: return "T32"; - case Environment::kArchAArch64: return "A64"; - default: return "Unknown"; - } -} - int TestApp::handleArgs(int argc, const char* const* argv) { CmdLine cmd(argc, argv); @@ -86,7 +54,7 @@ void TestApp::showInfo() { unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF), - archAsString(Environment::kArchHost)); + asmjitArchAsString(Arch::kHost)); printf(" [%s] Verbose (use --verbose to turn verbose output ON)\n", _verbose ? "x" : " "); printf(" [%s] DumpAsm (use --dump-asm to turn assembler dumps ON)\n", _dumpAsm ? "x" : " "); printf(" [%s] DumpHex (use --dump-hex to dump binary in hexadecimal)\n", _dumpHex ? "x" : " "); @@ -98,133 +66,156 @@ int TestApp::run() { return 0; #else #ifndef ASMJIT_NO_LOGGING - uint32_t kFormatFlags = FormatOptions::kFlagMachineCode | - FormatOptions::kFlagExplainImms | - FormatOptions::kFlagRegCasts | - FormatOptions::kFlagAnnotations | - FormatOptions::kFlagDebugPasses | - FormatOptions::kFlagDebugRA ; + FormatOptions formatOptions; + formatOptions.addFlags( + FormatFlags::kMachineCode | + FormatFlags::kExplainImms | + FormatFlags::kRegCasts ); FileLogger fileLogger(stdout); - fileLogger.addFlags(kFormatFlags); + fileLogger.setOptions(formatOptions); StringLogger stringLogger; - stringLogger.addFlags(kFormatFlags); + stringLogger.setOptions(formatOptions); #endif + JitRuntime runtime; + + PerformanceTimer compileTimer; + PerformanceTimer finalizeTimer; double compileTime = 0; double finalizeTime = 0; for (std::unique_ptr<TestCase>& test : _tests) { - JitRuntime runtime; - CodeHolder code; - SimpleErrorHandler errorHandler; - - PerformanceTimer perfTimer; + for (uint32_t pass = 0; pass < 2; pass++) { + CodeHolder code; + SimpleErrorHandler errorHandler; - code.init(runtime.environment()); - code.setErrorHandler(&errorHandler); + code.init(runtime.environment()); + code.setErrorHandler(&errorHandler); + if (pass != 0) { #ifndef ASMJIT_NO_LOGGING - if (_verbose) { - code.setLogger(&fileLogger); - } - else { - stringLogger.clear(); - code.setLogger(&stringLogger); - } + if (_verbose) { + code.setLogger(&fileLogger); + } + else { + stringLogger.clear(); + code.setLogger(&stringLogger); + } #endif - printf("[Test] %s", test->name()); + printf("[Test] %s", test->name()); #ifndef ASMJIT_NO_LOGGING - if (_verbose) printf("\n"); + if (_verbose) + printf("\n"); #endif + } + #if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 - x86::Compiler cc(&code); + x86::Compiler cc(&code); #endif #if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM == 64 - arm::Compiler cc(&code); + arm::Compiler cc(&code); #endif - perfTimer.start(); - test->compile(cc); - perfTimer.stop(); - compileTime += perfTimer.duration(); +#ifndef ASMJIT_NO_LOGGING + cc.addDiagnosticOptions(DiagnosticOptions::kRAAnnotate | DiagnosticOptions::kRADebugAll); +#endif - void* func = nullptr; - Error err = errorHandler._err; + compileTimer.start(); + test->compile(cc); + compileTimer.stop(); - if (!err) { - perfTimer.start(); - err = cc.finalize(); - perfTimer.stop(); - finalizeTime += perfTimer.duration(); - } + void* func = nullptr; + Error err = errorHandler._err; + + if (!err) { + finalizeTimer.start(); + err = cc.finalize(); + finalizeTimer.stop(); + } + + // The first pass is only for timing serialization and compilation, because otherwise it would be biased by + // logging, which takes much more time than finalize() does. We want to benchmark Compiler the way it would + // be used in production. + if (pass == 0) { + compileTime += compileTimer.duration(); + finalizeTime += finalizeTimer.duration(); + continue; + } #ifndef ASMJIT_NO_LOGGING - if (_dumpAsm) { - if (!_verbose) printf("\n"); + if (_dumpAsm) { + if (!_verbose) + printf("\n"); - String sb; - Formatter::formatNodeList(sb, kFormatFlags, &cc); - printf("%s", sb.data()); - } + String sb; + Formatter::formatNodeList(sb, formatOptions, &cc); + printf("%s", sb.data()); + } #endif - if (err == kErrorOk) - err = runtime.add(&func, &code); + if (err == kErrorOk) + err = runtime.add(&func, &code); - if (err == kErrorOk && _dumpHex) { - String sb; - sb.appendHex((void*)func, code.codeSize()); - printf("\n (HEX: %s)\n", sb.data()); - } + if (err == kErrorOk && _dumpHex) { + String sb; + sb.appendHex((void*)func, code.codeSize()); + printf("\n (HEX: %s)\n", sb.data()); + } - if (_verbose) - fflush(stdout); + if (_verbose) + fflush(stdout); - if (err == kErrorOk) { - _outputSize += code.codeSize(); + if (err == kErrorOk) { + _outputSize += code.codeSize(); - StringTmp<128> result; - StringTmp<128> expect; + StringTmp<128> result; + StringTmp<128> expect; - if (test->run(func, result, expect)) { - if (!_verbose) printf(" [OK]\n"); - } - else { - if (!_verbose) printf(" [FAILED]\n"); + if (test->run(func, result, expect)) { + if (!_verbose) + printf(" [OK]\n"); + } + else { + if (!_verbose) + printf(" [FAILED]\n"); #ifndef ASMJIT_NO_LOGGING - if (!_verbose) printf("%s", stringLogger.data()); + if (!_verbose) + printf("%s", stringLogger.data()); #endif - printf("[Status]\n"); - printf(" Returned: %s\n", result.data()); - printf(" Expected: %s\n", expect.data()); + printf("[Status]\n"); + printf(" Returned: %s\n", result.data()); + printf(" Expected: %s\n", expect.data()); - _nFailed++; - } + _nFailed++; + } - if (_dumpAsm) - printf("\n"); + if (_dumpAsm) + printf("\n"); - runtime.release(func); - } - else { - if (!_verbose) printf(" [FAILED]\n"); + runtime.release(func); + } + else { + if (!_verbose) + printf(" [FAILED]\n"); #ifndef ASMJIT_NO_LOGGING - if (!_verbose) printf("%s", stringLogger.data()); + if (!_verbose) + printf("%s", stringLogger.data()); #endif - printf("[Status]\n"); - printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); + printf("[Status]\n"); + printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); - _nFailed++; + _nFailed++; + } } } @@ -244,10 +235,6 @@ int TestApp::run() { #endif } -// ============================================================================ -// [Main] -// ============================================================================ - int main(int argc, char* argv[]) { TestApp app; diff --git a/test/asmjit_test_compiler.h b/test/asmjit_test_compiler.h index 5933e4a..e694b37 100644 --- a/test/asmjit_test_compiler.h +++ b/test/asmjit_test_compiler.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_TEST_COMPILER_H_INCLUDED #define ASMJIT_TEST_COMPILER_H_INCLUDED @@ -29,10 +11,6 @@ #include <memory> #include <vector> -// ============================================================================ -// [SimpleErrorHandler] -// ============================================================================ - class SimpleErrorHandler : public asmjit::ErrorHandler { public: SimpleErrorHandler() @@ -48,10 +26,6 @@ public: asmjit::String _message; }; -// ============================================================================ -// [TestCase] -// ============================================================================ - //! A test case interface for testing AsmJit's Compiler. class TestCase { public: @@ -70,10 +44,6 @@ public: asmjit::String _name; }; -// ============================================================================ -// [TestApp] -// ============================================================================ - class TestApp { public: std::vector<std::unique_ptr<TestCase>> _tests; diff --git a/test/asmjit_test_compiler_x86.cpp b/test/asmjit_test_compiler_x86.cpp index 0bd2130..7dbe955 100644 --- a/test/asmjit_test_compiler_x86.cpp +++ b/test/asmjit_test_compiler_x86.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> #if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 @@ -43,9 +25,8 @@ using namespace asmjit; -// ============================================================================ -// [X86TestCase] -// ============================================================================ +// x86::Compiler - X86TestCase +// =========================== class X86TestCase : public TestCase { public: @@ -59,9 +40,8 @@ public: virtual void compile(x86::Compiler& cc) = 0; }; -// ============================================================================ -// [X86Test_AlignBase] -// ============================================================================ +// x86::Compiler - X86Test_AlignBase +// ================================= class X86Test_AlignBase : public X86TestCase { public: @@ -85,14 +65,14 @@ public: uint32_t i; uint32_t argCount = _argCount; - FuncSignatureBuilder signature(CallConv::kIdHost); + FuncSignatureBuilder signature(CallConvId::kHost); signature.setRetT<int>(); for (i = 0; i < argCount; i++) signature.addArgT<int>(); - cc.addFunc(signature); + FuncNode* funcNode = cc.addFunc(signature); if (_preserveFP) - cc.func()->frame().setPreservedFP(); + funcNode->frame().setPreservedFP(); x86::Gp gpVar = cc.newIntPtr("gpVar"); x86::Gp gpSum; @@ -102,7 +82,7 @@ public: if (argCount) { for (i = 0; i < argCount; i++) { x86::Gp gpArg = cc.newInt32("gpArg%u", i); - cc.setArg(i, gpArg); + funcNode->setArg(i, gpArg); if (i == 0) gpSum = gpArg; @@ -229,9 +209,8 @@ public: bool _preserveFP; }; -// ============================================================================ -// [X86Test_NoCode] -// ============================================================================ +// x86::Compiler - X86Test_NoCode +// ============================== class X86Test_NoCode : public X86TestCase { public: @@ -242,7 +221,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); cc.endFunc(); } @@ -257,9 +236,8 @@ public: } }; -// ============================================================================ -// [X86Test_AlignNone] -// ============================================================================ +// x86::Compiler - X86Test_AlignNone +// ================================= class X86Test_NoAlign : public X86TestCase { public: @@ -270,9 +248,9 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); - cc.align(kAlignCode, 0); - cc.align(kAlignCode, 1); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); + cc.align(AlignMode::kCode, 0); + cc.align(AlignMode::kCode, 1); cc.endFunc(); } @@ -287,9 +265,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpMerge] -// ============================================================================ +// x86::Compiler - X86Test_JumpMerge +// ================================= class X86Test_JumpMerge : public X86TestCase { public: @@ -300,9 +277,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, int*, int>(CallConv::kIdHost)); - - Label L0 = cc.newLabel(); + Label L0 = cc.newLabel(); Label L1 = cc.newLabel(); Label L2 = cc.newLabel(); Label LEnd = cc.newLabel(); @@ -310,8 +285,9 @@ public: x86::Gp dst = cc.newIntPtr("dst"); x86::Gp val = cc.newInt32("val"); - cc.setArg(0, dst); - cc.setArg(1, val); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, val); cc.cmp(val, 0); cc.je(L2); @@ -353,9 +329,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpCross] -// ============================================================================ +// x86::Compiler - X86Test_JumpCross +// ================================= class X86Test_JumpCross : public X86TestCase { public: @@ -366,7 +341,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); Label L1 = cc.newLabel(); Label L2 = cc.newLabel(); @@ -395,9 +370,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpMany] -// ============================================================================ +// x86::Compiler - X86Test_JumpMany +// ================================ class X86Test_JumpMany : public X86TestCase { public: @@ -408,7 +382,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); for (uint32_t i = 0; i < 1000; i++) { Label L = cc.newLabel(); cc.jmp(L); @@ -436,9 +410,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpUnreachable1] -// ============================================================================ +// x86::Compiler - X86Test_JumpUnreachable1 +// ======================================== class X86Test_JumpUnreachable1 : public X86TestCase { public: @@ -449,7 +422,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); Label L_1 = cc.newLabel(); Label L_2 = cc.newLabel(); @@ -480,7 +453,7 @@ public: cc.bind(L_7); cc.add(v0, v1); - cc.align(kAlignCode, 16); + cc.align(AlignMode::kCode, 16); cc.bind(L_1); cc.ret(); cc.endFunc(); @@ -499,9 +472,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpUnreachable2] -// ============================================================================ +// x86::Compiler - X86Test_JumpUnreachable2 +// ======================================== class X86Test_JumpUnreachable2 : public X86TestCase { public: @@ -512,7 +484,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); Label L_1 = cc.newLabel(); Label L_2 = cc.newLabel(); @@ -546,9 +518,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpTable1] -// ============================================================================ +// x86::Compiler - X86Test_JumpTable1 +// ================================== class X86Test_JumpTable1 : public X86TestCase { public: @@ -573,25 +544,23 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConv::kIdHost)); - x86::Xmm a = cc.newXmmSs("a"); x86::Xmm b = cc.newXmmSs("b"); x86::Gp op = cc.newUInt32("op"); x86::Gp target = cc.newIntPtr("target"); x86::Gp offset = cc.newIntPtr("offset"); - Label L_End = cc.newLabel(); - Label L_Table = cc.newLabel(); Label L_Add = cc.newLabel(); Label L_Sub = cc.newLabel(); Label L_Mul = cc.newLabel(); Label L_Div = cc.newLabel(); + Label L_End = cc.newLabel(); - cc.setArg(0, a); - cc.setArg(1, b); - cc.setArg(2, op); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConvId::kHost)); + funcNode->setArg(0, a); + funcNode->setArg(1, b); + funcNode->setArg(2, op); cc.lea(offset, x86::ptr(L_Table)); if (cc.is64Bit()) @@ -665,9 +634,8 @@ public: } }; -// ============================================================================ -// [X86Test_JumpTable2] -// ============================================================================ +// x86::Compiler - X86Test_JumpTable2 +// ================================== class X86Test_JumpTable2 : public X86TestCase { public: @@ -679,8 +647,6 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int>(CallConv::kIdHost)); - x86::Gp result = cc.newUInt32("result"); x86::Gp value = cc.newUInt32("value"); x86::Gp target = cc.newIntPtr("target"); @@ -692,7 +658,8 @@ public: Label L_Case1 = cc.newLabel(); Label L_End = cc.newLabel(); - cc.setArg(0, value); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost)); + funcNode->setArg(0, value); cc.bind(L_Begin); cc.lea(offset, x86::ptr(L_Table)); @@ -748,9 +715,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocBase] -// ============================================================================ +// x86::Compiler - X86Test_AllocBase +// ================================= class X86Test_AllocBase : public X86TestCase { public: @@ -761,7 +727,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); x86::Gp v0 = cc.newInt32("v0"); x86::Gp v1 = cc.newInt32("v1"); @@ -799,9 +765,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocMany1] -// ============================================================================ +// x86::Compiler - X86Test_AllocMany1 +// ================================== class X86Test_AllocMany1 : public X86TestCase { public: @@ -814,13 +779,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, int*, int*>(CallConv::kIdHost)); - x86::Gp a0 = cc.newIntPtr("a0"); x86::Gp a1 = cc.newIntPtr("a1"); - cc.setArg(0, a0); - cc.setArg(1, a1); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int*>(CallConvId::kHost)); + funcNode->setArg(0, a0); + funcNode->setArg(1, a1); // Create some variables. x86::Gp t = cc.newInt32("t"); @@ -871,9 +835,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocMany2] -// ============================================================================ +// x86::Compiler - X86Test_AllocMany2 +// ================================== class X86Test_AllocMany2 : public X86TestCase { public: @@ -884,27 +847,25 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, uint32_t*>(CallConv::kIdHost)); - x86::Gp a = cc.newIntPtr("a"); x86::Gp v[32]; - uint32_t i; - cc.setArg(0, a); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, uint32_t*>(CallConvId::kHost)); + funcNode->setArg(0, a); - for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.newInt32("v%d", i); - for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.xor_(v[i], v[i]); + for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.newInt32("v%d", i); + for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.xor_(v[i], v[i]); x86::Gp x = cc.newInt32("x"); Label L = cc.newLabel(); cc.mov(x, 32); cc.bind(L); - for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.add(v[i], i); + for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.add(v[i], i); cc.dec(x); cc.jnz(L); - for (i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.mov(x86::dword_ptr(a, int(i * 4)), v[i]); + for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.mov(x86::dword_ptr(a, int(i * 4)), v[i]); cc.endFunc(); } @@ -935,9 +896,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocImul1] -// ============================================================================ +// x86::Compiler - X86Test_AllocImul1 +// ================================== class X86Test_AllocImul1 : public X86TestCase { public: @@ -948,8 +908,6 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, int*, int*, int, int>(CallConv::kIdHost)); - x86::Gp dstHi = cc.newIntPtr("dstHi"); x86::Gp dstLo = cc.newIntPtr("dstLo"); @@ -957,13 +915,13 @@ public: x86::Gp vLo = cc.newInt32("vLo"); x86::Gp src = cc.newInt32("src"); - cc.setArg(0, dstHi); - cc.setArg(1, dstLo); - cc.setArg(2, vLo); - cc.setArg(3, src); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int*, int, int>(CallConvId::kHost)); + funcNode->setArg(0, dstHi); + funcNode->setArg(1, dstLo); + funcNode->setArg(2, vLo); + funcNode->setArg(3, src); cc.imul(vHi, vLo, src); - cc.mov(x86::dword_ptr(dstHi), vHi); cc.mov(x86::dword_ptr(dstLo), vLo); cc.endFunc(); @@ -991,9 +949,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocImul2] -// ============================================================================ +// x86::Compiler - X86Test_AllocImul2 +// ================================== class X86Test_AllocImul2 : public X86TestCase { public: @@ -1004,13 +961,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, int*, const int*>(CallConv::kIdHost)); - x86::Gp dst = cc.newIntPtr("dst"); x86::Gp src = cc.newIntPtr("src"); - cc.setArg(0, dst); - cc.setArg(1, src); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, const int*>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, src); for (unsigned int i = 0; i < 4; i++) { x86::Gp x = cc.newInt32("x"); @@ -1045,9 +1001,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocIdiv1] -// ============================================================================ +// x86::Compiler - X86Test_AllocIdiv1 +// ================================== class X86Test_AllocIdiv1 : public X86TestCase { public: @@ -1058,14 +1013,13 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); - x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); x86::Gp dummy = cc.newInt32("dummy"); - cc.setArg(0, a); - cc.setArg(1, b); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, a); + funcNode->setArg(1, b); cc.xor_(dummy, dummy); cc.idiv(dummy, a, b); @@ -1091,9 +1045,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocSetz] -// ============================================================================ +// x86::Compiler - X86Test_AllocSetz +// ================================= class X86Test_AllocSetz : public X86TestCase { public: @@ -1104,15 +1057,14 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, int, int, char*>(CallConv::kIdHost)); - x86::Gp src0 = cc.newInt32("src0"); x86::Gp src1 = cc.newInt32("src1"); x86::Gp dst0 = cc.newIntPtr("dst0"); - cc.setArg(0, src0); - cc.setArg(1, src1); - cc.setArg(2, dst0); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int, int, char*>(CallConvId::kHost)); + funcNode->setArg(0, src0); + funcNode->setArg(1, src1); + funcNode->setArg(2, dst0); cc.cmp(src0, src1); cc.setz(x86::byte_ptr(dst0)); @@ -1142,9 +1094,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocShlRor] -// ============================================================================ +// x86::Compiler - X86Test_AllocShlRor +// =================================== class X86Test_AllocShlRor : public X86TestCase { public: @@ -1155,21 +1106,19 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, int*, int, int, int>(CallConv::kIdHost)); - x86::Gp dst = cc.newIntPtr("dst"); x86::Gp var = cc.newInt32("var"); x86::Gp vShlParam = cc.newInt32("vShlParam"); x86::Gp vRorParam = cc.newInt32("vRorParam"); - cc.setArg(0, dst); - cc.setArg(1, var); - cc.setArg(2, vShlParam); - cc.setArg(3, vRorParam); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, int*, int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, var); + funcNode->setArg(2, vShlParam); + funcNode->setArg(3, vRorParam); cc.shl(var, vShlParam); cc.ror(var, vRorParam); - cc.mov(x86::dword_ptr(dst), var); cc.endFunc(); } @@ -1192,41 +1141,37 @@ public: } }; -// ============================================================================ -// [X86Test_AllocGpbLo] -// ============================================================================ +// x86::Compiler - X86Test_AllocGpbLo +// ================================== class X86Test_AllocGpbLo1 : public X86TestCase { public: X86Test_AllocGpbLo1() : X86TestCase("AllocGpbLo1") {} - enum { kCount = 32 }; + enum : uint32_t { kCount = 32 }; static void add(TestApp& app) { app.add(new X86Test_AllocGpbLo1()); } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<uint32_t, uint32_t*>(CallConv::kIdHost)); - x86::Gp rPtr = cc.newUIntPtr("rPtr"); x86::Gp rSum = cc.newUInt32("rSum"); - - cc.setArg(0, rPtr); - x86::Gp x[kCount]; - uint32_t i; - for (i = 0; i < kCount; i++) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t*>(CallConvId::kHost)); + funcNode->setArg(0, rPtr); + + for (uint32_t i = 0; i < kCount; i++) { x[i] = cc.newUInt32("x%u", i); } // Init pseudo-regs with values from our array. - for (i = 0; i < kCount; i++) { + for (uint32_t i = 0; i < kCount; i++) { cc.mov(x[i], x86::dword_ptr(rPtr, int(i * 4))); } - for (i = 2; i < kCount; i++) { + for (uint32_t i = 2; i < kCount; i++) { // Add and truncate to 8 bit; no purpose, just mess with jit. cc.add (x[i ], x[i-1]); cc.movzx(x[i ], x[i ].r8()); @@ -1236,7 +1181,7 @@ public: // Sum up all computed values. cc.mov(rSum, 0); - for (i = 0; i < kCount; i++) { + for (uint32_t i = 0; i < kCount; i++) { cc.add(rSum, x[i]); } @@ -1282,9 +1227,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocGpbLo2] -// ============================================================================ +// x86::Compiler - X86Test_AllocGpbLo2 +// =================================== class X86Test_AllocGpbLo2 : public X86TestCase { public: @@ -1295,10 +1239,11 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConv::kIdHost)); - x86::Gp v = cc.newUInt32("v"); - cc.setArg(0, v); + + FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConvId::kHost)); + funcNode->setArg(0, v); + cc.mov(v.r8(), 0xFF); cc.ret(v); cc.endFunc(); @@ -1318,9 +1263,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocRepMovsb] -// ============================================================================ +// x86::Compiler - X86Test_AllocRepMovsb +// ===================================== class X86Test_AllocRepMovsb : public X86TestCase { public: @@ -1331,15 +1275,14 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, void*, void*, size_t>(CallConv::kIdHost)); - x86::Gp dst = cc.newIntPtr("dst"); x86::Gp src = cc.newIntPtr("src"); x86::Gp cnt = cc.newIntPtr("cnt"); - cc.setArg(0, dst); - cc.setArg(1, src); - cc.setArg(2, cnt); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, void*, size_t>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, src); + funcNode->setArg(2, cnt); cc.rep(cnt).movs(x86::byte_ptr(dst), x86::byte_ptr(src)); cc.endFunc(); @@ -1360,9 +1303,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocIfElse1] -// ============================================================================ +// x86::Compiler - X86Test_AllocIfElse1 +// ==================================== class X86Test_AllocIfElse1 : public X86TestCase { public: @@ -1373,16 +1315,15 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); - x86::Gp v1 = cc.newInt32("v1"); x86::Gp v2 = cc.newInt32("v2"); Label L_1 = cc.newLabel(); Label L_2 = cc.newLabel(); - cc.setArg(0, v1); - cc.setArg(1, v2); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, v1); + funcNode->setArg(1, v2); cc.cmp(v1, v2); cc.jg(L_1); @@ -1412,9 +1353,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocIfElse2] -// ============================================================================ +// x86::Compiler - X86Test_AllocIfElse2 +// ==================================== class X86Test_AllocIfElse2 : public X86TestCase { public: @@ -1425,8 +1365,6 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); - x86::Gp v1 = cc.newInt32("v1"); x86::Gp v2 = cc.newInt32("v2"); @@ -1435,8 +1373,9 @@ public: Label L_3 = cc.newLabel(); Label L_4 = cc.newLabel(); - cc.setArg(0, v1); - cc.setArg(1, v2); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, v1); + funcNode->setArg(1, v2); cc.jmp(L_1); cc.bind(L_2); @@ -1473,9 +1412,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocIfElse3] -// ============================================================================ +// x86::Compiler - X86Test_AllocIfElse3 +// ==================================== class X86Test_AllocIfElse3 : public X86TestCase { public: @@ -1486,8 +1424,6 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); - x86::Gp v1 = cc.newInt32("v1"); x86::Gp v2 = cc.newInt32("v2"); x86::Gp counter = cc.newInt32("counter"); @@ -1496,8 +1432,9 @@ public: Label L_Loop = cc.newLabel(); Label L_Exit = cc.newLabel(); - cc.setArg(0, v1); - cc.setArg(1, v2); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, v1); + funcNode->setArg(1, v2); cc.cmp(v1, v2); cc.jg(L_1); @@ -1534,9 +1471,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocIfElse4] -// ============================================================================ +// x86::Compiler - X86Test_AllocIfElse4 +// ==================================== class X86Test_AllocIfElse4 : public X86TestCase { public: @@ -1547,8 +1483,6 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); - x86::Gp v1 = cc.newInt32("v1"); x86::Gp v2 = cc.newInt32("v2"); x86::Gp counter = cc.newInt32("counter"); @@ -1558,11 +1492,11 @@ public: Label L_Loop2 = cc.newLabel(); Label L_Exit = cc.newLabel(); - cc.mov(counter, 0); - - cc.setArg(0, v1); - cc.setArg(1, v2); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, v1); + funcNode->setArg(1, v2); + cc.mov(counter, 0); cc.cmp(v1, v2); cc.jg(L_1); @@ -1600,9 +1534,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocInt8] -// ============================================================================ +// x86::Compiler - X86Test_AllocInt8 +// ================================= class X86Test_AllocInt8 : public X86TestCase { public: @@ -1616,8 +1549,8 @@ public: x86::Gp x = cc.newInt8("x"); x86::Gp y = cc.newInt32("y"); - cc.addFunc(FuncSignatureT<int, char>(CallConv::kIdHost)); - cc.setArg(0, x); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, char>(CallConvId::kHost)); + funcNode->setArg(0, x); cc.movsx(y, x); @@ -1639,9 +1572,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocUnhandledArg] -// ============================================================================ +// x86::Compiler - X86Test_AllocUnhandledArg +// ========================================= class X86Test_AllocUnhandledArg : public X86TestCase { public: @@ -1652,12 +1584,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); - x86::Gp x = cc.newInt32("x"); - cc.setArg(2, x); - cc.ret(x); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost)); + funcNode->setArg(2, x); + + cc.ret(x); cc.endFunc(); } @@ -1675,9 +1607,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocArgsIntPtr] -// ============================================================================ +// x86::Compiler - X86Test_AllocArgsIntPtr +// ======================================= class X86Test_AllocArgsIntPtr : public X86TestCase { public: @@ -1688,23 +1619,21 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, void*, void*, void*, void*, void*, void*, void*, void*>(CallConv::kIdHost)); - - uint32_t i; + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, void*, void*, void*, void*, void*, void*, void*>(CallConvId::kHost)); x86::Gp var[8]; - for (i = 0; i < 8; i++) { + for (uint32_t i = 0; i < 8; i++) { var[i] = cc.newIntPtr("var%u", i); - cc.setArg(i, var[i]); + funcNode->setArg(i, var[i]); } - for (i = 0; i < 8; i++) { + for (uint32_t i = 0; i < 8; i++) { cc.add(var[i], int(i + 1)); } // Move some data into buffer provided by arguments so we can verify if it // really works without looking into assembler output. - for (i = 0; i < 8; i++) { + for (uint32_t i = 0; i < 8; i++) { cc.add(x86::byte_ptr(var[i]), int(i + 1)); } @@ -1734,9 +1663,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocArgsFloat] -// ============================================================================ +// x86::Compiler - X86Test_AllocArgsFloat +// ====================================== class X86Test_AllocArgsFloat : public X86TestCase { public: @@ -1747,19 +1675,17 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, float, float, float, float, float, float, float, void*>(CallConv::kIdHost)); - - uint32_t i; + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, float, float, float, float, float, float, float, void*>(CallConvId::kHost)); x86::Gp p = cc.newIntPtr("p"); x86::Xmm xv[7]; - for (i = 0; i < 7; i++) { + for (uint32_t i = 0; i < 7; i++) { xv[i] = cc.newXmmSs("xv%u", i); - cc.setArg(i, xv[i]); + funcNode->setArg(i, xv[i]); } - cc.setArg(7, p); + funcNode->setArg(7, p); cc.addss(xv[0], xv[1]); cc.addss(xv[0], xv[2]); @@ -1788,9 +1714,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocArgsDouble] -// ============================================================================ +// x86::Compiler - X86Test_AllocArgsDouble +// ======================================= class X86Test_AllocArgsDouble : public X86TestCase { public: @@ -1801,19 +1726,17 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, double, double, double, double, double, double, double, void*>(CallConv::kIdHost)); - - uint32_t i; + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, double, double, double, double, double, double, double, void*>(CallConvId::kHost)); x86::Gp p = cc.newIntPtr("p"); x86::Xmm xv[7]; - for (i = 0; i < 7; i++) { + for (uint32_t i = 0; i < 7; i++) { xv[i] = cc.newXmmSd("xv%u", i); - cc.setArg(i, xv[i]); + funcNode->setArg(i, xv[i]); } - cc.setArg(7, p); + funcNode->setArg(7, p); cc.addsd(xv[0], xv[1]); cc.addsd(xv[0], xv[2]); @@ -1842,9 +1765,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocArgsVec] -// ============================================================================ +// x86::Compiler - X86Test_AllocArgsVec +// ==================================== class X86Test_AllocArgsVec : public X86TestCase { public: @@ -1854,17 +1776,18 @@ public: // Not supported on Windows. #ifndef _WIN32 app.add(new X86Test_AllocArgsVec()); +#else + DebugUtils::unused(app); #endif } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm>(CallConv::kIdHost)); - x86::Xmm a = cc.newXmm("aXmm"); x86::Xmm b = cc.newXmm("bXmm"); - cc.setArg(0, a); - cc.setArg(1, b); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm>(CallConvId::kHost)); + funcNode->setArg(0, a); + funcNode->setArg(1, b); cc.paddb(a, b); cc.ret(a); @@ -1895,9 +1818,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocRetFloat1] -// ============================================================================ +// x86::Compiler - X86Test_AllocRetFloat1 +// ====================================== class X86Test_AllocRetFloat1 : public X86TestCase { public: @@ -1908,12 +1830,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<float, float>(CallConv::kIdHost)); - x86::Xmm x = cc.newXmmSs("x"); - cc.setArg(0, x); - cc.ret(x); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float>(CallConvId::kHost)); + funcNode->setArg(0, x); + + cc.ret(x); cc.endFunc(); } @@ -1931,9 +1853,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocRetFloat2] -// ============================================================================ +// x86::Compiler - X86Test_AllocRetFloat2 +// ====================================== class X86Test_AllocRetFloat2 : public X86TestCase { public: @@ -1944,13 +1865,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<float, float, float>(CallConv::kIdHost)); - x86::Xmm x = cc.newXmmSs("x"); x86::Xmm y = cc.newXmmSs("y"); - cc.setArg(0, x); - cc.setArg(1, y); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float>(CallConvId::kHost)); + funcNode->setArg(0, x); + funcNode->setArg(1, y); cc.addss(x, y); cc.ret(x); @@ -1972,9 +1892,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocRetDouble1] -// ============================================================================ +// x86::Compiler - X86Test_AllocRetDouble1 +// ======================================= class X86Test_AllocRetDouble1 : public X86TestCase { public: @@ -1985,12 +1904,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<double, double>(CallConv::kIdHost)); - x86::Xmm x = cc.newXmmSd("x"); - cc.setArg(0, x); - cc.ret(x); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double>(CallConvId::kHost)); + funcNode->setArg(0, x); + + cc.ret(x); cc.endFunc(); } @@ -2007,9 +1926,9 @@ public: return resultRet == expectRet; } }; -// ============================================================================ -// [X86Test_AllocRetDouble2] -// ============================================================================ + +// x86::Compiler - X86Test_AllocRetDouble2 +// ======================================= class X86Test_AllocRetDouble2 : public X86TestCase { public: @@ -2020,13 +1939,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<double, double, double>(CallConv::kIdHost)); - x86::Xmm x = cc.newXmmSd("x"); x86::Xmm y = cc.newXmmSd("y"); - cc.setArg(0, x); - cc.setArg(1, y); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>(CallConvId::kHost)); + funcNode->setArg(0, x); + funcNode->setArg(1, y); cc.addsd(x, y); cc.ret(x); @@ -2048,9 +1966,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocStack] -// ============================================================================ +// x86::Compiler - X86Test_AllocStack +// ================================== class X86Test_AllocStack : public X86TestCase { public: @@ -2063,7 +1980,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); x86::Mem stack = cc.newStack(kSize, 1); stack.setSize(1); @@ -2116,9 +2033,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocMemcpy] -// ============================================================================ +// x86::Compiler - X86Test_AllocMemcpy +// =================================== class X86Test_AllocMemcpy : public X86TestCase { public: @@ -2138,10 +2054,10 @@ public: Label L_Loop = cc.newLabel(); // Create base labels we use Label L_Exit = cc.newLabel(); // in our function. - cc.addFunc(FuncSignatureT<void, uint32_t*, const uint32_t*, size_t>(CallConv::kIdHost)); - cc.setArg(0, dst); - cc.setArg(1, src); - cc.setArg(2, cnt); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, uint32_t*, const uint32_t*, size_t>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, src); + funcNode->setArg(2, cnt); cc.test(cnt, cnt); // Exit if the size is zero. cc.jz(L_Exit); @@ -2198,9 +2114,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocExtraBlock] -// ============================================================================ +// x86::Compiler - X86Test_AllocExtraBlock +// ======================================= class X86Test_AllocExtraBlock : public X86TestCase { public: @@ -2216,10 +2131,10 @@ public: x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); - cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); - cc.setArg(0, cond); - cc.setArg(1, a); - cc.setArg(2, b); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, cond); + funcNode->setArg(1, a); + funcNode->setArg(2, b); Label L_Ret = cc.newLabel(); Label L_Extra = cc.newLabel(); @@ -2234,7 +2149,7 @@ public: cc.ret(ret); // Emit code sequence at the end of the function. - BaseNode* prevCursor = cc.setCursor(cc.func()->endNode()->prev()); + BaseNode* prevCursor = cc.setCursor(funcNode->endNode()->prev()); cc.bind(L_Extra); cc.mov(ret, a); cc.sub(ret, b); @@ -2261,9 +2176,8 @@ public: } }; -// ============================================================================ -// [X86Test_AllocAlphaBlend] -// ============================================================================ +// x86::Compiler - X86Test_AllocAlphaBlend +// ======================================= class X86Test_AllocAlphaBlend : public X86TestCase { public: @@ -2340,9 +2254,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallBase1] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallBase1 +// ===================================== class X86Test_FuncCallBase1 : public X86TestCase { public: @@ -2357,10 +2270,10 @@ public: x86::Gp v1 = cc.newInt32("v1"); x86::Gp v2 = cc.newInt32("v2"); - cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); - cc.setArg(0, v0); - cc.setArg(1, v1); - cc.setArg(2, v2); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, v0); + funcNode->setArg(1, v1); + funcNode->setArg(2, v2); // Just do something. cc.shl(v0, 1); @@ -2369,7 +2282,7 @@ public: // Call a function. InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, v2); invokeNode->setArg(1, v1); invokeNode->setArg(2, v0); @@ -2395,9 +2308,8 @@ public: static int calledFunc(int a, int b, int c) { return (a + b) * c; } }; -// ============================================================================ -// [X86Test_FuncCallBase2] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallBase2 +// ===================================== class X86Test_FuncCallBase2 : public X86TestCase { public: @@ -2410,7 +2322,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); const int kTokenSize = 32; @@ -2430,19 +2342,19 @@ public: cc.lea(p2, s2); // Try to corrupt the stack if wrongly allocated. - cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdCDecl)); + cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConvId::kCDecl)); invokeNode->setArg(0, p1); invokeNode->setArg(1, imm(token)); invokeNode->setArg(2, imm(kTokenSize)); invokeNode->setRet(0, p1); - cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdCDecl)); + cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConvId::kCDecl)); invokeNode->setArg(0, p2); invokeNode->setArg(1, imm(token)); invokeNode->setArg(2, imm(kTokenSize)); invokeNode->setRet(0, p2); - cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignatureT<int, void*, void*, size_t>(CallConv::kIdCDecl)); + cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignatureT<int, void*, void*, size_t>(CallConvId::kCDecl)); invokeNode->setArg(0, p1); invokeNode->setArg(1, p2); invokeNode->setArg(2, imm(kTokenSize)); @@ -2477,9 +2389,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallStd] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallStd +// =================================== class X86Test_FuncCallStd : public X86TestCase { public: @@ -2494,15 +2405,15 @@ public: x86::Gp y = cc.newInt32("y"); x86::Gp z = cc.newInt32("z"); - cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); - cc.setArg(0, x); - cc.setArg(1, y); - cc.setArg(2, z); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, x); + funcNode->setArg(1, y); + funcNode->setArg(2, z); InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, int, int, int>(CallConv::kIdStdCall)); + FuncSignatureT<int, int, int, int>(CallConvId::kStdCall)); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setArg(2, z); @@ -2531,9 +2442,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallFast] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallFast +// ==================================== class X86Test_FuncCallFast : public X86TestCase { public: @@ -2546,16 +2456,16 @@ public: virtual void compile(x86::Compiler& cc) { x86::Gp var = cc.newInt32("var"); - cc.addFunc(FuncSignatureT<int, int>(CallConv::kIdHost)); - cc.setArg(0, var); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost)); + funcNode->setArg(0, var); InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConv::kIdFastCall)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConvId::kFastCall)); invokeNode->setArg(0, var); invokeNode->setRet(0, var); - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConv::kIdFastCall)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConvId::kFastCall)); invokeNode->setArg(0, var); invokeNode->setRet(0, var); @@ -2582,9 +2492,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallSIMD] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallSIMD +// ==================================== class X86Test_FuncCallSIMD : public X86TestCase { public: @@ -2604,7 +2513,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<void, void*, const void*, const void*>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, const void*, const void*>(CallConvId::kHost)); x86::Gp resultPtr = cc.newIntPtr("resultPtr"); x86::Gp aPtr = cc.newIntPtr("aPtr"); @@ -2614,16 +2523,16 @@ public: x86::Xmm aXmm = cc.newXmm("aXmm"); x86::Xmm bXmm = cc.newXmm("bXmm"); - cc.setArg(0, resultPtr); - cc.setArg(1, aPtr); - cc.setArg(2, bPtr); + funcNode->setArg(0, resultPtr); + funcNode->setArg(1, aPtr); + funcNode->setArg(2, bPtr); - uint32_t ccId = CallConv::kIdCDecl; + CallConvId ccId = CallConvId::kCDecl; Imm pFnImm = imm((void*)calledFunc_cdecl); #ifdef _MSC_VER if (_useVectorCall) { - ccId = CallConv::kIdVectorCall; + ccId = CallConvId::kVectorCall; pFnImm = imm((void*)calledFunc_vcall); } #endif @@ -2673,9 +2582,8 @@ public: #endif }; -// ============================================================================ -// [X86Test_FuncCallLight] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallLight +// ===================================== class X86Test_FuncCallLight : public X86TestCase { public: @@ -2686,11 +2594,11 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncSignatureT<void, const void*, const void*, const void*, const void*, void*> funcSig(CallConv::kIdCDecl); - FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm> fastSig(CallConv::kIdLightCall2); + FuncSignatureT<void, const void*, const void*, const void*, const void*, void*> f1Sig(CallConvId::kCDecl); + FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm> f2Sig(CallConvId::kLightCall2); - FuncNode* func = cc.newFunc(funcSig); - FuncNode* fast = cc.newFunc(fastSig); + FuncNode* f1Node = cc.newFunc(f1Sig); + FuncNode* f2Node = cc.newFunc(f2Sig); { x86::Gp aPtr = cc.newIntPtr("aPtr"); @@ -2704,13 +2612,12 @@ public: x86::Xmm cXmm = cc.newXmm("cXmm"); x86::Xmm dXmm = cc.newXmm("dXmm"); - cc.addFunc(func); - - cc.setArg(0, aPtr); - cc.setArg(1, bPtr); - cc.setArg(2, cPtr); - cc.setArg(3, dPtr); - cc.setArg(4, pOut); + cc.addFunc(f1Node); + f1Node->setArg(0, aPtr); + f1Node->setArg(1, bPtr); + f1Node->setArg(2, cPtr); + f1Node->setArg(3, dPtr); + f1Node->setArg(4, pOut); cc.movups(aXmm, x86::ptr(aPtr)); cc.movups(bXmm, x86::ptr(bPtr)); @@ -2722,12 +2629,12 @@ public: InvokeNode* invokeNode; - cc.invoke(&invokeNode, fast->label(), fastSig); + cc.invoke(&invokeNode, f2Node->label(), f2Sig); invokeNode->setArg(0, aXmm); invokeNode->setArg(1, bXmm); invokeNode->setRet(0, xXmm); - cc.invoke(&invokeNode, fast->label(), fastSig); + cc.invoke(&invokeNode, f2Node->label(), f2Sig); invokeNode->setArg(0, cXmm); invokeNode->setArg(1, dXmm); invokeNode->setRet(0, yXmm); @@ -2742,9 +2649,9 @@ public: x86::Xmm aXmm = cc.newXmm("aXmm"); x86::Xmm bXmm = cc.newXmm("bXmm"); - cc.addFunc(fast); - cc.setArg(0, aXmm); - cc.setArg(1, bXmm); + cc.addFunc(f2Node); + f2Node->setArg(0, aXmm); + f2Node->setArg(1, bXmm); cc.paddw(aXmm, bXmm); cc.ret(aXmm); cc.endFunc(); @@ -2773,9 +2680,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallManyArgs] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallManyArgs +// ======================================== class X86Test_FuncCallManyArgs : public X86TestCase { public: @@ -2790,7 +2696,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); // Prepare. x86::Gp va = cc.newInt32("va"); @@ -2819,7 +2725,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost)); + FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, va); invokeNode->setArg(1, vb); invokeNode->setArg(2, vc); @@ -2850,9 +2756,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallDuplicateArgs] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallDuplicateArgs +// ============================================= class X86Test_FuncCallDuplicateArgs : public X86TestCase { public: @@ -2867,7 +2772,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); // Prepare. x86::Gp a = cc.newInt32("a"); @@ -2877,7 +2782,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost)); + FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, a); invokeNode->setArg(1, a); invokeNode->setArg(2, a); @@ -2908,9 +2813,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallImmArgs] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallImmArgs +// ======================================= class X86Test_FuncCallImmArgs : public X86TestCase { public: @@ -2921,7 +2825,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); // Prepare. x86::Gp rv = cc.newInt32("rv"); @@ -2930,7 +2834,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)X86Test_FuncCallManyArgs::calledFunc), - FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost)); + FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, imm(0x03)); invokeNode->setArg(1, imm(0x12)); @@ -2962,9 +2866,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallPtrArgs] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallPtrArgs +// ======================================= class X86Test_FuncCallPtrArgs : public X86TestCase { public: @@ -2988,7 +2891,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); // Prepare. x86::Gp rv = cc.newInt32("rv"); @@ -2997,7 +2900,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>(CallConv::kIdHost)); + FuncSignatureT<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>(CallConvId::kHost)); invokeNode->setArg(0, imm(0x01)); invokeNode->setArg(1, imm(0x02)); @@ -3029,9 +2932,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallRefArgs] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallRefArgs +// ======================================= class X86Test_FuncCallRefArgs : public X86TestCase { public: @@ -3050,7 +2952,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int&, int&, int&, int&>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int&, int&, int&, int&>(CallConvId::kHost)); // Prepare. x86::Gp arg1 = cc.newInt32(); @@ -3059,16 +2961,16 @@ public: x86::Gp arg4 = cc.newInt32(); x86::Gp rv = cc.newInt32("rv"); - cc.setArg(0, arg1); - cc.setArg(1, arg2); - cc.setArg(2, arg3); - cc.setArg(3, arg4); + funcNode->setArg(0, arg1); + funcNode->setArg(1, arg2); + funcNode->setArg(2, arg3); + funcNode->setArg(3, arg4); // Call function. InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, int&, int&, int&, int&>(CallConv::kIdHost)); + FuncSignatureT<int, int&, int&, int&, int&>(CallConvId::kHost)); invokeNode->setArg(0, arg1); invokeNode->setArg(1, arg2); @@ -3096,9 +2998,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallFloatAsXmmRet] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallFloatAsXmmRet +// ============================================= class X86Test_FuncCallFloatAsXmmRet : public X86TestCase { public: @@ -3113,18 +3014,18 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<float, float, float>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float>(CallConvId::kHost)); x86::Xmm a = cc.newXmmSs("a"); x86::Xmm b = cc.newXmmSs("b"); x86::Xmm ret = cc.newXmmSs("ret"); - cc.setArg(0, a); - cc.setArg(1, b); + funcNode->setArg(0, a); + funcNode->setArg(1, b); // Call function. InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<float, float, float>(CallConv::kIdHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<float, float, float>(CallConvId::kHost)); invokeNode->setArg(0, a); invokeNode->setArg(1, b); invokeNode->setRet(0, ret); @@ -3147,9 +3048,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallDoubleAsXmmRet] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallDoubleAsXmmRet +// ============================================== class X86Test_FuncCallDoubleAsXmmRet : public X86TestCase { public: @@ -3164,17 +3064,17 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<double, double, double>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>(CallConvId::kHost)); x86::Xmm a = cc.newXmmSd("a"); x86::Xmm b = cc.newXmmSd("b"); x86::Xmm ret = cc.newXmmSd("ret"); - cc.setArg(0, a); - cc.setArg(1, b); + funcNode->setArg(0, a); + funcNode->setArg(1, b); InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<double, double, double>(CallConv::kIdHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<double, double, double>(CallConvId::kHost)); invokeNode->setArg(0, a); invokeNode->setArg(1, b); invokeNode->setRet(0, ret); @@ -3197,9 +3097,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallConditional] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallConditional +// =========================================== class X86Test_FuncCallConditional : public X86TestCase { public: @@ -3217,10 +3116,10 @@ public: InvokeNode* invokeNode; x86::Gp result; - cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); - cc.setArg(0, x); - cc.setArg(1, y); - cc.setArg(2, op); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost)); + funcNode->setArg(0, x); + funcNode->setArg(1, y); + funcNode->setArg(2, op); Label opAdd = cc.newLabel(); Label opMul = cc.newLabel(); @@ -3237,7 +3136,7 @@ public: cc.bind(opAdd); result = cc.newInt32("result_1"); - cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignatureT<int, int, int>(CallConv::kIdHost)); + cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignatureT<int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setRet(0, result); @@ -3246,7 +3145,7 @@ public: cc.bind(opMul); result = cc.newInt32("result_2"); - cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignatureT<int, int, int>(CallConv::kIdHost)); + cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignatureT<int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, x); invokeNode->setArg(1, y); invokeNode->setRet(0, result); @@ -3278,9 +3177,8 @@ public: static int calledFuncMul(int x, int y) { return x * y; } }; -// ============================================================================ -// [X86Test_FuncCallMultiple] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMultiple +// ======================================== class X86Test_FuncCallMultiple : public X86TestCase { public: @@ -3301,8 +3199,8 @@ public: x86::Gp acc0 = cc.newInt32("acc0"); x86::Gp acc1 = cc.newInt32("acc1"); - cc.addFunc(FuncSignatureT<int, int*>(CallConv::kIdHost)); - cc.setArg(0, buf); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int*>(CallConvId::kHost)); + funcNode->setArg(0, buf); cc.mov(acc0, 0); cc.mov(acc1, 0); @@ -3316,7 +3214,7 @@ public: cc.mov(ptr, buf); cc.mov(idx, int(i)); - cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdFastCall)); + cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConvId::kFastCall)); invokeNode->setArg(0, ptr); invokeNode->setArg(1, idx); invokeNode->setRet(0, ret); @@ -3326,7 +3224,7 @@ public: cc.mov(ptr, buf); cc.mov(idx, int(i)); - cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdFastCall)); + cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConvId::kFastCall)); invokeNode->setArg(0, ptr); invokeNode->setArg(1, idx); invokeNode->setRet(0, ret); @@ -3355,9 +3253,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallRecursive] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallRecursive +// ========================================= class X86Test_FuncCallRecursive : public X86TestCase { public: @@ -3371,8 +3268,8 @@ public: x86::Gp val = cc.newInt32("val"); Label skip = cc.newLabel(); - FuncNode* func = cc.addFunc(FuncSignatureT<int, int>(CallConv::kIdHost)); - cc.setArg(0, val); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost)); + funcNode->setArg(0, val); cc.cmp(val, 1); cc.jle(skip); @@ -3383,7 +3280,7 @@ public: InvokeNode* invokeNode; - cc.invoke(&invokeNode, func->label(), FuncSignatureT<int, int>(CallConv::kIdHost)); + cc.invoke(&invokeNode, funcNode->label(), FuncSignatureT<int, int>(CallConvId::kHost)); invokeNode->setArg(0, tmp); invokeNode->setRet(0, tmp); cc.mul(cc.newInt32(), val, tmp); @@ -3407,9 +3304,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallVarArg1] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallVarArg1 +// ======================================= class X86Test_FuncCallVarArg1 : public X86TestCase { public: @@ -3420,17 +3316,17 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int, int, int>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int, int>(CallConvId::kHost)); x86::Gp a0 = cc.newInt32("a0"); x86::Gp a1 = cc.newInt32("a1"); x86::Gp a2 = cc.newInt32("a2"); x86::Gp a3 = cc.newInt32("a3"); - cc.setArg(0, a0); - cc.setArg(1, a1); - cc.setArg(2, a2); - cc.setArg(3, a3); + funcNode->setArg(0, a0); + funcNode->setArg(1, a1); + funcNode->setArg(2, a2); + funcNode->setArg(3, a3); // We call `int func(size_t, ...)` // - The `vaIndex` must be 1 (first argument after size_t). @@ -3438,7 +3334,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, size_t, int, int, int, int>(CallConv::kIdHost, 1)); + FuncSignatureT<int, size_t, int, int, int, int>(CallConvId::kHost, 1)); invokeNode->setArg(0, imm(4)); invokeNode->setArg(1, a0); invokeNode->setArg(2, a1); @@ -3476,9 +3372,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallVarArg2] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallVarArg2 +// ======================================= class X86Test_FuncCallVarArg2 : public X86TestCase { public: @@ -3489,17 +3384,17 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<double, double, double, double, double>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double, double, double>(CallConvId::kHost)); x86::Xmm a0 = cc.newXmmSd("a0"); x86::Xmm a1 = cc.newXmmSd("a1"); x86::Xmm a2 = cc.newXmmSd("a2"); x86::Xmm a3 = cc.newXmmSd("a3"); - cc.setArg(0, a0); - cc.setArg(1, a1); - cc.setArg(2, a2); - cc.setArg(3, a3); + funcNode->setArg(0, a0); + funcNode->setArg(1, a1); + funcNode->setArg(2, a2); + funcNode->setArg(3, a3); // We call `double func(size_t, ...)` // - The `vaIndex` must be 1 (first argument after size_t). @@ -3507,7 +3402,7 @@ public: InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<double, size_t, double, double, double, double>(CallConv::kIdHost, 1)); + FuncSignatureT<double, size_t, double, double, double, double>(CallConvId::kHost, 1)); invokeNode->setArg(0, imm(4)); invokeNode->setArg(1, a0); invokeNode->setArg(2, a1); @@ -3545,9 +3440,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallInt64Arg] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallInt64Arg +// ======================================== class X86Test_FuncCallInt64Arg : public X86TestCase { public: @@ -3558,11 +3452,11 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<uint64_t, uint64_t>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint64_t, uint64_t>(CallConvId::kHost)); if (cc.is64Bit()) { x86::Gp reg = cc.newUInt64(); - cc.setArg(0, reg); + funcNode->setArg(0, reg); cc.add(reg, 1); cc.ret(reg); } @@ -3570,8 +3464,8 @@ public: x86::Gp hi = cc.newUInt32("hi"); x86::Gp lo = cc.newUInt32("lo"); - cc.setArg(0, 0, lo); - cc.setArg(0, 1, hi); + funcNode->setArg(0, 0, lo); + funcNode->setArg(0, 1, hi); cc.add(lo, 1); cc.adc(hi, 0); @@ -3607,9 +3501,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallMisc1] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMisc1 +// ===================================== class X86Test_FuncCallMisc1 : public X86TestCase { public: @@ -3622,19 +3515,19 @@ public: static void dummy(int, int) {} virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); x86::Gp r = cc.newInt32("r"); - cc.setArg(0, a); - cc.setArg(1, b); + funcNode->setArg(0, a); + funcNode->setArg(1, b); InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)dummy), - FuncSignatureT<void, int, int>(CallConv::kIdHost)); + FuncSignatureT<void, int, int>(CallConvId::kHost)); invokeNode->setArg(0, a); invokeNode->setArg(1, b); @@ -3658,9 +3551,8 @@ public: } }; -// ============================================================================ -// [X86Test_FuncCallMisc2] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMisc2 +// ===================================== class X86Test_FuncCallMisc2 : public X86TestCase { public: @@ -3671,19 +3563,19 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<double, const double*>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, const double*>(CallConvId::kHost)); x86::Gp p = cc.newIntPtr("p"); x86::Xmm arg = cc.newXmmSd("arg"); x86::Xmm ret = cc.newXmmSd("ret"); - cc.setArg(0, p); + funcNode->setArg(0, p); cc.movsd(arg, x86::ptr(p)); InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)op), - FuncSignatureT<double, double>(CallConv::kIdHost)); + FuncSignatureT<double, double>(CallConvId::kHost)); invokeNode->setArg(0, arg); invokeNode->setRet(0, ret); @@ -3709,9 +3601,8 @@ public: static double op(double a) { return a * a; } }; -// ============================================================================ -// [X86Test_FuncCallMisc3] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMisc3 +// ===================================== class X86Test_FuncCallMisc3 : public X86TestCase { public: @@ -3722,19 +3613,19 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<double, const double*>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, const double*>(CallConvId::kHost)); x86::Gp p = cc.newIntPtr("p"); x86::Xmm arg = cc.newXmmSd("arg"); x86::Xmm ret = cc.newXmmSd("ret"); - cc.setArg(0, p); + funcNode->setArg(0, p); cc.movsd(arg, x86::ptr(p)); InvokeNode* invokeNode; cc.invoke(&invokeNode, imm((void*)op), - FuncSignatureT<double, double>(CallConv::kIdHost)); + FuncSignatureT<double, double>(CallConvId::kHost)); invokeNode->setArg(0, arg); invokeNode->setRet(0, ret); @@ -3763,9 +3654,8 @@ public: static double op(double a) { return a * a; } }; -// ============================================================================ -// [X86Test_FuncCallMisc4] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMisc4 +// ===================================== class X86Test_FuncCallMisc4 : public X86TestCase { public: @@ -3779,13 +3669,13 @@ public: InvokeNode* invokeNode; FuncSignatureBuilder funcSignature; - funcSignature.setCallConv(CallConv::kIdHost); - funcSignature.setRet(Type::kIdF64); + funcSignature.setCallConvId(CallConvId::kHost); + funcSignature.setRet(TypeId::kFloat64); cc.addFunc(funcSignature); FuncSignatureBuilder invokeSignature; - invokeSignature.setCallConv(CallConv::kIdHost); - invokeSignature.setRet(Type::kIdF64); + invokeSignature.setCallConvId(CallConvId::kHost); + invokeSignature.setRet(TypeId::kFloat64); cc.invoke(&invokeNode, imm((void*)calledFunc), invokeSignature); x86::Xmm ret = cc.newXmmSd("ret"); @@ -3811,9 +3701,8 @@ public: static double calledFunc() { return 3.14; } }; -// ============================================================================ -// [X86Test_FuncCallMisc5] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMisc5 +// ===================================== // The register allocator should clobber the register used by the `call` itself. class X86Test_FuncCallMisc5 : public X86TestCase { @@ -3825,12 +3714,12 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); x86::Gp pFn = cc.newIntPtr("pFn"); x86::Gp vars[16]; - uint32_t i, regCount = cc.arch() == Environment::kArchX86 ? 8 : 16; + uint32_t i, regCount = cc.arch() == Arch::kX86 ? 8 : 16; ASMJIT_ASSERT(regCount <= ASMJIT_ARRAY_SIZE(vars)); cc.mov(pFn, imm((void*)calledFunc)); @@ -3844,7 +3733,7 @@ public: } InvokeNode* invokeNode; - cc.invoke(&invokeNode, pFn, FuncSignatureT<void>(CallConv::kIdHost)); + cc.invoke(&invokeNode, pFn, FuncSignatureT<void>(CallConvId::kHost)); for (i = 1; i < regCount; i++) if (vars[i].isValid()) @@ -3870,9 +3759,8 @@ public: static void calledFunc() {} }; -// ============================================================================ -// [X86Test_FuncCallMisc6] -// ============================================================================ +// x86::Compiler - X86Test_FuncCallMisc6 +// ===================================== class X86Test_FuncCallMisc6 : public X86TestCase { public: @@ -3883,7 +3771,7 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t>(CallConvId::kHost)); constexpr uint32_t kCount = 16; @@ -3892,14 +3780,14 @@ public: x86::Gp retVal = cc.newUInt32("retVal"); uint32_t i; - cc.setArg(0, argVal); + funcNode->setArg(0, argVal); cc.add(argVal, 1); for (i = 0; i < kCount; i++) v[i] = cc.newUInt32("v%u", i); InvokeNode* invokeNode; - cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<uint32_t, uint32_t>(CallConv::kIdHost)); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<uint32_t, uint32_t>(CallConvId::kHost)); invokeNode->setArg(0, argVal); invokeNode->setRet(0, retVal); @@ -3931,9 +3819,8 @@ public: static uint32_t calledFunc(uint32_t x) { return x + 1; } }; -// ============================================================================ -// [X86Test_MiscLocalConstPool] -// ============================================================================ +// x86::Compiler - X86Test_MiscLocalConstPool +// ========================================== class X86Test_MiscLocalConstPool : public X86TestCase { public: @@ -3944,13 +3831,13 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); x86::Gp v0 = cc.newInt32("v0"); x86::Gp v1 = cc.newInt32("v1"); - x86::Mem c0 = cc.newInt32Const(ConstPool::kScopeLocal, 200); - x86::Mem c1 = cc.newInt32Const(ConstPool::kScopeLocal, 33); + x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kLocal, 200); + x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kLocal, 33); cc.mov(v0, c0); cc.mov(v1, c1); @@ -3974,9 +3861,8 @@ public: } }; -// ============================================================================ -// [X86Test_MiscGlobalConstPool] -// ============================================================================ +// x86::Compiler - X86Test_MiscGlobalConstPool +// =========================================== class X86Test_MiscGlobalConstPool : public X86TestCase { public: @@ -3987,13 +3873,13 @@ public: } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); x86::Gp v0 = cc.newInt32("v0"); x86::Gp v1 = cc.newInt32("v1"); - x86::Mem c0 = cc.newInt32Const(ConstPool::kScopeGlobal, 200); - x86::Mem c1 = cc.newInt32Const(ConstPool::kScopeGlobal, 33); + x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kGlobal, 200); + x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kGlobal, 33); cc.mov(v0, c0); cc.mov(v1, c1); @@ -4017,9 +3903,8 @@ public: } }; -// ============================================================================ -// [X86Test_MiscMultiRet] -// ============================================================================ +// x86::Compiler - X86Test_MiscMultiRet +// ==================================== struct X86Test_MiscMultiRet : public X86TestCase { X86Test_MiscMultiRet() : X86TestCase("MiscMultiRet") {} @@ -4029,7 +3914,7 @@ struct X86Test_MiscMultiRet : public X86TestCase { } virtual void compile(x86::Compiler& cc) { - cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, int, int>(CallConvId::kHost)); x86::Gp op = cc.newInt32("op"); x86::Gp a = cc.newInt32("a"); @@ -4041,9 +3926,9 @@ struct X86Test_MiscMultiRet : public X86TestCase { Label L_Mul = cc.newLabel(); Label L_Div = cc.newLabel(); - cc.setArg(0, op); - cc.setArg(1, a); - cc.setArg(2, b); + funcNode->setArg(0, op); + funcNode->setArg(1, a); + funcNode->setArg(2, b); cc.cmp(op, 0); cc.jz(L_Add); @@ -4109,9 +3994,8 @@ struct X86Test_MiscMultiRet : public X86TestCase { } }; -// ============================================================================ -// [X86Test_MiscMultiFunc] -// ============================================================================ +// x86::Compiler - X86Test_MiscMultiFunc +// ===================================== class X86Test_MiscMultiFunc : public X86TestCase { public: @@ -4122,19 +4006,19 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncNode* f1 = cc.newFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); - FuncNode* f2 = cc.newFunc(FuncSignatureT<int, int, int>(CallConv::kIdHost)); + FuncNode* f1Node = cc.newFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); + FuncNode* f2Node = cc.newFunc(FuncSignatureT<int, int, int>(CallConvId::kHost)); { x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); - cc.addFunc(f1); - cc.setArg(0, a); - cc.setArg(1, b); + cc.addFunc(f1Node); + f1Node->setArg(0, a); + f1Node->setArg(1, b); InvokeNode* invokeNode; - cc.invoke(&invokeNode, f2->label(), FuncSignatureT<int, int, int>(CallConv::kIdHost)); + cc.invoke(&invokeNode, f2Node->label(), FuncSignatureT<int, int, int>(CallConvId::kHost)); invokeNode->setArg(0, a); invokeNode->setArg(1, b); invokeNode->setRet(0, a); @@ -4147,9 +4031,9 @@ public: x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newInt32("b"); - cc.addFunc(f2); - cc.setArg(0, a); - cc.setArg(1, b); + cc.addFunc(f2Node); + f2Node->setArg(0, a); + f2Node->setArg(1, b); cc.add(a, b); cc.ret(a); @@ -4172,9 +4056,8 @@ public: } }; -// ============================================================================ -// [X86Test_MiscUnfollow] -// ============================================================================ +// x86::Compiler - X86Test_MiscUnfollow +// ==================================== // Global (I didn't find a better way to test this). static jmp_buf globalJmpBuf; @@ -4188,27 +4071,21 @@ public: } virtual void compile(x86::Compiler& cc) { - // NOTE: Fastcall calling convention is the most appropriate here, as all - // arguments will be passed by registers and there won't be any stack - // misalignment when we call the `handler()`. This was failing on OSX - // when targeting 32-bit. - cc.addFunc(FuncSignatureT<int, int, void*>(CallConv::kIdFastCall)); - + // NOTE: Fastcall calling convention is the most appropriate here as all arguments are passed via registers and + // there won't be any stack misalignment in the `handler()`. This was failing on MacOS when targeting 32-bit mode. x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newIntPtr("b"); Label tramp = cc.newLabel(); - cc.setArg(0, a); - cc.setArg(1, b); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int, void*>(CallConvId::kFastCall)); + funcNode->setArg(0, a); + funcNode->setArg(1, b); cc.cmp(a, 0); cc.jz(tramp); - cc.ret(a); - cc.bind(tramp); cc.unfollow().jmp(b); - cc.endFunc(); } @@ -4234,9 +4111,8 @@ public: static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); } }; -// ============================================================================ -// [Export] -// ============================================================================ +// x86::Compiler - Tests +// ===================== void compiler_add_x86_tests(TestApp& app) { // Base tests. diff --git a/test/asmjit_test_emitters.cpp b/test/asmjit_test_emitters.cpp index 9ca80e8..63c14a6 100644 --- a/test/asmjit_test_emitters.cpp +++ b/test/asmjit_test_emitters.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> @@ -52,7 +34,7 @@ static void makeRawFunc(x86::Emitter* emitter) noexcept { // Create and initialize `FuncDetail` and `FuncFrame`. FuncDetail func; - func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost), emitter->environment()); + func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost), emitter->environment()); FuncFrame frame; frame.init(func); @@ -82,17 +64,16 @@ static void makeRawFunc(x86::Emitter* emitter) noexcept { #ifndef ASMJIT_NO_COMPILER // This function works with x86::Compiler, provided for comparison. static void makeCompiledFunc(x86::Compiler* cc) noexcept { - x86::Gp dst = cc->newIntPtr(); - x86::Gp src_a = cc->newIntPtr(); - x86::Gp src_b = cc->newIntPtr(); + x86::Gp dst = cc->newIntPtr("dst"); + x86::Gp src_a = cc->newIntPtr("src_a"); + x86::Gp src_b = cc->newIntPtr("src_b"); + x86::Xmm vec0 = cc->newXmm("vec0"); + x86::Xmm vec1 = cc->newXmm("vec1"); - x86::Xmm vec0 = cc->newXmm(); - x86::Xmm vec1 = cc->newXmm(); - - cc->addFunc(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost)); - cc->setArg(0, dst); - cc->setArg(1, src_a); - cc->setArg(2, src_b); + FuncNode* funcNode = cc->addFunc(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, src_a); + funcNode->setArg(2, src_b); cc->movdqu(vec0, x86::ptr(src_a)); cc->movdqu(vec1, x86::ptr(src_b)); @@ -102,10 +83,10 @@ static void makeCompiledFunc(x86::Compiler* cc) noexcept { } #endif -static uint32_t testFunc(JitRuntime& rt, uint32_t emitterType) noexcept { +static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { #ifndef ASMJIT_NO_LOGGING FileLogger logger(stdout); - logger.setIndentation(FormatOptions::kIndentationCode, 2); + logger.setIndentation(FormatIndentationGroup::kCode, 2); #endif CodeHolder code; @@ -117,7 +98,11 @@ static uint32_t testFunc(JitRuntime& rt, uint32_t emitterType) noexcept { Error err = kErrorOk; switch (emitterType) { - case BaseEmitter::kTypeAssembler: { + case EmitterType::kNone: { + break; + } + + case EmitterType::kAssembler: { printf("Using x86::Assembler:\n"); x86::Assembler a(&code); makeRawFunc(a.as<x86::Emitter>()); @@ -125,7 +110,7 @@ static uint32_t testFunc(JitRuntime& rt, uint32_t emitterType) noexcept { } #ifndef ASMJIT_NO_BUILDER - case BaseEmitter::kTypeBuilder: { + case EmitterType::kBuilder: { printf("Using x86::Builder:\n"); x86::Builder cb(&code); makeRawFunc(cb.as<x86::Emitter>()); @@ -140,7 +125,7 @@ static uint32_t testFunc(JitRuntime& rt, uint32_t emitterType) noexcept { #endif #ifndef ASMJIT_NO_COMPILER - case BaseEmitter::kTypeCompiler: { + case EmitterType::kCompiler: { printf("Using x86::Compiler:\n"); x86::Compiler cc(&code); makeCompiledFunc(&cc); @@ -187,14 +172,14 @@ int main() { JitRuntime rt; unsigned nFailed = 0; - nFailed += testFunc(rt, BaseEmitter::kTypeAssembler); + nFailed += testFunc(rt, EmitterType::kAssembler); #ifndef ASMJIT_NO_BUILDER - nFailed += testFunc(rt, BaseEmitter::kTypeBuilder); + nFailed += testFunc(rt, EmitterType::kBuilder); #endif #ifndef ASMJIT_NO_COMPILER - nFailed += testFunc(rt, BaseEmitter::kTypeCompiler); + nFailed += testFunc(rt, EmitterType::kCompiler); #endif if (!nFailed) diff --git a/test/asmjit_test_instinfo.cpp b/test/asmjit_test_instinfo.cpp index 2de8897..3d51edc 100644 --- a/test/asmjit_test_instinfo.cpp +++ b/test/asmjit_test_instinfo.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> @@ -35,7 +17,7 @@ static char accessLetter(bool r, bool w) noexcept { return r && w ? 'X' : r ? 'R' : w ? 'W' : '_'; } -static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount) { +static void printInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) { StringTmp<512> sb; // Read & Write Information @@ -45,7 +27,7 @@ static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* opera InstAPI::queryRWInfo(arch, inst, operands, opCount, &rw); #ifndef ASMJIT_NO_LOGGING - Formatter::formatInstruction(sb, 0, nullptr, arch, inst, operands, opCount); + Formatter::formatInstruction(sb, FormatFlags::kNone, nullptr, arch, inst, operands, opCount); #else sb.append("<Logging-Not-Available>"); #endif @@ -77,34 +59,37 @@ static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* opera sb.append("\n"); } - if (rw.readFlags() | rw.writeFlags()) { + // CPU Flags (Read/Write) + // ---------------------- + + if ((rw.readFlags() | rw.writeFlags()) != CpuRWFlags::kNone) { sb.append(" Flags: \n"); struct FlagMap { - uint32_t flag; + CpuRWFlags flag; char name[4]; }; static const FlagMap flagMap[] = { - { x86::Status::kCF, "CF" }, - { x86::Status::kOF, "OF" }, - { x86::Status::kSF, "SF" }, - { x86::Status::kZF, "ZF" }, - { x86::Status::kAF, "AF" }, - { x86::Status::kPF, "PF" }, - { x86::Status::kDF, "DF" }, - { x86::Status::kIF, "IF" }, - { x86::Status::kAC, "AC" }, - { x86::Status::kC0, "C0" }, - { x86::Status::kC1, "C1" }, - { x86::Status::kC2, "C2" }, - { x86::Status::kC3, "C3" } + { CpuRWFlags::kX86_CF, "CF" }, + { CpuRWFlags::kX86_OF, "OF" }, + { CpuRWFlags::kX86_SF, "SF" }, + { CpuRWFlags::kX86_ZF, "ZF" }, + { CpuRWFlags::kX86_AF, "AF" }, + { CpuRWFlags::kX86_PF, "PF" }, + { CpuRWFlags::kX86_DF, "DF" }, + { CpuRWFlags::kX86_IF, "IF" }, + { CpuRWFlags::kX86_AC, "AC" }, + { CpuRWFlags::kX86_C0, "C0" }, + { CpuRWFlags::kX86_C1, "C1" }, + { CpuRWFlags::kX86_C2, "C2" }, + { CpuRWFlags::kX86_C3, "C3" } }; sb.append(" "); for (uint32_t f = 0; f < 13; f++) { - char c = accessLetter((rw.readFlags() & flagMap[f].flag) != 0, - (rw.writeFlags() & flagMap[f].flag) != 0); + char c = accessLetter((rw.readFlags() & flagMap[f].flag) != CpuRWFlags::kNone, + (rw.writeFlags() & flagMap[f].flag) != CpuRWFlags::kNone); if (c != '_') sb.appendFormat("%s=%c ", flagMap[f].name, c); } @@ -115,7 +100,7 @@ static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* opera // CPU Features // ------------ - BaseFeatures features; + CpuFeatures features; InstAPI::queryFeatures(arch, inst, operands, opCount, &features); #ifndef ASMJIT_NO_LOGGING @@ -124,7 +109,7 @@ static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* opera sb.append(" "); bool first = true; - BaseFeatures::Iterator it(features.iterator()); + CpuFeatures::Iterator it(features.iterator()); while (it.hasNext()) { uint32_t featureId = uint32_t(it.next()); if (!first) @@ -140,7 +125,7 @@ static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* opera } template<typename... Args> -static void printInfoSimple(uint32_t arch, uint32_t instId, uint32_t options, Args&&... args) { +static void printInfoSimple(Arch arch,InstId instId, InstOptions options, Args&&... args) { BaseInst inst(instId); inst.addOptions(options); Operand_ opArray[] = { std::forward<Args>(args)... }; @@ -148,7 +133,7 @@ static void printInfoSimple(uint32_t arch, uint32_t instId, uint32_t options, Ar } template<typename... Args> -static void printInfoExtra(uint32_t arch, uint32_t instId, uint32_t options, const BaseReg& extraReg, Args&&... args) { +static void printInfoExtra(Arch arch, InstId instId, InstOptions options, const BaseReg& extraReg, Args&&... args) { BaseInst inst(instId); inst.addOptions(options); inst.setExtraReg(extraReg); @@ -159,27 +144,27 @@ static void printInfoExtra(uint32_t arch, uint32_t instId, uint32_t options, con static void testX86Arch() { #if !defined(ASMJIT_NO_X86) using namespace x86; - uint32_t arch = Environment::kArchX64; + Arch arch = Arch::kX64; - printInfoSimple(arch, Inst::kIdAdd, 0, eax, ebx); - printInfoSimple(arch, Inst::kIdLods, 0, eax, dword_ptr(rsi)); + printInfoSimple(arch, Inst::kIdAdd, InstOptions::kNone, eax, ebx); + printInfoSimple(arch, Inst::kIdLods, InstOptions::kNone, eax, dword_ptr(rsi)); - printInfoSimple(arch, Inst::kIdPshufd, 0, xmm0, xmm1, imm(0)); - printInfoSimple(arch, Inst::kIdPabsb, 0, mm1, mm2); - printInfoSimple(arch, Inst::kIdPabsb, 0, xmm1, xmm2); - printInfoSimple(arch, Inst::kIdPextrw, 0, eax, mm1, imm(0)); - printInfoSimple(arch, Inst::kIdPextrw, 0, eax, xmm1, imm(0)); - printInfoSimple(arch, Inst::kIdPextrw, 0, ptr(rax), xmm1, imm(0)); + printInfoSimple(arch, Inst::kIdPshufd, InstOptions::kNone, xmm0, xmm1, imm(0)); + printInfoSimple(arch, Inst::kIdPabsb, InstOptions::kNone, mm1, mm2); + printInfoSimple(arch, Inst::kIdPabsb, InstOptions::kNone, xmm1, xmm2); + printInfoSimple(arch, Inst::kIdPextrw, InstOptions::kNone, eax, mm1, imm(0)); + printInfoSimple(arch, Inst::kIdPextrw, InstOptions::kNone, eax, xmm1, imm(0)); + printInfoSimple(arch, Inst::kIdPextrw, InstOptions::kNone, ptr(rax), xmm1, imm(0)); - printInfoSimple(arch, Inst::kIdVpdpbusd, 0, xmm0, xmm1, xmm2); - printInfoSimple(arch, Inst::kIdVpdpbusd, Inst::kOptionVex, xmm0, xmm1, xmm2); + printInfoSimple(arch, Inst::kIdVpdpbusd, InstOptions::kNone, xmm0, xmm1, xmm2); + printInfoSimple(arch, Inst::kIdVpdpbusd, InstOptions::kX86_Vex, xmm0, xmm1, xmm2); - printInfoSimple(arch, Inst::kIdVaddpd, 0, ymm0, ymm1, ymm2); - printInfoSimple(arch, Inst::kIdVaddpd, 0, ymm0, ymm30, ymm31); - printInfoSimple(arch, Inst::kIdVaddpd, 0, zmm0, zmm1, zmm2); + printInfoSimple(arch, Inst::kIdVaddpd, InstOptions::kNone, ymm0, ymm1, ymm2); + printInfoSimple(arch, Inst::kIdVaddpd, InstOptions::kNone, ymm0, ymm30, ymm31); + printInfoSimple(arch, Inst::kIdVaddpd, InstOptions::kNone, zmm0, zmm1, zmm2); - printInfoExtra(arch, Inst::kIdVaddpd, 0, k1, zmm0, zmm1, zmm2); - printInfoExtra(arch, Inst::kIdVaddpd, Inst::kOptionZMask, k1, zmm0, zmm1, zmm2); + printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kNone, k1, zmm0, zmm1, zmm2); + printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kX86_ZMask, k1, zmm0, zmm1, zmm2); #endif } diff --git a/test/asmjit_test_misc.h b/test/asmjit_test_misc.h index f0d156f..0839d30 100644 --- a/test/asmjit_test_misc.h +++ b/test/asmjit_test_misc.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_TEST_MISC_H_INCLUDED #define ASMJIT_TEST_MISC_H_INCLUDED @@ -60,8 +42,8 @@ static void generateSseAlphaBlendInternal( cc.movd(v0080, gp0.r32()); cc.mov(gp0.r32(), 0x01010101); cc.movd(v0101, gp0.r32()); - cc.pshufd(v0080, v0080, x86::Predicate::shuf(0, 0, 0, 0)); - cc.pshufd(v0101, v0101, x86::Predicate::shuf(0, 0, 0, 0)); + cc.pshufd(v0080, v0080, x86::shuffleImm(0, 0, 0, 0)); + cc.pshufd(v0101, v0101, x86::shuffleImm(0, 0, 0, 0)); // How many pixels have to be processed to make the loop aligned. cc.xor_(j, j); @@ -89,7 +71,7 @@ static void generateSseAlphaBlendInternal( cc.psrlw(a0, 8); cc.punpcklbw(x0, vzero); - cc.pshuflw(a0, a0, x86::Predicate::shuf(1, 1, 1, 1)); + cc.pshuflw(a0, a0, x86::shuffleImm(1, 1, 1, 1)); cc.punpcklbw(y0, vzero); cc.pmullw(x0, a0); @@ -144,8 +126,8 @@ static void generateSseAlphaBlendInternal( cc.punpckhbw(x1, vzero); cc.punpckhwd(a1, a1); - cc.pshufd(a0, a0, x86::Predicate::shuf(3, 3, 1, 1)); - cc.pshufd(a1, a1, x86::Predicate::shuf(3, 3, 1, 1)); + cc.pshufd(a0, a0, x86::shuffleImm(3, 3, 1, 1)); + cc.pshufd(a1, a1, x86::shuffleImm(3, 3, 1, 1)); cc.pmullw(x0, a0); cc.pmullw(x1, a1); @@ -188,7 +170,7 @@ static void generateSseAlphaBlend(asmjit::BaseEmitter& emitter, bool emitPrologE if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -220,7 +202,7 @@ static void generateSseAlphaBlend(asmjit::BaseEmitter& emitter, bool emitPrologE if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -260,10 +242,10 @@ static void generateSseAlphaBlend(asmjit::BaseEmitter& emitter, bool emitPrologE Xmm v6 = cc.newXmm("v6"); Xmm v7 = cc.newXmm("v7"); - cc.addFunc(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost)); - cc.setArg(0, dst); - cc.setArg(1, src); - cc.setArg(2, i); + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost)); + funcNode->setArg(0, dst); + funcNode->setArg(1, src); + funcNode->setArg(2, i); generateSseAlphaBlendInternal(cc, dst, src, i, j, v0, v1, v2, v3, v4, v5, v6, v7); cc.endFunc(); } diff --git a/test/asmjit_test_perf.cpp b/test/asmjit_test_perf.cpp index 6340129..2ade96c 100644 --- a/test/asmjit_test_perf.cpp +++ b/test/asmjit_test_perf.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> #include <stdio.h> diff --git a/test/asmjit_test_perf.h b/test/asmjit_test_perf.h index 565c18a..2ab0038 100644 --- a/test/asmjit_test_perf.h +++ b/test/asmjit_test_perf.h @@ -1,30 +1,13 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_TEST_PERF_H_INCLUDED #define ASMJIT_TEST_PERF_H_INCLUDED #include <asmjit/core.h> +#include "asmjitutils.h" #include "performancetimer.h" class MyErrorHandler : public asmjit::ErrorHandler { @@ -37,14 +20,11 @@ class MyErrorHandler : public asmjit::ErrorHandler { }; template<typename EmitterT, typename FuncT> -static void bench(asmjit::CodeHolder& code, uint32_t arch, uint32_t numIterations, const char* testName, const FuncT& func) noexcept { +static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numIterations, const char* testName, const FuncT& func) noexcept { EmitterT emitter; MyErrorHandler eh; - const char* archName = - arch == asmjit::Environment::kArchX86 ? "X86" : - arch == asmjit::Environment::kArchX64 ? "X64" : "???"; - + const char* archName = asmjitArchAsString(arch); const char* emitterName = emitter.isAssembler() ? "Assembler" : emitter.isCompiler() ? "Compiler" : diff --git a/test/asmjit_test_perf_x86.cpp b/test/asmjit_test_perf_x86.cpp index 679e2c0..e2720b7 100644 --- a/test/asmjit_test_perf_x86.cpp +++ b/test/asmjit_test_perf_x86.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include <asmjit/core.h> @@ -353,7 +335,7 @@ static void generateGpSequence(BaseEmitter& emitter, InstForm form, bool emitPro if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -379,7 +361,7 @@ static void generateGpSequence(BaseEmitter& emitter, InstForm form, bool emitPro if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -404,7 +386,7 @@ static void generateGpSequence(BaseEmitter& emitter, InstForm form, bool emitPro Gp c = cc.newIntPtr("c"); Gp d = cc.newIntPtr("d"); - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); generateGpSequenceInternal(cc, form, a, b, c, d); cc.endFunc(); } @@ -945,7 +927,7 @@ static void generateSseSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -966,7 +948,7 @@ static void generateSseSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -992,7 +974,7 @@ static void generateSseSequence(BaseEmitter& emitter, InstForm form, bool emitPr Xmm c = cc.newXmm("c"); Xmm d = cc.newXmm("d"); - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); generateSseSequenceInternal(cc, form, gp, a, b, c, d); cc.endFunc(); } @@ -2115,7 +2097,7 @@ static void generateAvxSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -2136,7 +2118,7 @@ static void generateAvxSequence(BaseEmitter& emitter, InstForm form, bool emitPr if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -2162,7 +2144,7 @@ static void generateAvxSequence(BaseEmitter& emitter, InstForm form, bool emitPr Ymm c = cc.newYmm("c"); Ymm d = cc.newYmm("d"); - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); generateAvxSequenceInternal(cc, form, gp, a, b, c, d); cc.endFunc(); } @@ -4867,7 +4849,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -4888,7 +4870,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi if (emitPrologEpilog) { FuncDetail func; - func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost), cc.environment()); + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); FuncFrame frame; frame.init(func); @@ -4918,7 +4900,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi KReg kB = cc.newKq("kB"); KReg kC = cc.newKq("kC"); - cc.addFunc(FuncSignatureT<void>(CallConv::kIdHost)); + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); generateAvx512SequenceInternal(cc, form, gp, kA, kB, kC, vecA, vecB, vecC, vecD); cc.endFunc(); } @@ -4926,7 +4908,7 @@ static void generateAvx512Sequence(BaseEmitter& emitter, InstForm form, bool emi } template<typename EmitterFn> -static void benchmarkX86Function(uint32_t arch, uint32_t numIterations, const char* description, const EmitterFn& emitterFn) noexcept { +static void benchmarkX86Function(Arch arch, uint32_t numIterations, const char* description, const EmitterFn& emitterFn) noexcept { CodeHolder code; printf("%s:\n", description); @@ -4935,12 +4917,12 @@ static void benchmarkX86Function(uint32_t arch, uint32_t numIterations, const ch }); bench<x86::Assembler>(code, arch, numIterations, "[validated]", [&](x86::Assembler& cc) { - cc.addValidationOptions(BaseEmitter::kValidationOptionAssembler); + cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); emitterFn(cc, false); }); bench<x86::Assembler>(code, arch, numIterations, "[prolog/epilog]", [&](x86::Assembler& cc) { - cc.addValidationOptions(BaseEmitter::kValidationOptionAssembler); + cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); emitterFn(cc, true); }); @@ -4978,10 +4960,10 @@ void benchmarkX86Emitters(uint32_t numIterations, bool testX86, bool testX64) { uint32_t i = 0; uint32_t n = 0; - uint32_t archs[2] {}; + Arch archs[2] {}; - if (testX86) archs[n++] = Environment::kArchX86; - if (testX64) archs[n++] = Environment::kArchX64; + if (testX86) archs[n++] = Arch::kX86; + if (testX64) archs[n++] = Arch::kX64; for (i = 0; i < n; i++) { static const char description[] = "GpSequence<Reg> (Sequence of GP instructions - reg-only)"; diff --git a/test/asmjit_test_unit.cpp b/test/asmjit_test_unit.cpp index 34931b2..5658ebc 100644 --- a/test/asmjit_test_unit.cpp +++ b/test/asmjit_test_unit.cpp @@ -1,61 +1,26 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib -#include <asmjit/asmjit.h> -#include "./broken.h" +#include <asmjit/core.h> -using namespace asmjit; +#if !defined(ASMJIT_NO_X86) +#include <asmjit/x86.h> +#endif -// ============================================================================ -// [DumpCpu] -// ============================================================================ - -struct DumpCpuFeature { - uint32_t feature; - const char* name; -}; - -static const char* archToString(uint32_t arch) noexcept { - switch (arch & ~Environment::kArchBigEndianMask) { - case Environment::kArchX86 : return "X86"; - case Environment::kArchX64 : return "X64"; - case Environment::kArchARM : return "ARM"; - case Environment::kArchThumb : return "Thumb"; - case Environment::kArchAArch64 : return "AArch64"; - case Environment::kArchMIPS32_LE: return "MIPS"; - case Environment::kArchMIPS64_LE: return "MIPS64"; - default: return "Unknown"; - } -} +#include "asmjitutils.h" +#include "broken.h" + +using namespace asmjit; static void dumpCpu(void) noexcept { const CpuInfo& cpu = CpuInfo::host(); - // -------------------------------------------------------------------------- - // [CPU Information] - // -------------------------------------------------------------------------- + // CPU Information + // --------------- - INFO("Host CPU:"); + INFO("CPU Info:"); INFO(" Vendor : %s", cpu.vendor()); INFO(" Brand : %s", cpu.brand()); INFO(" Model ID : %u", cpu.modelId()); @@ -68,13 +33,12 @@ static void dumpCpu(void) noexcept { INFO(" HW-Thread Count : %u", cpu.hwThreadCount()); INFO(""); - // -------------------------------------------------------------------------- - // [CPU Features] - // -------------------------------------------------------------------------- + // CPU Features + // ------------ #ifndef ASMJIT_NO_LOGGING INFO("CPU Features:"); - BaseFeatures::Iterator it(cpu.features().iterator()); + CpuFeatures::Iterator it(cpu.features().iterator()); while (it.hasNext()) { uint32_t featureId = uint32_t(it.next()); StringTmp<64> featureString; @@ -85,10 +49,6 @@ static void dumpCpu(void) noexcept { #endif // !ASMJIT_NO_LOGGING } -// ============================================================================ -// [DumpSizeOf] -// ============================================================================ - #define DUMP_TYPE(...) \ INFO(" %-26s: %u", #__VA_ARGS__, uint32_t(sizeof(__VA_ARGS__))) @@ -188,10 +148,6 @@ static void dumpSizeOf(void) noexcept { #undef DUMP_TYPE -// ============================================================================ -// [Main] -// ============================================================================ - static void onBeforeRun(void) noexcept { dumpCpu(); dumpSizeOf(); @@ -208,7 +164,7 @@ int main(int argc, const char* argv[]) { unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF), - archToString(Environment::kArchHost), + asmjitArchAsString(Arch::kHost), buildType ); diff --git a/test/asmjit_test_x86_sections.cpp b/test/asmjit_test_x86_sections.cpp index 582811e..afd5807 100644 --- a/test/asmjit_test_x86_sections.cpp +++ b/test/asmjit_test_x86_sections.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib // ---------------------------------------------------------------------------- // This is a working example that demonstrates how multiple sections can be @@ -58,12 +40,12 @@ static void fail(const char* message, Error err) { int main() { printf("AsmJit X86 Sections Test\n\n"); - Environment env = hostEnvironment(); + Environment env = Environment::host(); JitAllocator allocator; #ifndef ASMJIT_NO_LOGGING FileLogger logger(stdout); - logger.setIndentation(FormatOptions::kIndentationCode, 2); + logger.setIndentation(FormatIndentationGroup::kCode, 2); #endif CodeHolder code; @@ -74,7 +56,7 @@ int main() { #endif Section* dataSection; - Error err = code.newSection(&dataSection, ".data", SIZE_MAX, 0, 8); + Error err = code.newSection(&dataSection, ".data", SIZE_MAX, SectionFlags::kNone, 8); if (err) { fail("Failed to create a .data section", err); @@ -88,7 +70,7 @@ int main() { Label data = a.newLabel(); FuncDetail func; - func.init(FuncSignatureT<size_t, size_t>(CallConv::kIdHost), code.environment()); + func.init(FuncSignatureT<size_t, size_t>(CallConvId::kHost), code.environment()); FuncFrame frame; frame.init(func); @@ -145,14 +127,14 @@ int main() { } // Allocate memory for the function and relocate it there. - void* roPtr; + void* rxPtr; void* rwPtr; - err = allocator.alloc(&roPtr, &rwPtr, codeSize); + err = allocator.alloc(&rxPtr, &rwPtr, codeSize); if (err) fail("Failed to allocate executable memory", err); // Relocate to the base-address of the allocated memory. - code.relocateToBase(uint64_t(uintptr_t(roPtr))); + code.relocateToBase(uint64_t(uintptr_t(rxPtr))); // Copy the flattened code into `mem.rw`. There are two ways. You can either copy // everything manually by iterating over all sections or use `copyFlattenedData`. @@ -162,7 +144,7 @@ int main() { // Execute the function and test whether it works. typedef size_t (*Func)(size_t idx); - Func fn = (Func)roPtr; + Func fn = (Func)rxPtr; printf("\n"); if (fn(0) != dataArray[0] || diff --git a/test/asmjitutils.h b/test/asmjitutils.h new file mode 100644 index 0000000..d84d3d4 --- /dev/null +++ b/test/asmjitutils.h @@ -0,0 +1,38 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJITUTILS_H_INCLUDED +#define ASMJITUTILS_H_INCLUDED + +#include <asmjit/core.h> + +static const char* asmjitArchAsString(asmjit::Arch arch) noexcept { + switch (arch) { + case asmjit::Arch::kX86 : return "X86"; + case asmjit::Arch::kX64 : return "X64"; + + case asmjit::Arch::kRISCV32 : return "RISCV32"; + case asmjit::Arch::kRISCV64 : return "RISCV64"; + + case asmjit::Arch::kARM : return "ARM"; + case asmjit::Arch::kAArch64 : return "AArch64"; + case asmjit::Arch::kThumb : return "Thumb"; + + case asmjit::Arch::kMIPS32_LE : return "MIPS_LE"; + case asmjit::Arch::kMIPS64_LE : return "MIPS64_LE"; + + case asmjit::Arch::kARM_BE : return "ARM_BE"; + case asmjit::Arch::kThumb_BE : return "Thumb_BE"; + case asmjit::Arch::kAArch64_BE: return "AArch64_BE"; + + case asmjit::Arch::kMIPS32_BE : return "MIPS_BE"; + case asmjit::Arch::kMIPS64_BE : return "MIPS64_BE"; + + default: + return "<Unknown>"; + } +} + +#endif // ASMJITUTILS_H_INCLUDED diff --git a/test/cmdline.h b/test/cmdline.h index effedd1..4da0d2e 100644 --- a/test/cmdline.h +++ b/test/cmdline.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef CMDLINE_H_INCLUDED #define CMDLINE_H_INCLUDED @@ -28,10 +10,6 @@ #include <stdlib.h> #include <string.h> -// ============================================================================ -// [CmdLine] -// ============================================================================ - class CmdLine { public: int _argc; diff --git a/test/performancetimer.h b/test/performancetimer.h index ebbaca3..baa0479 100644 --- a/test/performancetimer.h +++ b/test/performancetimer.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef PERFORMANCETIMER_H_INCLUDED #define PERFORMANCETIMER_H_INCLUDED diff --git a/tools/configure-makefiles.sh b/tools/configure-makefiles.sh index 00d2f2f..69503dc 100755 --- a/tools/configure-makefiles.sh +++ b/tools/configure-makefiles.sh @@ -5,11 +5,9 @@ BUILD_DIR="${CURRENT_DIR}/../build" BUILD_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DASMJIT_TEST=1" echo "== [Configuring Build - Debug] ==" -mkdir -p "${BUILD_DIR}/Debug" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Debug" -DCMAKE_BUILD_TYPE=Debug ${BUILD_OPTIONS} echo "" echo "== [Configuring Build - Release] ==" -mkdir -p "${BUILD_DIR}/Release" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release" -DCMAKE_BUILD_TYPE=Release ${BUILD_OPTIONS} echo "" diff --git a/tools/configure-ninja.sh b/tools/configure-ninja.sh index f7db4d8..84808d2 100755 --- a/tools/configure-ninja.sh +++ b/tools/configure-ninja.sh @@ -5,11 +5,9 @@ BUILD_DIR="${CURRENT_DIR}/../build" BUILD_OPTIONS="-G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DASMJIT_TEST=1" echo "== [Configuring Build - Debug] ==" -mkdir -p "${BUILD_DIR}/Debug" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Debug" -DCMAKE_BUILD_TYPE=Debug ${BUILD_OPTIONS} echo "" echo "== [Configuring Build - Release] ==" -mkdir -p "${BUILD_DIR}/Release" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release" -DCMAKE_BUILD_TYPE=Release ${BUILD_OPTIONS} echo "" diff --git a/tools/configure-sanitizers.sh b/tools/configure-sanitizers.sh index d7cc48a..a9f6496 100755 --- a/tools/configure-sanitizers.sh +++ b/tools/configure-sanitizers.sh @@ -2,14 +2,12 @@ CURRENT_DIR="`pwd`" BUILD_DIR="${CURRENT_DIR}/../build" -BUILD_OPTIONS="-G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DASMJIT_TEST=1" +BUILD_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DASMJIT_TEST=1" echo "== [Configuring Build - Release_ASAN] ==" -mkdir -p "${BUILD_DIR}/Release_ASAN" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_ASAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=address echo "" echo "== [Configuring Build - Release_UBSAN] ==" -mkdir -p "${BUILD_DIR}/Release_UBSAN" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_UBSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=undefined echo "" diff --git a/tools/configure-vs-x64.bat b/tools/configure-vs-x64.bat deleted file mode 100644 index db4012a..0000000 --- a/tools/configure-vs-x64.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -set CURRENT_DIR=%CD% -set BUILD_DIR="build_vs_x64" - -mkdir ..\%BUILD_DIR% -cd ..\%BUILD_DIR% -cmake .. -G"Visual Studio 16" -A x64 -DASMJIT_TEST=1 -cd %CURRENT_DIR% diff --git a/tools/configure-vs-x86.bat b/tools/configure-vs-x86.bat deleted file mode 100644 index 7bc7b9d..0000000 --- a/tools/configure-vs-x86.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -set CURRENT_DIR=%CD% -set BUILD_DIR="build_vs_x86" - -mkdir ..\%BUILD_DIR% -cd ..\%BUILD_DIR% -cmake .. -G"Visual Studio 16" -A Win32 -DASMJIT_TEST=1 -cd %CURRENT_DIR% diff --git a/tools/configure-vs2019-x64.bat b/tools/configure-vs2019-x64.bat new file mode 100644 index 0000000..05bc31e --- /dev/null +++ b/tools/configure-vs2019-x64.bat @@ -0,0 +1,2 @@ +@echo off +cmake .. -B "..\build_vs2019_x64" -G"Visual Studio 16" -A x64 -DASMJIT_TEST=1 diff --git a/tools/configure-vs2019-x86.bat b/tools/configure-vs2019-x86.bat new file mode 100644 index 0000000..a0e2663 --- /dev/null +++ b/tools/configure-vs2019-x86.bat @@ -0,0 +1,2 @@ +@echo off +cmake .. -B "..\build_vs2019_x86" -G"Visual Studio 16" -A Win32 -DASMJIT_TEST=1 diff --git a/tools/configure-vs2022-x64.bat b/tools/configure-vs2022-x64.bat new file mode 100644 index 0000000..b33f541 --- /dev/null +++ b/tools/configure-vs2022-x64.bat @@ -0,0 +1,2 @@ +@echo off +cmake .. -B "..\build_vs2022_x64" -G"Visual Studio 17" -A x64 -DASMJIT_TEST=1 diff --git a/tools/configure-vs2022-x86.bat b/tools/configure-vs2022-x86.bat new file mode 100644 index 0000000..0ba3505 --- /dev/null +++ b/tools/configure-vs2022-x86.bat @@ -0,0 +1,2 @@ +@echo off +cmake .. -B "..\build_vs2022_x86" -G"Visual Studio 17" -A Win32 -DASMJIT_TEST=1 diff --git a/tools/tablegen-x86.js b/tools/tablegen-x86.js index 2ddaa3a..6b2110b 100644 --- a/tools/tablegen-x86.js +++ b/tools/tablegen-x86.js @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib // ============================================================================ // tablegen-x86.js @@ -161,7 +143,11 @@ const VexToEvexMap = { "vpand": "vpandd", "vpandn": "vpandnd", "vpor": "vpord", - "vpxor": "vpxord" + "vpxor": "vpxord", + "vroundpd": "vrndscalepd", + "vroundps": "vrndscaleps", + "vroundsd": "vrndscalesd", + "vroundss": "vrndscaless" }; class GenUtils { @@ -242,7 +228,8 @@ class GenUtils { var i, j; var mib = dbInsts.length > 0 && /^(?:bndldx|bndstx)$/.test(dbInsts[0].name); - if (mib) f.Mib = true; + if (mib) + f.Mib = true; var mmx = false; var vec = false; @@ -274,13 +261,14 @@ class GenUtils { const dbInst = dbInsts[i]; const operands = dbInst.operands; - if (dbInst.attributes.Lock ) f.Lock = true; - if (dbInst.attributes.XAcquire ) f.XAcquire = true; - if (dbInst.attributes.XRelease ) f.XRelease = true; - if (dbInst.attributes.BND ) f.Rep = true; - if (dbInst.attributes.REP ) f.Rep = true; - if (dbInst.attributes.REPNE ) f.Rep = true; - if (dbInst.attributes.RepIgnored) f.RepIgnored = true; + if (dbInst.attributes.Lock ) f.Lock = true; + if (dbInst.attributes.XAcquire ) f.XAcquire = true; + if (dbInst.attributes.XRelease ) f.XRelease = true; + if (dbInst.attributes.BND ) f.Rep = true; + if (dbInst.attributes.REP ) f.Rep = true; + if (dbInst.attributes.REPNE ) f.Rep = true; + if (dbInst.attributes.RepIgnored ) f.RepIgnored = true; + if (dbInst.attributes.ImplicitZeroing) f.Avx512ImplicitZ = true; if (dbInst.fpu) { for (var j = 0; j < operands.length; j++) { @@ -325,7 +313,9 @@ class GenUtils { GenUtils.assignVexEvexCompatibilityFlags(f, dbInsts) } - return Object.getOwnPropertyNames(f); + const result = Object.getOwnPropertyNames(f); + result.sort(); + return result; } static eqOps(aOps, aFrom, bOps, bFrom) { @@ -457,12 +447,12 @@ class GenUtils { } } - static controlType(dbInsts) { + static controlFlow(dbInsts) { if (dbInsts.checkAttribute("Control", "Jump")) return "Jump"; if (dbInsts.checkAttribute("Control", "Call")) return "Call"; if (dbInsts.checkAttribute("Control", "Branch")) return "Branch"; if (dbInsts.checkAttribute("Control", "Return")) return "Return"; - return "None"; + return "Regular"; } } @@ -473,6 +463,8 @@ class GenUtils { class X86TableGen extends core.TableGen { constructor() { super("X86"); + + this.emitMissingString = ""; } // -------------------------------------------------------------------------- @@ -526,31 +518,31 @@ class X86TableGen extends core.TableGen { FAIL(`Instruction '${name}' not found in asmdb`); const flags = GenUtils.flagsOf(dbInsts); - const controlType = GenUtils.controlType(dbInsts); + const controlFlow = GenUtils.controlFlow(dbInsts); const singleRegCase = GenUtils.singleRegCase(name); this.addInst({ - id : 0, // Instruction id (numeric value). - name : name, // Instruction name. - enum : enum_, // Instruction enum without `kId` prefix. - dbInsts : dbInsts, // All dbInsts returned from asmdb query. - encoding : encoding, // Instruction encoding. - opcode0 : opcode0, // Primary opcode. - opcode1 : opcode1, // Secondary opcode. - flags : flags, - signatures : null, // Instruction signatures. - controlType : controlType, - singleRegCase : singleRegCase, - - mainOpcodeValue : -1, // Main opcode value (0.255 hex). - mainOpcodeIndex : -1, // Index to InstDB::_mainOpcodeTable. - altOpcodeIndex : -1, // Index to InstDB::_altOpcodeTable. - nameIndex : -1, // Index to InstDB::_nameData. - commonInfoIndexA : -1, - commomInfoIndexB : -1, - - signatureIndex : -1, - signatureCount : -1 + id : 0, // Instruction id (numeric value). + name : name, // Instruction name. + enum : enum_, // Instruction enum without `kId` prefix. + dbInsts : dbInsts, // All dbInsts returned from asmdb query. + encoding : encoding, // Instruction encoding. + opcode0 : opcode0, // Primary opcode. + opcode1 : opcode1, // Secondary opcode. + flags : flags, + signatures : null, // Instruction signatures. + controlFlow : controlFlow, + singleRegCase : singleRegCase, + + mainOpcodeValue : -1, // Main opcode value (0.255 hex). + mainOpcodeIndex : -1, // Index to InstDB::_mainOpcodeTable. + altOpcodeIndex : -1, // Index to InstDB::_altOpcodeTable. + nameIndex : -1, // Index to InstDB::_nameData. + commonInfoIndex : -1, + additionalInfoIndex: -1, + + signatureIndex : -1, + signatureCount : -1 }); } @@ -563,15 +555,15 @@ class X86TableGen extends core.TableGen { merge() { var s = StringUtils.format(this.insts, "", true, function(inst) { return "INST(" + - String(inst.enum ).padEnd(17) + ", " + - String(inst.encoding ).padEnd(19) + ", " + - String(inst.opcode0 ).padEnd(26) + ", " + - String(inst.opcode1 ).padEnd(26) + ", " + - String(inst.mainOpcodeIndex ).padEnd( 3) + ", " + - String(inst.altOpcodeIndex ).padEnd( 3) + ", " + - String(inst.nameIndex ).padEnd( 5) + ", " + - String(inst.commonInfoIndexA).padEnd( 3) + ", " + - String(inst.commomInfoIndexB).padEnd( 3) + ")"; + String(inst.enum ).padEnd(17) + ", " + + String(inst.encoding ).padEnd(19) + ", " + + String(inst.opcode0 ).padEnd(26) + ", " + + String(inst.opcode1 ).padEnd(26) + ", " + + String(inst.mainOpcodeIndex ).padEnd( 3) + ", " + + String(inst.altOpcodeIndex ).padEnd( 3) + ", " + + String(inst.nameIndex ).padEnd( 5) + ", " + + String(inst.commonInfoIndex ).padEnd( 3) + ", " + + String(inst.additionalInfoIndex).padEnd( 3) + ")"; }) + "\n"; this.inject("InstInfo", s, this.insts.length * 8); } @@ -613,6 +605,7 @@ class X86TableGen extends core.TableGen { } }, this); console.log(out); + console.log(this.emitMissingString); } newInstFromGroup(dbInsts) { @@ -637,24 +630,83 @@ class X86TableGen extends core.TableGen { return s === "VEX" || s === "EVEX" || s === "XOP"; } + function formatEmit(dbi) { + const results = []; + const nameUp = dbi.name[0].toUpperCase() + dbi.name.substr(1); + + for (let choice = 0; choice < 2; choice++) { + let s = `ASMJIT_INST_${dbi.operands.length}x(${dbi.name}, ${nameUp}`; + for (let j = 0; j < dbi.operands.length; j++) { + s += ", "; + const op = dbi.operands[j]; + var reg = op.reg; + var mem = op.mem; + + if (op.isReg() && op.isMem()) { + if (choice == 0) mem = null; + if (choice == 1) reg = null; + } + + if (reg) { + if (reg === "xmm" || reg === "ymm" || reg === "zmm") + s += "Vec"; + else if (reg === "k") + s += "KReg"; + else if (reg === "r32" || reg === "r64" || reg === "r16" || reg === "r8") + s += "Gp"; + else + s += reg; + } + else if (mem) { + s += "Mem"; + } + else if (op.isImm()) { + s += "Imm"; + } + else { + s += "Unknown"; + } + } + s += `)`; + results.push(s); + } + + return results; + } + var dbi = dbInsts[0]; - var id = this.insts.length; - var name = dbi.name; - var enum_ = name[0].toUpperCase() + name.substr(1); + var id = this.insts.length; + var name = dbi.name; + var enum_ = name[0].toUpperCase() + name.substr(1); - var opcode = dbi.opcodeHex; - var modR = dbi.modR; - var mm = dbi.mm; - var pp = dbi.pp; + var opcode = dbi.opcodeHex; + var modR = dbi.modR; + var mm = dbi.mm; + var pp = dbi.pp; var encoding = dbi.encoding; - var isVec = isVecPrefix(dbi.prefix); - - var access = GetAccess(dbi); + var isVec = isVecPrefix(dbi.prefix); + var evexCount = 0; + + var access = GetAccess(dbi); + + var vexL = undefined; + var vexW = undefined; + var evexW = undefined; + var cdshl = "_"; + var tupleType = "_"; + + const tupleTypeToCDSHL = { + "FVM": "4", + "FV": "4", + "HVM": "3", + "HV": "3", + "QVM": "2", + "QV": "2", + "T1S": "?" + } - var vexL = undefined; - var vexW = undefined; - var evexW = undefined; + const emitMap = {}; for (var i = 0; i < dbInsts.length; i++) { dbi = dbInsts[i]; @@ -674,47 +726,66 @@ class X86TableGen extends core.TableGen { } if (dbi.prefix === "EVEX") { + evexCount++; var newEvexW = String(dbi.w === "W0" ? 0 : dbi.w === "W1" ? 1 : "_"); if (evexW !== undefined && evexW !== newEvexW) evexW = "x"; else evexW = newEvexW; + + if (dbi.tupleType) { + if (tupleType !== "_" && tupleType !== dbi.tupleType) { + console.log(`${dbi.name}: WARNING: TupleType ${tupleType} != ${dbi.tupleType}`); + } + + tupleType = dbi.tupleType; + } } - if (opcode !== dbi.opcodeHex ) { console.log(`ISSUE: Opcode ${opcode} != ${dbi.opcodeHex}`); return null; } - if (modR !== dbi.modR ) { console.log(`ISSUE: ModR ${modR} != ${dbi.modR}`); return null; } - if (mm !== dbi.mm ) { console.log(`ISSUE: MM ${mm} != ${dbi.mm}`); return null; } - if (pp !== dbi.pp ) { console.log(`ISSUE: PP ${pp} != ${dbi.pp}`); return null; } - if (encoding !== dbi.encoding ) { console.log(`ISSUE: Enc ${encoding} != ${dbi.encoding}`); return null; } - if (access !== GetAccess(dbi)) { console.log(`ISSUE: Access ${access} != ${GetAccess(dbi)}`); return null; } - if (isVec != isVecPrefix(dbi.prefix)) { console.log(`ISSUE: Vex/Non-Vex mismatch`); return null; } + if (opcode !== dbi.opcodeHex ) { console.log(`${dbi.name}: ISSUE: Opcode ${opcode} != ${dbi.opcodeHex}`); return null; } + if (modR !== dbi.modR ) { console.log(`${dbi.name}: ISSUE: ModR ${modR} != ${dbi.modR}`); return null; } + if (mm !== dbi.mm ) { console.log(`${dbi.name}: ISSUE: MM ${mm} != ${dbi.mm}`); return null; } + if (pp !== dbi.pp ) { console.log(`${dbi.name}: ISSUE: PP ${pp} != ${dbi.pp}`); return null; } + if (encoding !== dbi.encoding ) { console.log(`${dbi.name}: ISSUE: Enc ${encoding} != ${dbi.encoding}`); return null; } + if (access !== GetAccess(dbi)) { console.log(`${dbi.name}: ISSUE: Access ${access} != ${GetAccess(dbi)}`); return null; } + if (isVec != isVecPrefix(dbi.prefix)) { console.log(`${dbi.name}: ISSUE: Vex/Non-Vex mismatch`); return null; } + + formatEmit(dbi).forEach((emit) => { + if (!emitMap[emit]) { + emitMap[emit] = true; + this.emitMissingString += emit + "\n"; + } + }); } + if (tupleType !== "_") + cdshl = tupleTypeToCDSHL[tupleType] || "?"; + var ppmm = pp.padEnd(2).replace(/ /g, "0") + mm.padEnd(4).replace(/ /g, "0") ; var composed = composeOpCode({ - type : isVec ? "V" : "O", + type : evexCount == dbInsts.length ? "E" : isVec ? "V" : "O", prefix: ppmm, opcode: opcode, o : modR === "r" ? "_" : (modR ? modR : "_"), l : vexL !== undefined ? vexL : "_", w : vexW !== undefined ? vexW : "_", ew : evexW !== undefined ? evexW : "_", - en : "_", - tt : dbi.modRM ? dbi.modRM + " " : "_ " + en : cdshl, + tt : dbi.modRM ? dbi.modRM + " " : tupleType.padEnd(3) }); return { - id : id, - name : name, - enum : enum_, - encoding : encoding, - opcode0 : composed, - opcode1 : "0", - nameIndex : -1, - commonInfoIndexA : -1, - commomInfoIndexB : -1 + id : id, + name : name, + enum : enum_, + encoding : encoding, + opcode0 : composed, + opcode1 : "0", + nameIndex : -1, + commonInfoIndex : -1, + additionalInfoIndex: -1 }; } @@ -823,39 +894,103 @@ class AltOpcodeTable extends core.Task { const mainOpcodeTable = new IndexedArray(); const altOpcodeTable = new IndexedArray(); - mainOpcodeTable.addIndexed("O(000000,00,0,0,0,0,0,_ )"); + const cdttSimplification = { + "0" : "None", + "_" : "None", + "FV" : "ByLL", + "HV" : "ByLL", + "QV" : "ByLL", + "FVM" : "ByLL", + "T1S" : "None", + "T1F" : "None", + "T1_4X": "None", + "T2" : "None", + "T4" : "None", + "T8" : "None", + "HVM" : "ByLL", + "QVM" : "ByLL", + "OVM" : "ByLL", + "128" : "None", + "T4X" : "None" + } - function indexOpcode(opcode) { - if (opcode === "0") - return ["00", 0]; + const noOp = "O(000000,00,0,0,0,0,0,0 )"; - // O_FPU(__,__OP,_) - if (opcode.startsWith("O_FPU(")) { - var value = opcode.substring(11, 13); - var remaining = opcode.substring(0, 11) + "00" + opcode.substring(13); + mainOpcodeTable.addIndexed(noOp); - return [value, mainOpcodeTable.addIndexed(remaining.padEnd(26))]; + function splitOpcodeToComponents(opcode) { + const i = opcode.indexOf("("); + const prefix = opcode.substr(0, i); + return [prefix].concat(opcode.substring(i + 1, opcode.length - 1).split(",")); + } + + function normalizeOpcodeComponents(components) { + for (let i = 1; i < components.length; i++) { + components[i] = components[i].trim(); + // These all are zeros that only have some contextual meaning in the table, but the assembler doesn't care. + if (components[i] === "_" || components[i] === "I" || components[i] === "x") + components[i] = "0"; + } + + // Simplify CDTT (compressed displacement TupleType). + if (components.length >= 9) { + if (components[0] === "V" || components[0] === "E") { + const cdtt = components[8]; + if (cdttSimplification[cdtt] !== undefined) + components[8] = cdttSimplification[cdtt]; + } } + return components; + } + + function joinOpcodeComponents(components) { + const prefix = components[0]; + const values = components.slice(1); + if (values.length >= 8) + values[7] = values[7].padEnd(4); + return prefix + "(" + values.join(",") + ")"; + } + + function indexMainOpcode(opcode) { + if (opcode === "0") + return ["00", 0]; - // X(______,OP,_,_,_,_,_,_ ) - if (opcode.startsWith("O(") || opcode.startsWith("V(") || opcode.startsWith("E(")) { - var value = opcode.substring(9, 11); - var remaining = opcode.substring(0, 9) + "00" + opcode.substring(11); + var opcodeByte = ""; + const components = normalizeOpcodeComponents(splitOpcodeToComponents(opcode)); - remaining = remaining.replace(/,[_xI],/g, ",0,"); - remaining = remaining.replace(/,[_xI],/g, ",0,"); - return [value, mainOpcodeTable.addIndexed(remaining.padEnd(26))]; + if (components[0] === "O_FPU") { + // Reset opcode byte, this is stored in the instruction data itself. + opcodeByte = components[2].substr(2, 2); + components[2] = components[2].substr(0, 2) + "00"; + } + else if (components[0] === "O" || components[0] === "V" || components[0] === "E") { + // Reset opcode byte, this is stored in the instruction data itself. + opcodeByte = components[2]; + components[2] = "00"; + } + else { + FAIL(`Failed to process opcode '${opcode}'`); } - FAIL(`Failed to process opcode '${opcode}'`); + const newOpcode = joinOpcodeComponents(components); + return [opcodeByte, mainOpcodeTable.addIndexed(newOpcode.padEnd(27))]; + } + + function indexAltOpcode(opcode) { + if (opcode === "0") + opcode = noOp; + else + opcode = joinOpcodeComponents(normalizeOpcodeComponents(splitOpcodeToComponents(opcode))); + return altOpcodeTable.addIndexed(opcode.padEnd(27)); } insts.map((inst) => { - const [value, index] = indexOpcode(inst.opcode0); + const [value, index] = indexMainOpcode(inst.opcode0); inst.mainOpcodeValue = value; inst.mainOpcodeIndex = index; - inst.altOpcodeIndex = altOpcodeTable.addIndexed(inst.opcode1.padEnd(26)); + inst.altOpcodeIndex = indexAltOpcode(inst.opcode1); }); + // console.log(mainOpcodeTable.length); // console.log(StringUtils.format(mainOpcodeTable, kIndent, true)); @@ -877,84 +1012,32 @@ const RegOp = MapUtils.arrayToMap(["al", "ah", "ax", "eax", "rax", "cl", "r8lo", const MemOp = MapUtils.arrayToMap(["m8", "m16", "m32", "m48", "m64", "m80", "m128", "m256", "m512", "m1024"]); const cmpOp = StringUtils.makePriorityCompare([ - "r8lo", "r8hi", "r16", "r32", "r64", "xmm", "ymm", "zmm", "mm", "k", "sreg", "creg", "dreg", "st", "bnd", - "mem", "vm", "m8", "m16", "m32", "m48", "m64", "m80", "m128", "m256", "m512", "m1024", - "mib", - "vm32x", "vm32y", "vm32z", "vm64x", "vm64y", "vm64z", - "memBase", "memES", "memDS", - "i4", "u4", "i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", - "rel8", "rel32", - "implicit" + "RegGpbLo", "RegGpbHi", "RegGpw", "RegGpd", "RegGpq", "RegXmm", "RegYmm", "RegZmm", "RegMm", "RegKReg", "RegSReg", "RegCReg", "RegDReg", "RegSt", "RegBnd", "RegTmm", + "MemUnspecified", "Mem8", "Mem16", "Mem32", "Mem48", "Mem64", "Mem80", "Mem128", "Mem256", "Mem512", "Mem1024", + "Vm32x", "Vm32y", "Vm32z", "Vm64x", "Vm64y", "Vm64z", + "ImmI4", "ImmU4", "ImmI8", "ImmU8", "ImmI16", "ImmU16", "ImmI32", "ImmU32", "ImmI64", "ImmU64", + "Rel8", "Rel32", + "FlagMemBase", + "FlagMemDs", + "FlagMemEs", + "FlagMib", + "FlagTMem", + "FlagConsecutive", + "FlagImplicit" ]); -const OpToAsmJitOp = { - "implicit": "F(Implicit)", - - "r8lo" : "F(GpbLo)", - "r8hi" : "F(GpbHi)", - "r16" : "F(Gpw)", - "r32" : "F(Gpd)", - "r64" : "F(Gpq)", - "xmm" : "F(Xmm)", - "ymm" : "F(Ymm)", - "zmm" : "F(Zmm)", - "mm" : "F(Mm)", - "k" : "F(KReg)", - "sreg" : "F(SReg)", - "creg" : "F(CReg)", - "dreg" : "F(DReg)", - "st" : "F(St)", - "bnd" : "F(Bnd)", - "tmm" : "F(Tmm)", - - "mem" : "F(Mem)", - "vm" : "F(Vm)", - - "i4" : "F(I4)", - "u4" : "F(U4)", - "i8" : "F(I8)", - "u8" : "F(U8)", - "i16" : "F(I16)", - "u16" : "F(U16)", - "i32" : "F(I32)", - "u32" : "F(U32)", - "i64" : "F(I64)", - "u64" : "F(U64)", - - "rel8" : "F(Rel8)", - "rel32" : "F(Rel32)", - - "m8" : "M(M8)", - "m16" : "M(M16)", - "m32" : "M(M32)", - "m48" : "M(M48)", - "m64" : "M(M64)", - "m80" : "M(M80)", - "m128" : "M(M128)", - "m256" : "M(M256)", - "m512" : "M(M512)", - "m1024" : "M(M1024)", - "mib" : "M(Mib)", - "mAny" : "M(Any)", - "vm32x" : "M(Vm32x)", - "vm32y" : "M(Vm32y)", - "vm32z" : "M(Vm32z)", - "vm64x" : "M(Vm64x)", - "vm64y" : "M(Vm64y)", - "vm64z" : "M(Vm64z)", - - "memBase" : "M(BaseOnly)", - "memDS" : "M(Ds)", - "memES" : "M(Es)" -}; - -function StringifyArray(a, map) { +function StringifyOpArray(a, map) { var s = ""; for (var i = 0; i < a.length; i++) { const op = a[i]; - if (!hasOwn.call(map, op)) + var mapped = null; + if (typeof map === "function") + mapped = map(op); + else if (hasOwn.call(map, op)) + mapped = map[op]; + else FAIL(`UNHANDLED OPERAND '${op}'`); - s += (s ? " | " : "") + map[op]; + s += (s ? " | " : "") + mapped; } return s ? s : "0"; } @@ -1034,134 +1117,117 @@ class OSignature { } toAsmJitOpData() { - var oFlags = this.flags; + var opFlags = Object.create(null); + var regMask = 0; - var mFlags = Object.create(null); - var mMemFlags = Object.create(null); - var mExtFlags = Object.create(null); - var sRegMask = 0; - - for (var k in oFlags) { + for (var k in this.flags) { switch (k) { - case "implicit": - case "r8lo" : - case "r8hi" : - case "r16" : - case "r32" : - case "r64" : - case "creg" : - case "dreg" : - case "sreg" : - case "bnd" : - case "st" : - case "k" : - case "mm" : - case "xmm" : - case "ymm" : - case "zmm" : - case "tmm" : mFlags[k] = true; break; - - case "m8" : - case "m16" : - case "m32" : - case "m48" : - case "m64" : - case "m80" : - case "m128" : - case "m256" : - case "m512" : - case "m1024" : mFlags.mem = true; mMemFlags[k] = true; break; - case "mib" : mFlags.mem = true; mMemFlags.mib = true; break; - case "mem" : mFlags.mem = true; mMemFlags.mAny = true; break; - case "tmem" : mFlags.mem = true; mMemFlags.mAny = true; break; - - case "memBase" : mFlags.mem = true; mMemFlags.memBase = true; break; - case "memDS" : mFlags.mem = true; mMemFlags.memDS = true; break; - case "memES" : mFlags.mem = true; mMemFlags.memES = true; break; - case "memZAX" : mFlags.mem = true; sRegMask |= 1 << 0; break; - case "memZSI" : mFlags.mem = true; sRegMask |= 1 << 6; break; - case "memZDI" : mFlags.mem = true; sRegMask |= 1 << 7; break; - - case "vm32x" : mFlags.vm = true; mMemFlags.vm32x = true; break; - case "vm32y" : mFlags.vm = true; mMemFlags.vm32y = true; break; - case "vm32z" : mFlags.vm = true; mMemFlags.vm32z = true; break; - case "vm64x" : mFlags.vm = true; mMemFlags.vm64x = true; break; - case "vm64y" : mFlags.vm = true; mMemFlags.vm64y = true; break; - case "vm64z" : mFlags.vm = true; mMemFlags.vm64z = true; break; - - case "i4" : - case "u4" : - case "i8" : - case "u8" : - case "i16" : - case "u16" : - case "i32" : - case "u32" : - case "i64" : - case "u64" : mFlags[k] = true; break; - - case "rel8" : - case "rel32" : - mFlags.i32 = true; - mFlags.i64 = true; - mFlags[k] = true; - break; - - case "rel16" : - mFlags.i32 = true; - mFlags.i64 = true; - mFlags.rel32 = true; - break; - - default: { - switch (k) { - case "es" : mFlags.sreg = true; sRegMask |= 1 << 1; break; - case "cs" : mFlags.sreg = true; sRegMask |= 1 << 2; break; - case "ss" : mFlags.sreg = true; sRegMask |= 1 << 3; break; - case "ds" : mFlags.sreg = true; sRegMask |= 1 << 4; break; - case "fs" : mFlags.sreg = true; sRegMask |= 1 << 5; break; - case "gs" : mFlags.sreg = true; sRegMask |= 1 << 6; break; - case "al" : mFlags.r8lo = true; sRegMask |= 1 << 0; break; - case "ah" : mFlags.r8hi = true; sRegMask |= 1 << 0; break; - case "ax" : mFlags.r16 = true; sRegMask |= 1 << 0; break; - case "eax" : mFlags.r32 = true; sRegMask |= 1 << 0; break; - case "rax" : mFlags.r64 = true; sRegMask |= 1 << 0; break; - case "cl" : mFlags.r8lo = true; sRegMask |= 1 << 1; break; - case "ch" : mFlags.r8hi = true; sRegMask |= 1 << 1; break; - case "cx" : mFlags.r16 = true; sRegMask |= 1 << 1; break; - case "ecx" : mFlags.r32 = true; sRegMask |= 1 << 1; break; - case "rcx" : mFlags.r64 = true; sRegMask |= 1 << 1; break; - case "dl" : mFlags.r8lo = true; sRegMask |= 1 << 2; break; - case "dh" : mFlags.r8hi = true; sRegMask |= 1 << 2; break; - case "dx" : mFlags.r16 = true; sRegMask |= 1 << 2; break; - case "edx" : mFlags.r32 = true; sRegMask |= 1 << 2; break; - case "rdx" : mFlags.r64 = true; sRegMask |= 1 << 2; break; - case "bl" : mFlags.r8lo = true; sRegMask |= 1 << 3; break; - case "bh" : mFlags.r8hi = true; sRegMask |= 1 << 3; break; - case "bx" : mFlags.r16 = true; sRegMask |= 1 << 3; break; - case "ebx" : mFlags.r32 = true; sRegMask |= 1 << 3; break; - case "rbx" : mFlags.r64 = true; sRegMask |= 1 << 3; break; - case "si" : mFlags.r16 = true; sRegMask |= 1 << 6; break; - case "esi" : mFlags.r32 = true; sRegMask |= 1 << 6; break; - case "rsi" : mFlags.r64 = true; sRegMask |= 1 << 6; break; - case "di" : mFlags.r16 = true; sRegMask |= 1 << 7; break; - case "edi" : mFlags.r32 = true; sRegMask |= 1 << 7; break; - case "rdi" : mFlags.r64 = true; sRegMask |= 1 << 7; break; - case "st0" : mFlags.st = true; sRegMask |= 1 << 0; break; - case "xmm0" : mFlags.xmm = true; sRegMask |= 1 << 0; break; - case "ymm0" : mFlags.ymm = true; sRegMask |= 1 << 0; break; - default: - console.log(`UNKNOWN OPERAND '${k}'`); - } - } + case "r8lo" : opFlags.RegGpbLo = true; break; + case "r8hi" : opFlags.RegGpbHi = true; break; + case "r16" : opFlags.RegGpw = true; break; + case "r32" : opFlags.RegGpd = true; break; + case "r64" : opFlags.RegGpq = true; break; + case "creg" : opFlags.RegCReg = true; break; + case "dreg" : opFlags.RegDReg = true; break; + case "sreg" : opFlags.RegSReg = true; break; + case "bnd" : opFlags.RegBnd = true; break; + case "st" : opFlags.RegSt = true; break; + case "k" : opFlags.RegKReg = true; break; + case "mm" : opFlags.RegMm = true; break; + case "xmm" : opFlags.RegXmm = true; break; + case "ymm" : opFlags.RegYmm = true; break; + case "zmm" : opFlags.RegZmm = true; break; + case "tmm" : opFlags.RegTmm = true; break; + + case "m8" : opFlags.Mem8 = true; break; + case "m16" : opFlags.Mem16 = true; break; + case "m32" : opFlags.Mem32 = true; break; + case "m48" : opFlags.Mem48 = true; break; + case "m64" : opFlags.Mem64 = true; break; + case "m80" : opFlags.Mem80 = true; break; + case "m128" : opFlags.Mem128 = true; break; + case "m256" : opFlags.Mem256 = true; break; + case "m512" : opFlags.Mem512 = true; break; + case "m1024" : opFlags.Mem1024 = true; break; + + case "mem" : opFlags.MemUnspecified = true; break; + case "mib" : opFlags.MemUnspecified = true; opFlags.FlagMib = true; break; + case "tmem" : opFlags.MemUnspecified = true; opFlags.FlagTMem = true; break; + + case "memBase" : opFlags.FlagMemBase = true; break; + case "memDS" : opFlags.FlagMemDs = true; break; + case "memES" : opFlags.FlagMemEs = true; break; + case "memZAX" : regMask |= 1 << 0; break; + case "memZSI" : regMask |= 1 << 6; break; + case "memZDI" : regMask |= 1 << 7; break; + + case "vm32x" : opFlags.Vm32x = true; break; + case "vm32y" : opFlags.Vm32y = true; break; + case "vm32z" : opFlags.Vm32z = true; break; + case "vm64x" : opFlags.Vm64x = true; break; + case "vm64y" : opFlags.Vm64y = true; break; + case "vm64z" : opFlags.Vm64z = true; break; + + case "i4" : opFlags.ImmI4 = true; break; + case "u4" : opFlags.ImmU4 = true; break; + case "i8" : opFlags.ImmI8 = true; break; + case "u8" : opFlags.ImmU8 = true; break; + case "i16" : opFlags.ImmI16 = true; break; + case "u16" : opFlags.ImmU16 = true; break; + case "i32" : opFlags.ImmI32 = true; break; + case "u32" : opFlags.ImmU32 = true; break; + case "i64" : opFlags.ImmI64 = true; break; + case "u64" : opFlags.ImmU64 = true; break; + + case "rel8" : opFlags.ImmI32 = true; opFlags.ImmI64 = true; opFlags.Rel8 = true; break; + case "rel16" : opFlags.ImmI32 = true; opFlags.ImmI64 = true; opFlags.Rel32 = true; break; + case "rel32" : opFlags.ImmI32 = true; opFlags.ImmI64 = true; opFlags.Rel32 = true; break; + + case "es" : opFlags.RegSReg = true; regMask |= 1 << 1; break; + case "cs" : opFlags.RegSReg = true; regMask |= 1 << 2; break; + case "ss" : opFlags.RegSReg = true; regMask |= 1 << 3; break; + case "ds" : opFlags.RegSReg = true; regMask |= 1 << 4; break; + case "fs" : opFlags.RegSReg = true; regMask |= 1 << 5; break; + case "gs" : opFlags.RegSReg = true; regMask |= 1 << 6; break; + case "al" : opFlags.RegGpbLo = true; regMask |= 1 << 0; break; + case "ah" : opFlags.RegGpbHi = true; regMask |= 1 << 0; break; + case "ax" : opFlags.RegGpw = true; regMask |= 1 << 0; break; + case "eax" : opFlags.RegGpd = true; regMask |= 1 << 0; break; + case "rax" : opFlags.RegGpq = true; regMask |= 1 << 0; break; + case "cl" : opFlags.RegGpbLo = true; regMask |= 1 << 1; break; + case "ch" : opFlags.RegGpbHi = true; regMask |= 1 << 1; break; + case "cx" : opFlags.RegGpw = true; regMask |= 1 << 1; break; + case "ecx" : opFlags.RegGpd = true; regMask |= 1 << 1; break; + case "rcx" : opFlags.RegGpq = true; regMask |= 1 << 1; break; + case "dl" : opFlags.RegGpbLo = true; regMask |= 1 << 2; break; + case "dh" : opFlags.RegGpbHi = true; regMask |= 1 << 2; break; + case "dx" : opFlags.RegGpw = true; regMask |= 1 << 2; break; + case "edx" : opFlags.RegGpd = true; regMask |= 1 << 2; break; + case "rdx" : opFlags.RegGpq = true; regMask |= 1 << 2; break; + case "bl" : opFlags.RegGpbLo = true; regMask |= 1 << 3; break; + case "bh" : opFlags.RegGpbHi = true; regMask |= 1 << 3; break; + case "bx" : opFlags.RegGpw = true; regMask |= 1 << 3; break; + case "ebx" : opFlags.RegGpd = true; regMask |= 1 << 3; break; + case "rbx" : opFlags.RegGpq = true; regMask |= 1 << 3; break; + case "si" : opFlags.RegGpw = true; regMask |= 1 << 6; break; + case "esi" : opFlags.RegGpd = true; regMask |= 1 << 6; break; + case "rsi" : opFlags.RegGpq = true; regMask |= 1 << 6; break; + case "di" : opFlags.RegGpw = true; regMask |= 1 << 7; break; + case "edi" : opFlags.RegGpd = true; regMask |= 1 << 7; break; + case "rdi" : opFlags.RegGpq = true; regMask |= 1 << 7; break; + case "st0" : opFlags.RegSt = true; regMask |= 1 << 0; break; + case "xmm0" : opFlags.RegXmm = true; regMask |= 1 << 0; break; + case "ymm0" : opFlags.RegYmm = true; regMask |= 1 << 0; break; + + case "implicit": opFlags.FlagImplicit = true; break; + + default: + console.log(`UNKNOWN OPERAND '${k}'`); } } - const sFlags = StringifyArray(ArrayUtils.sorted(mFlags , cmpOp), OpToAsmJitOp); - const sMemFlags = StringifyArray(ArrayUtils.sorted(mMemFlags, cmpOp), OpToAsmJitOp); - const sExtFlags = StringifyArray(ArrayUtils.sorted(mExtFlags, cmpOp), OpToAsmJitOp); - - return `ROW(${sFlags || 0}, ${sMemFlags || 0}, ${sExtFlags || 0}, ${decToHex(sRegMask, 2)})`; + const outputFlags = StringifyOpArray(ArrayUtils.sorted(opFlags, cmpOp), function(k) { return `F(${k})`; }); + return `ROW(${outputFlags || 0}, ${decToHex(regMask, 2)})`; } } @@ -1411,7 +1477,7 @@ class InstSignatureTable extends core.Task { const oSignatureArr = []; // Must be first to be assigned to zero. - const oSignatureNone = "ROW(0, 0, 0, 0xFF)"; + const oSignatureNone = "ROW(0, 0xFF)"; oSignatureMap[oSignatureNone] = [0]; oSignatureArr.push(oSignatureNone); @@ -1508,21 +1574,19 @@ class InstSignatureTable extends core.Task { }); } - var s = `#define ROW(count, x86, x64, implicit, o0, o1, o2, o3, o4, o5) \\\n` + - ` { count, (x86 ? uint8_t(InstDB::kModeX86) : uint8_t(0)) | \\\n` + - ` (x64 ? uint8_t(InstDB::kModeX64) : uint8_t(0)) , \\\n` + - ` implicit, \\\n` + - ` 0, \\\n` + - ` { o0, o1, o2, o3, o4, o5 } \\\n` + + var s = `#define ROW(count, x86, x64, implicit, o0, o1, o2, o3, o4, o5) \\\n` + + ` { count, uint8_t(x86 ? uint8_t(InstDB::Mode::kX86) : uint8_t(0)) | \\\n` + + ` (x64 ? uint8_t(InstDB::Mode::kX64) : uint8_t(0)) , \\\n` + + ` implicit, \\\n` + + ` 0, \\\n` + + ` { o0, o1, o2, o3, o4, o5 } \\\n` + ` }\n` + StringUtils.makeCxxArrayWithComment(iSignatureArr, "const InstDB::InstSignature InstDB::_instSignatureTable[]") + `#undef ROW\n` + `\n` + - `#define ROW(flags, mFlags, extFlags, regId) { uint32_t(flags), uint16_t(mFlags), uint8_t(extFlags), uint8_t(regId) }\n` + - `#define F(VAL) InstDB::kOp##VAL\n` + - `#define M(VAL) InstDB::kMemOp##VAL\n` + + `#define ROW(opFlags, regId) { opFlags, uint8_t(regId) }\n` + + `#define F(VAL) uint64_t(InstDB::OpFlags::k##VAL)\n` + StringUtils.makeCxxArray(oSignatureArr, "const InstDB::OpSignature InstDB::_opSignatureTable[]") + - `#undef M\n` + `#undef F\n` + `#undef ROW\n`; this.inject("InstSignatureTable", disclaimer(s), oSignatureArr.length * 8 + iSignatureArr.length * 8); @@ -1710,18 +1774,18 @@ class InstSignatureTable extends core.Task { } // ============================================================================ -// [tablegen.x86.InstCommonInfoTableB] +// [tablegen.x86.AdditionalInfoTable] // ============================================================================ -class InstCommonInfoTableB extends core.Task { +class AdditionalInfoTable extends core.Task { constructor() { - super("InstCommonInfoTableB"); + super("AdditionalInfoTable"); } run() { const insts = this.ctx.insts; - const commonTableB = new IndexedArray(); const rwInfoTable = new IndexedArray(); + const additionaInfoTable = new IndexedArray(); // If the instruction doesn't read any flags it should point to the first index. rwInfoTable.addIndexed(`{ 0, 0 }`); @@ -1737,17 +1801,17 @@ class InstCommonInfoTableB extends core.Task { const wData = w.map(function(flag) { return `FLAG(${flag})`; }).join(" | ") || "0"; const rwDataIndex = rwInfoTable.addIndexed(`{ ${rData}, ${wData} }`); - inst.commomInfoIndexB = commonTableB.addIndexed(`{ { ${features} }, ${rwDataIndex}, 0 }`); + inst.additionalInfoIndex = additionaInfoTable.addIndexed(`{ { ${features} }, ${rwDataIndex}, 0 }`); }); - var s = `#define EXT(VAL) uint32_t(Features::k##VAL)\n` + - `const InstDB::CommonInfoTableB InstDB::_commonInfoTableB[] = {\n${StringUtils.format(commonTableB, kIndent, true)}\n};\n` + + var s = `#define EXT(VAL) uint32_t(CpuFeatures::X86::k##VAL)\n` + + `const InstDB::AdditionalInfo InstDB::_additionalInfoTable[] = {\n${StringUtils.format(additionaInfoTable, kIndent, true)}\n};\n` + `#undef EXT\n` + `\n` + - `#define FLAG(VAL) uint32_t(Status::k##VAL)\n` + + `#define FLAG(VAL) uint32_t(CpuRWFlags::kX86_##VAL)\n` + `const InstDB::RWFlagsInfoTable InstDB::_rwFlagsInfoTable[] = {\n${StringUtils.format(rwInfoTable, kIndent, true)}\n};\n` + `#undef FLAG\n`; - this.inject("InstCommonInfoTableB", disclaimer(s), commonTableB.length * 8 + rwInfoTable.length * 8); + this.inject("AdditionalInfoTable", disclaimer(s), additionaInfoTable.length * 8 + rwInfoTable.length * 8); } rwFlagsOf(dbInsts) { @@ -1852,35 +1916,35 @@ class InstRWInfoTable extends core.Task { const _ = null; this.rwCategoryByData = { Vmov1_8: [ - [{access: "W", flags: {}, fixed: -1, index: 0, width: 8}, {access: "R", flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 16}, {access: "R", flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 32}, {access: "R", flags: {}, fixed: -1, index: 0, width:256},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 64}, {access: "R", flags: {}, fixed: -1, index: 0, width:512},_,_,_,_] + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 8}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 16}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 32}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:256},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 64}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:512},_,_,_,_] ], Vmov1_4: [ - [{access: "W", flags: {}, fixed: -1, index: 0, width: 32}, {access: "R", flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 64}, {access: "R", flags: {}, fixed: -1, index: 0, width:256},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width:128}, {access: "R", flags: {}, fixed: -1, index: 0, width:512},_,_,_,_] + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 32}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 64}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:256},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width:128}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:512},_,_,_,_] ], Vmov1_2: [ - [{access: "W", flags: {}, fixed: -1, index: 0, width: 64}, {access: "R", flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width:128}, {access: "R", flags: {}, fixed: -1, index: 0, width:256},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width:256}, {access: "R", flags: {}, fixed: -1, index: 0, width:512},_,_,_,_] + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 64}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width:128}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:256},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width:256}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:512},_,_,_,_] ], Vmov2_1: [ - [{access: "W", flags: {}, fixed: -1, index: 0, width: 128}, {access: "R", flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 256}, {access: "R", flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 512}, {access: "R", flags: {}, fixed: -1, index: 0, width:256},_,_,_,_] + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 128}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 256}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:128},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 512}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:256},_,_,_,_] ], Vmov4_1: [ - [{access: "W", flags: {}, fixed: -1, index: 0, width: 128}, {access: "R", flags: {}, fixed: -1, index: 0, width: 32},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 256}, {access: "R", flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 512}, {access: "R", flags: {}, fixed: -1, index: 0, width:128},_,_,_,_] + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 128}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 32},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 256}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 512}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width:128},_,_,_,_] ], Vmov8_1: [ - [{access: "W", flags: {}, fixed: -1, index: 0, width: 128}, {access: "R", flags: {}, fixed: -1, index: 0, width: 16},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 256}, {access: "R", flags: {}, fixed: -1, index: 0, width: 32},_,_,_,_], - [{access: "W", flags: {}, fixed: -1, index: 0, width: 512}, {access: "R", flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_] + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 128}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 16},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 256}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 32},_,_,_,_], + [{access: "W", clc: 0, flags: {}, fixed: -1, index: 0, width: 512}, {access: "R", clc: 0, flags: {}, fixed: -1, index: 0, width: 64},_,_,_,_] ] }; } @@ -1900,8 +1964,9 @@ class InstRWInfoTable extends core.Task { "0x0000000000000000u", "0x0000000000000000u", "0xFF", + "0", CxxUtils.struct(0), - "0" + "OpRWFlags::kNone" ); this.rmInfoTable.addIndexed(noRmInfo); @@ -1946,12 +2011,15 @@ class InstRWInfoTable extends core.Task { const wIndex = opAcc === "X" || opAcc === "W" ? op.index : -1; const wWidth = opAcc === "X" || opAcc === "W" ? op.width : -1; + const consecutiveLeadCount = op.clc; + const opData = CxxUtils.struct( this.byteMaskFromBitRanges([{ start: rIndex, end: rIndex + rWidth - 1 }]) + "u", this.byteMaskFromBitRanges([{ start: wIndex, end: wIndex + wWidth - 1 }]) + "u", StringUtils.decToHex(op.fixed === -1 ? 0xFF : op.fixed, 2), + String(consecutiveLeadCount), CxxUtils.struct(0), - CxxUtils.flags(flags, function(flag) { return "OpRWInfo::k" + flag; }) + CxxUtils.flags(flags, function(flag) { return "OpRWFlags::k" + flag; }, "OpRWFlags::kNone") ); rwOpsIndex.push(this.opInfoTable.addIndexed(opData)); @@ -1962,7 +2030,7 @@ class InstRWInfoTable extends core.Task { StringUtils.decToHex(rmInfo.rmIndexes, 2), String(Math.max(rmInfo.memFixed, 0)).padEnd(2), CxxUtils.flags({ "InstDB::RWInfoRm::kFlagAmbiguous": Boolean(rmInfo.memAmbiguous) }), - rmInfo.memExtension === "None" ? "0" : "Features::k" + rmInfo.memExtension + rmInfo.memExtension === "None" ? "0" : "uint32_t(CpuFeatures::X86::k" + rmInfo.memExtension + ")" ); const rwData = CxxUtils.struct( @@ -2045,6 +2113,7 @@ class InstRWInfoTable extends core.Task { return { access: op.read && op.write ? "X" : op.read ? "R" : op.write ? "W" : "?", + clc: 0, flags: {}, fixed: GenUtils.fixedRegOf(op.reg), index: op.rwxIndex, @@ -2066,12 +2135,16 @@ class InstRWInfoTable extends core.Task { const opSize = op.isReg() ? op.regSize : op.memSize; var d = { access: op.read && op.write ? "X" : op.read ? "R" : op.write ? "W" : "?", + clc: 0, flags: {}, fixed: -1, index: -1, width: -1 }; + if (op.consecutiveLeadCount) + d.clc = op.consecutiveLeadCount; + if (op.isReg()) d.fixed = GenUtils.fixedRegOf(op.reg); else @@ -2080,6 +2153,9 @@ class InstRWInfoTable extends core.Task { if (op.zext) d.flags.ZExt = true; + if (op.regIndexRel) + d.flags.Consecutive = true; + for (var k in self.rwOpFlagsForInstruction(asmInst.name, j)) d.flags[k] = true; @@ -2436,7 +2512,7 @@ class InstCommonTable extends core.Task { "IdEnum", "NameTable", "InstSignatureTable", - "InstCommonInfoTableB", + "AdditionalInfoTable", "InstRWInfoTable" ]); } @@ -2452,26 +2528,26 @@ class InstCommonTable extends core.Task { const commonFlags = commonFlagsArray.map(function(flag) { return `F(${flag })`; }).join("|") || "0"; const avx512Flags = avx512FlagsArray.map(function(flag) { return `X(${flag.substr(6)})`; }).join("|") || "0"; - const singleRegCase = `SINGLE_REG(${inst.singleRegCase})`; - const controlType = `CONTROL(${inst.controlType})`; + const controlFlow = `CONTROL_FLOW(${inst.controlFlow})`; + const singleRegCase = `SAME_REG_HINT(${inst.singleRegCase})`; const row = "{ " + String(commonFlags ).padEnd(50) + ", " + String(avx512Flags ).padEnd(30) + ", " + String(inst.signatureIndex).padEnd( 3) + ", " + String(inst.signatureCount).padEnd( 2) + ", " + - String(controlType ).padEnd(16) + ", " + + String(controlFlow ).padEnd(16) + ", " + String(singleRegCase ).padEnd(16) + "}"; - inst.commonInfoIndexA = table.addIndexed(row); + inst.commonInfoIndex = table.addIndexed(row); }); - var s = `#define F(VAL) InstDB::kFlag##VAL\n` + - `#define X(VAL) InstDB::kAvx512Flag##VAL\n` + - `#define CONTROL(VAL) Inst::kControl##VAL\n` + - `#define SINGLE_REG(VAL) InstDB::kSingleReg##VAL\n` + + var s = `#define F(VAL) uint32_t(InstDB::InstFlags::k##VAL)\n` + + `#define X(VAL) uint32_t(InstDB::Avx512Flags::k##VAL)\n` + + `#define CONTROL_FLOW(VAL) uint8_t(InstControlFlow::k##VAL)\n` + + `#define SAME_REG_HINT(VAL) uint8_t(InstSameRegHint::k##VAL)\n` + `const InstDB::CommonInfo InstDB::_commonInfoTable[] = {\n${StringUtils.format(table, kIndent, true)}\n};\n` + - `#undef SINGLE_REG\n` + - `#undef CONTROL\n` + + `#undef SAME_REG_HINT\n` + + `#undef CONTROL_FLOW\n` + `#undef X\n` + `#undef F\n`; this.inject("InstCommonTable", disclaimer(s), table.length * 8); @@ -2487,7 +2563,7 @@ new X86TableGen() .addTask(new NameTable()) .addTask(new AltOpcodeTable()) .addTask(new InstSignatureTable()) - .addTask(new InstCommonInfoTableB()) + .addTask(new AdditionalInfoTable()) .addTask(new InstRWInfoTable()) .addTask(new InstCommonTable()) .run(); diff --git a/tools/tablegen.js b/tools/tablegen.js index c367522..75d81b1 100644 --- a/tools/tablegen.js +++ b/tools/tablegen.js @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib // ============================================================================ // tablegen.js @@ -426,7 +408,10 @@ exports.MapUtils = MapUtils; // ============================================================================ class CxxUtils { - static flags(obj, fn) { + static flags(obj, fn, none) { + if (none == null) + none = "0"; + if (!fn) fn = nop; @@ -435,7 +420,7 @@ class CxxUtils { if (obj[k]) out += (out ? " | " : "") + fn(k); } - return out ? out : "0"; + return out ? out : none; } static struct(...args) { |