Restructure backends

This commit is contained in:
momo5502
2025-04-11 08:58:49 +02:00
parent 6cb43b672e
commit d409c08ef6
71 changed files with 14 additions and 12 deletions

View File

@@ -0,0 +1,5 @@
add_subdirectory(unicorn-emulator)
if (MOMO_ENABLE_RUST_CODE)
add_subdirectory(icicle-emulator)
endif()

View File

@@ -0,0 +1,20 @@
add_subdirectory(icicle-bridge)
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS
*.cpp
*.hpp
*.rc
)
list(SORT SRC_FILES)
if(MOMO_BUILD_AS_LIBRARY)
add_library(icicle-emulator STATIC ${SRC_FILES})
else()
add_library(icicle-emulator SHARED ${SRC_FILES})
endif()
target_include_directories(icicle-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}")
target_link_libraries(icicle-emulator PUBLIC emulator)
target_link_libraries(icicle-emulator PRIVATE emulator-common icicle-bridge)

View File

@@ -0,0 +1,2 @@
/target
/Ghidra

View File

@@ -0,0 +1,65 @@
include(ExternalProject)
set(ICICLE_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/cargo-build)
set(ICICLE_ARTIFACT_DIR ${ICICLE_BUILD_DIR}/$<IF:$<CONFIG:Debug>,debug,release>)
set(ICICLE_RUST_PROJECT_NAME "icicle")
set(ICICLE_RUST_LIBNAME "lib${ICICLE_RUST_PROJECT_NAME}.a")
if(MSVC)
set(ICICLE_RUST_LIBNAME "${ICICLE_RUST_PROJECT_NAME}.lib")
endif()
set(CARGO_TRIPLE)
set(CARGO_OPTIONS)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(CARGO_TRIPLE "aarch64-apple-ios")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
set(CARGO_TRIPLE "aarch64-linux-android")
else()
set(CARGO_TRIPLE "${CMAKE_ANDROID_ARCH_ABI}-linux-android")
endif()
endif()
if(CARGO_TRIPLE)
set(CARGO_OPTIONS ${CARGO_OPTIONS} "--target=${CARGO_TRIPLE}")
set(ICICLE_ARTIFACT_DIR ${ICICLE_BUILD_DIR}/${CARGO_TRIPLE}/$<IF:$<CONFIG:Debug>,debug,release>)
endif()
set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/${ICICLE_RUST_LIBNAME})
ExternalProject_Add(
icicle-rust-project
PREFIX ${CMAKE_CURRENT_BINARY_DIR}
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}
BINARY_DIR ${CMAKE_CURRENT_LIST_DIR}
CONFIGURE_COMMAND ""
BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build ${CARGO_OPTIONS} --lib --profile $<IF:$<CONFIG:Debug>,dev,release>
INSTALL_COMMAND ""
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
BUILD_ALWAYS 1
BUILD_BYPRODUCTS ${ICICLE_RUST_LIB}
)
add_custom_command(
TARGET icicle-rust-project POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_LIST_DIR}/data" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
COMMENT "Copying Ghidra Processor Specification"
)
add_library(icicle-bridge INTERFACE)
add_dependencies(icicle-bridge icicle-rust-project)
target_link_libraries(icicle-bridge INTERFACE ${ICICLE_RUST_LIB})
if(MSVC)
target_link_libraries(icicle-bridge INTERFACE
ws2_32.lib
Userenv.lib
ntdll.lib
Bcrypt.lib
)
endif()

View File

@@ -0,0 +1,960 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"cpp_demangle",
"fallible-iterator",
"gimli",
"memmap2",
"object",
"rustc-demangle",
"smallvec",
"typed-arena",
]
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"getrandom",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "anyhow"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
[[package]]
name = "arbitrary"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
dependencies = [
"serde",
]
[[package]]
name = "bstr"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "bytemuck"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpp_demangle"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d"
dependencies = [
"cfg-if",
]
[[package]]
name = "cranelift"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27711210499725bafe52c320a988e27283e6cf477ee8edac57e8275bef8ea550"
dependencies = [
"cranelift-codegen",
"cranelift-frontend",
"cranelift-module",
]
[[package]]
name = "cranelift-bforest"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "540b193ff98b825a1f250a75b3118911af918a734154c69d80bcfcf91e7e9522"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-bitset"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7cb269598b9557ab942d687d3c1086d77c4b50dcf35813f3a65ba306fd42279"
[[package]]
name = "cranelift-codegen"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46566d7c83a8bff4150748d66020f4c7224091952aa4b4df1ec4959c39d937a1"
dependencies = [
"bumpalo",
"cranelift-bforest",
"cranelift-bitset",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-control",
"cranelift-entity",
"cranelift-isle",
"gimli",
"hashbrown 0.14.5",
"log",
"regalloc2",
"rustc-hash",
"smallvec",
"target-lexicon",
]
[[package]]
name = "cranelift-codegen-meta"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2df8a86a34236cc75a8a6a271973da779c2aeb36c43b6e14da474cf931317082"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf75340b6a57b7c7c1b74f10d3d90883ee6d43a554be8131a4046c2ebcf5eb65"
[[package]]
name = "cranelift-control"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e84495bc5d23d86aad8c86f8ade4af765b94882af60d60e271d3153942f1978"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963c17147b80df351965e57c04d20dbedc85bcaf44c3436780a59a3f1ff1b1c2"
dependencies = [
"cranelift-bitset",
]
[[package]]
name = "cranelift-frontend"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "727f02acbc4b4cb2ba38a6637101d579db50190df1dd05168c68e762851a3dd5"
dependencies = [
"cranelift-codegen",
"log",
"smallvec",
"target-lexicon",
]
[[package]]
name = "cranelift-isle"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b00cc2e03c748f2531eea01c871f502b909d30295fdcad43aec7bf5c5b4667"
[[package]]
name = "cranelift-jit"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f74630af581f32b99c8f4e06ee45799383ecc0795e3ff8aa86b7584bb2d643fd"
dependencies = [
"anyhow",
"cranelift-codegen",
"cranelift-control",
"cranelift-entity",
"cranelift-module",
"cranelift-native",
"libc",
"log",
"region",
"target-lexicon",
"wasmtime-jit-icache-coherence",
"windows-sys 0.59.0",
]
[[package]]
name = "cranelift-module"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aaa16c4f18a15be310df221ea544f516acc42fc58ca96e09a3d08651744efa1"
dependencies = [
"anyhow",
"cranelift-codegen",
"cranelift-control",
]
[[package]]
name = "cranelift-native"
version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbeaf978dc7c1a2de8bbb9162510ed218eb156697bc45590b8fbdd69bb08e8de"
dependencies = [
"cranelift-codegen",
"libc",
"target-lexicon",
]
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crunchy"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
dependencies = [
"libc",
"windows-sys 0.59.0",
]
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "flate2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
dependencies = [
"fallible-iterator",
"indexmap",
"stable_deref_trait",
]
[[package]]
name = "half"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [
"foldhash",
]
[[package]]
name = "icicle"
version = "0.1.0"
dependencies = [
"icicle-cpu",
"icicle-vm",
"pcode",
]
[[package]]
name = "icicle-cpu"
version = "0.1.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"addr2line",
"ahash",
"anyhow",
"bitflags 2.9.0",
"bytemuck",
"gimli",
"half",
"icicle-mem",
"object",
"pcode",
"sleigh-runtime",
"target-lexicon",
"tracing",
]
[[package]]
name = "icicle-jit"
version = "0.2.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"cranelift",
"cranelift-codegen",
"cranelift-jit",
"cranelift-module",
"cranelift-native",
"icicle-cpu",
"memoffset",
"pcode",
"target-lexicon",
"tracing",
"wasmtime-jit-debug",
]
[[package]]
name = "icicle-linux"
version = "0.1.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"bitflags 2.9.0",
"bstr",
"bytemuck",
"icicle-cpu",
"object",
"pcode",
"sleigh-runtime",
"target-lexicon",
"tracing",
]
[[package]]
name = "icicle-mem"
version = "0.3.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"ahash",
"tracing",
]
[[package]]
name = "icicle-vm"
version = "0.2.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"anyhow",
"icicle-cpu",
"icicle-jit",
"icicle-linux",
"ihex",
"object",
"pcode",
"ron",
"serde",
"serde-xml-rs",
"sleigh-compile",
"sleigh-runtime",
"target-lexicon",
"tracing",
]
[[package]]
name = "ihex"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2"
[[package]]
name = "indexmap"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
]
[[package]]
name = "libc"
version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "mach2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
dependencies = [
"libc",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "memmap2"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"crc32fast",
"flate2",
"hashbrown 0.15.2",
"indexmap",
"memchr",
"ruzstd",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "pcode"
version = "0.2.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "proc-macro2"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regalloc2"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0"
dependencies = [
"hashbrown 0.14.5",
"log",
"rustc-hash",
"slice-group-by",
"smallvec",
]
[[package]]
name = "region"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7"
dependencies = [
"bitflags 1.3.2",
"libc",
"mach2",
"windows-sys 0.52.0",
]
[[package]]
name = "ron"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64",
"bitflags 2.9.0",
"serde",
"serde_derive",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
]
[[package]]
name = "ruzstd"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f"
dependencies = [
"twox-hash",
]
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde-xml-rs"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
dependencies = [
"log",
"serde",
"thiserror",
"xml-rs",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sleigh-compile"
version = "0.3.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"pcode",
"serde",
"serde-xml-rs",
"serde_derive",
"sleigh-parse",
"sleigh-runtime",
]
[[package]]
name = "sleigh-parse"
version = "0.3.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
[[package]]
name = "sleigh-runtime"
version = "0.1.0"
source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a"
dependencies = [
"pcode",
"sleigh-parse",
]
[[package]]
name = "slice-group-by"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
[[package]]
name = "smallvec"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
[[package]]
name = "twox-hash"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
"cfg-if",
"static_assertions",
]
[[package]]
name = "typed-arena"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasmtime-jit-debug"
version = "26.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f02a0118d471de665565ed200bc56673eaa10cc8e223dfe2cef5d50ed0d9d143"
dependencies = [
"object",
"rustix",
"wasmtime-versioned-export-macros",
]
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "26.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da47fba49af72581bc0dc67c8faaf5ee550e6f106e285122a184a675193701a5"
dependencies = [
"anyhow",
"cfg-if",
"libc",
"windows-sys 0.59.0",
]
[[package]]
name = "wasmtime-versioned-export-macros"
version = "26.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8efb877c9e5e67239d4553bb44dd2a34ae5cfb728f3cf2c5e64439c6ca6ee7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "xml-rs"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -0,0 +1,12 @@
[package]
name = "icicle"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["staticlib"]
[dependencies]
icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu" }
icicle-cpu = { git = "https://github.com/icicle-emu/icicle-emu" }
pcode = { git = "https://github.com/icicle-emu/icicle-emu" }

View File

@@ -0,0 +1,33 @@
:ADCX Reg32, rm32 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; rm32 & Reg32 ... & check_Reg32_dest ... {
tmp:5 = zext(Reg32) + zext(rm32) + zext(CF);
tmpCF:1 = tmp(4); # just the carry byte
CF = tmpCF != 0;
Reg32 = tmp:4;
build check_Reg32_dest;
}
@ifdef IA64
:ADCX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
tmp:9 = zext(Reg64) + zext(rm64) + zext(CF);
tmpCF:1 = tmp(8); # just the carry byte
CF = tmpCF != 0;
Reg64 = tmp:8;
}
@endif
:ADOX Reg32, rm32 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; rm32 & Reg32 ... & check_Reg32_dest ... {
tmp:5 = zext(Reg32) + zext(rm32) + zext(OF);
tmpOF:1 = tmp(4); # just the carry byte
OF = tmpOF != 0;
Reg32 = tmp:4;
build check_Reg32_dest;
}
@ifdef IA64
:ADOX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
tmp:9 = zext(Reg64) + zext(rm64) + zext(OF);
tmpOF:1 = tmp(8); # just the carry byte
OF = tmpOF != 0;
Reg64 = tmp:8;
}
@endif

View File

@@ -0,0 +1,252 @@
# VINSERTI128/VINSERTI32x4/VINSERTI64x2/VINSERTI32x8/VINSERTI64x4 5-314 PAGE 2138 LINE 109785
define pcodeop vinserti128 ;
:VINSERTI128 YmmReg1, vexVVVV_YmmReg, XmmReg2_m128, imm8 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x38; YmmReg1 ... & XmmReg2_m128; imm8 & imm8_0 {
local tmp:16 = XmmReg2_m128;
# ignoring all but the least significant bit
if (imm8_0:1 == 0) goto <case0>;
if (imm8_0:1 == 1) goto <case1>;
<case0>
YmmReg1[0,128] = tmp;
YmmReg1[128,128] = vexVVVV_YmmReg[128,128];
goto <done>;
<case1>
YmmReg1[0,128] = vexVVVV_YmmReg[0,128];
YmmReg1[128,128] = tmp;
<done>
}
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106903
define pcodeop vgatherdpd ;
:VGATHERDPD XmmReg1, q_vm32x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x92; (XmmReg1 & YmmReg1) ... & q_vm32x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherdpd(XmmReg1, q_vm32x, vexVVVV_XmmReg);
local tmp:16 = vgatherdpd(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106908
@ifdef IA64
define pcodeop vgatherqpd ;
:VGATHERQPD XmmReg1, q_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & q_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherqpd(XmmReg1, q_vm64x, vexVVVV_XmmReg);
local tmp:16 = vgatherqpd(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
@endif
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106913
:VGATHERDPD YmmReg1, q_vm32x, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x92; YmmReg1 ... & q_vm32x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vgatherdpd(YmmReg1, q_vm32x, vexVVVV_YmmReg);
YmmReg1 = vgatherdpd(YmmReg1, vexVVVV_YmmReg);
# TODO ZmmReg1 = zext(YmmReg1)
vexVVVV_YmmReg = 0;
}
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106918
@ifdef IA64
:VGATHERQPD YmmReg1, q_vm64y, vexVVVV_YmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x93; YmmReg1 ... & q_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vgatherqpd(YmmReg1, q_vm64y, vexVVVV_YmmReg);
YmmReg1 = vgatherqpd(YmmReg1, vexVVVV_YmmReg);
# TODO ZmmReg1 = zext(YmmReg1)
vexVVVV_YmmReg = 0;
}
@endif
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107130
define pcodeop vgatherdps ;
:VGATHERDPS XmmReg1, d_vm32x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x92; (XmmReg1 & YmmReg1) ... & d_vm32x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherdps(XmmReg1, d_vm32x, vexVVVV_XmmReg);
local tmp:16 = vgatherdps(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107135
@ifdef IA64
define pcodeop vgatherqps ;
:VGATHERQPS XmmReg1, d_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherqps(XmmReg1, d_vm64x, vexVVVV_XmmReg);
local tmp:16 = vgatherqps(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
@endif
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107140
:VGATHERDPS YmmReg1, d_vm32y, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x92; YmmReg1 ... & d_vm32y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vgatherdps(YmmReg1, d_vm32y, vexVVVV_YmmReg);
YmmReg1 = vgatherdps(YmmReg1, vexVVVV_YmmReg);
# TODO ZmmReg1 = zext(YmmReg1)
vexVVVV_YmmReg = 0;
}
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107145
@ifdef IA64
:VGATHERQPS XmmReg1, d_vm64y, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vgatherqps(XmmReg1, d_vm64y, vexVVVV_XmmReg);
XmmReg1 = vgatherqps(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(XmmReg1);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
@endif
# PCMPEQQ 4-250 PAGE 1370 LINE 71171
:VPCMPEQQ YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_WIG) & vexVVVV_YmmReg; byte=0x29; YmmReg1 ... & YmmReg2_m256
{
YmmReg1[0,64] = zext(vexVVVV_YmmReg[0,64] == YmmReg2_m256[0,64]) * 0xffffffffffffffff:8;
YmmReg1[64,64] = zext(vexVVVV_YmmReg[64,64] == YmmReg2_m256[64,64]) * 0xffffffffffffffff:8;
YmmReg1[128,64] = zext(vexVVVV_YmmReg[128,64] == YmmReg2_m256[128,64]) * 0xffffffffffffffff:8;
YmmReg1[192,64] = zext(vexVVVV_YmmReg[192,64] == YmmReg2_m256[192,64]) * 0xffffffffffffffff:8;
# TODO ZmmReg1 = zext(YmmReg1)
}
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107884
define pcodeop vpgatherdd ;
:VPGATHERDD XmmReg1, d_vm32x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x90; (XmmReg1 & YmmReg1) ... & d_vm32x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherdd(XmmReg1, d_vm32x, vexVVVV_XmmReg);
local tmp:16 = vpgatherdd(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107888
@ifdef IA64
define pcodeop vpgatherqd ;
:VPGATHERQD XmmReg1, d_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherqd(XmmReg1, d_vm64x, vexVVVV_XmmReg);
local tmp:16 = vpgatherqd(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
@endif
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107892
:VPGATHERDD YmmReg1, d_vm32y, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x90; YmmReg1 ... & d_vm32y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vpgatherdd(YmmReg1, d_vm32y, vexVVVV_YmmReg);
YmmReg1 = vpgatherdd(YmmReg1, vexVVVV_YmmReg);
# TODO ZmmReg1 = zext(YmmReg1)
vexVVVV_YmmReg = 0;
}
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107896
@ifdef IA64
:VPGATHERQD XmmReg1, d_vm64y, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherqd(XmmReg1, d_vm64y, vexVVVV_XmmReg);
local tmp:16 = vpgatherqd(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
@endif
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108234
define pcodeop vpgatherdq ;
:VPGATHERDQ XmmReg1, q_vm32x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x90; (XmmReg1 & YmmReg1) ... & q_vm32x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherdq(XmmReg1, q_vm32x, vexVVVV_XmmReg);
local tmp:16 = vpgatherdq(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108238
@ifdef IA64
define pcodeop vpgatherqq ;
:VPGATHERQQ XmmReg1, q_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & q_vm64x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# XmmReg1 = vpgatherqq(XmmReg1, q_vm64x, vexVVVV_XmmReg);
local tmp:16 = vpgatherqq(XmmReg1, vexVVVV_XmmReg);
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
vexVVVV_XmmReg = 0;
}
@endif
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108242
:VPGATHERDQ YmmReg1, q_vm32x, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x90; YmmReg1 ... & q_vm32x {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vpgatherdq(YmmReg1, q_vm32x, vexVVVV_YmmReg);
YmmReg1 = vpgatherdq(YmmReg1, vexVVVV_YmmReg);
# TODO ZmmReg1 = zext(YmmReg1)
vexVVVV_YmmReg = 0;
}
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108246
@ifdef IA64
:VPGATHERQQ YmmReg1, q_vm64y, vexVVVV_YmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x91; YmmReg1 ... & q_vm64y {
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
# YmmReg1 = vpgatherqq(YmmReg1, q_vm64y, vexVVVV_YmmReg);
YmmReg1 = vpgatherqq(YmmReg1, vexVVVV_YmmReg);
# TODO ZmmReg1 = zext(YmmReg1)
vexVVVV_YmmReg = 0;
}
@endif
# PMOVMSKB 4-338 PAGE 1458 LINE 75655
:VPMOVMSKB Reg32, YmmReg2 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xD7; Reg32 & (mod=0x3 & YmmReg2) & check_Reg32_dest
{
local byte_mask:4 = 0:4;
byte_mask[0,1] = YmmReg2[7,1];
byte_mask[1,1] = YmmReg2[15,1];
byte_mask[2,1] = YmmReg2[23,1];
byte_mask[3,1] = YmmReg2[31,1];
byte_mask[4,1] = YmmReg2[39,1];
byte_mask[5,1] = YmmReg2[47,1];
byte_mask[6,1] = YmmReg2[55,1];
byte_mask[7,1] = YmmReg2[63,1];
byte_mask[8,1] = YmmReg2[71,1];
byte_mask[9,1] = YmmReg2[79,1];
byte_mask[10,1] = YmmReg2[87,1];
byte_mask[11,1] = YmmReg2[95,1];
byte_mask[12,1] = YmmReg2[103,1];
byte_mask[13,1] = YmmReg2[111,1];
byte_mask[14,1] = YmmReg2[119,1];
byte_mask[15,1] = YmmReg2[127,1];
byte_mask[16,1] = YmmReg2[135,1];
byte_mask[17,1] = YmmReg2[143,1];
byte_mask[18,1] = YmmReg2[151,1];
byte_mask[19,1] = YmmReg2[159,1];
byte_mask[20,1] = YmmReg2[167,1];
byte_mask[21,1] = YmmReg2[175,1];
byte_mask[22,1] = YmmReg2[183,1];
byte_mask[23,1] = YmmReg2[191,1];
byte_mask[24,1] = YmmReg2[199,1];
byte_mask[25,1] = YmmReg2[207,1];
byte_mask[26,1] = YmmReg2[215,1];
byte_mask[27,1] = YmmReg2[223,1];
byte_mask[28,1] = YmmReg2[231,1];
byte_mask[29,1] = YmmReg2[239,1];
byte_mask[30,1] = YmmReg2[247,1];
byte_mask[31,1] = YmmReg2[255,1];
Reg32 = zext(byte_mask);
build check_Reg32_dest;
}

View File

@@ -0,0 +1,287 @@
# MOVAPD 4-45 PAGE 1165 LINE 60844
:VMOVAPD XmmReg1, XmmReg2_m128 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x28; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
YmmReg1 = zext(XmmReg2_m128);
# TODO ZmmReg1 = zext(XmmReg1)
}
# MOVAPD 4-45 PAGE 1165 LINE 60846
:VMOVAPD XmmReg2, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x29; mod=3 & XmmReg1 & (XmmReg2 & YmmReg2)
{
YmmReg2 = zext(XmmReg1);
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVAPD 4-45 PAGE 1165 LINE 60846
:VMOVAPD m128, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x29; XmmReg1 ... & m128
{
m128 = XmmReg1;
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVAPD 4-45 PAGE 1165 LINE 60848
:VMOVAPD YmmReg1, YmmReg2_m256 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x28; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = YmmReg2_m256;
# TODO ZmmReg1 = zext(YmmReg1)
}
# MOVAPD 4-45 PAGE 1165 LINE 60850
:VMOVAPD YmmReg2_m256, YmmReg1 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x29; YmmReg1 ... & YmmReg2_m256
{
YmmReg2_m256 = YmmReg1;
# TODO ZmmReg2 = zext(YmmReg2)
}
# MOVAPS 4-49 PAGE 1169 LINE 61039
:VMOVAPS XmmReg1, XmmReg2_m128 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x28; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
YmmReg1 = zext(XmmReg2_m128);
# TODO ZmmReg1 = zext(XmmReg1)
}
# MOVAPS 4-49 PAGE 1169 LINE 61041
:VMOVAPS XmmReg2, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x29; mod=3 & XmmReg1 & (XmmReg2 & YmmReg2)
{
YmmReg2 = zext(XmmReg1);
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVAPS 4-49 PAGE 1169 LINE 61041
:VMOVAPS m128, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x29; XmmReg1 ... & m128
{
m128 = XmmReg1;
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVAPS 4-49 PAGE 1169 LINE 61043
:VMOVAPS YmmReg1, YmmReg2_m256 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x28; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = YmmReg2_m256;
# TODO ZmmReg1 = zext(YmmReg1)
}
# MOVAPS 4-49 PAGE 1169 LINE 61045
:VMOVAPS YmmReg2_m256, YmmReg1 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x29; YmmReg1 ... & YmmReg2_m256
{
YmmReg2_m256 = YmmReg1;
# TODO ZmmReg2 = zext(YmmReg2)
}
# MOVDQA,VMOVDQA32/64 4-62 PAGE 1182 LINE 61667
# Note: we do not model the exception generated if VMOVDQA is used with a memory operand which is not 16-bye aligned
:VMOVDQA XmmReg1, XmmReg2_m128 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x6F; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
YmmReg1 = zext(XmmReg2_m128);
# TODO ZmmReg1 = zext(XmmReg1)
}
# MOVDQA,VMOVDQA32/64 4-62 PAGE 1182 LINE 61669
:VMOVDQA XmmReg2, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x7F; XmmReg1 & (mod = 3 & XmmReg2 & YmmReg2)
{
YmmReg2 = zext(XmmReg1);
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVDQA,VMOVDQA32/64 4-62 PAGE 1182 LINE 61669
:VMOVDQA m128, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x7F; XmmReg1 ... & m128
{
m128 = XmmReg1;
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVDQA,VMOVDQA32/64 4-62 PAGE 1182 LINE 61671
:VMOVDQA YmmReg1, YmmReg2_m256 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x6F; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = YmmReg2_m256;
# TODO ZmmReg1 = zext(YmmReg1)
}
# MOVDQA,VMOVDQA32/64 4-62 PAGE 1182 LINE 61673
:VMOVDQA YmmReg2_m256, YmmReg1 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0x7F; YmmReg1 ... & YmmReg2_m256
{
YmmReg2_m256 = YmmReg1;
# TODO ZmmReg2 = zext(YmmReg2)
}
# MOVSD 4-111 PAGE 1231 LINE 63970
:VMOVSD XmmReg1, vexVVVV_XmmReg, XmmReg2 is $(VEX_NDS) & $(VEX_LIG) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x10; XmmReg1 & YmmReg1 & (mod=0x3 & XmmReg2)
{
local tmpa:8 = XmmReg2[0,64];
local tmpb:8 = vexVVVV_XmmReg[64,64];
YmmReg1 = 0;
XmmReg1[0,64] = tmpa;
XmmReg1[64,64] = tmpb;
# TODO ZmmReg1 = zext(XmmReg1)
}
# MOVSD 4-111 PAGE 1231 LINE 63972
:VMOVSD XmmReg1, m64 is $(VEX_NONE) & $(VEX_LIG) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_WIG); byte=0x10; (XmmReg1 & YmmReg1) ... & m64
{
YmmReg1[0,64] = m64;
YmmReg1[64,64] = 0;
# TODO ZmmReg1 = zext(XmmReg1)
}
# MOVSD 4-111 PAGE 1231 LINE 63974
:VMOVSD XmmReg2, vexVVVV_XmmReg, XmmReg1 is $(VEX_NDS) & $(VEX_LIG) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x11; XmmReg1 & (mod=0x3 & (XmmReg2 & YmmReg2))
{
local tmpa:8 = XmmReg1[0,64];
local tmpb:8 = vexVVVV_XmmReg[64,64];
YmmReg2 = 0;
XmmReg2[0,64] = tmpa;
XmmReg2[64,64] = tmpb;
# TODO ZmmReg2 = zext(XmmReg2)
}
# MOVSD 4-111 PAGE 1231 LINE 63976
:VMOVSD m64, XmmReg1 is $(VEX_NONE) & $(VEX_LIG) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_WIG); byte=0x11; XmmReg1 ... & m64
{
m64 = XmmReg1[0,64];
}
# MOVUPS 4-130 PAGE 1250 LINE 64872
:VMOVUPS XmmReg1, XmmReg2_m128 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x10; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = XmmReg2_m128;
YmmReg1[0,128] = tmp;
YmmReg1[128,64] = 0;
YmmReg1[192,64] = 0;
}
# MOVUPS 4-130 PAGE 1250 LINE 64874
# break this into two constructors to handle the zext for the register destination case
:VMOVUPS XmmReg2, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x11; XmmReg1 & (mod = 3 & XmmReg2 & YmmReg2)
{
XmmReg2 = XmmReg1;
YmmReg2 = zext(XmmReg2);
}
# MOVUPS 4-130 PAGE 1250 LINE 64874
:VMOVUPS m128, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x11; XmmReg1 ... & m128
{
m128 = XmmReg1;
}
# MOVUPS 4-130 PAGE 1250 LINE 64876
:VMOVUPS YmmReg1, YmmReg2_m256 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x10; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = YmmReg2_m256;
# TODO ZmmReg1 = zext(YmmReg1)
}
# MOVUPS 4-130 PAGE 1250 LINE 64878
# TODO in general, what do we do with the zext of only the register case; needs investigation
:VMOVUPS YmmReg2_m256, YmmReg1 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x11; YmmReg1 ... & YmmReg2_m256
{
YmmReg2_m256 = YmmReg1;
}
# PCMPEQQ 4-250 PAGE 1370 LINE 71169
:VPCMPEQQ XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x29; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
XmmReg1[0,64] = zext(vexVVVV_XmmReg[0,64] == XmmReg2_m128[0,64]) * 0xffffffffffffffff:8;
XmmReg1[64,64] = zext(vexVVVV_XmmReg[64,64] == XmmReg2_m128[64,64]) * 0xffffffffffffffff:8;
YmmReg1 = zext(XmmReg1);
# TODO ZmmReg1 = zext(XmmReg1)
}
# PMOVMSKB 4-338 PAGE 1458 LINE 75651
:VPMOVMSKB Reg32, XmmReg2 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xD7; Reg32 & (mod=0x3 & XmmReg2) & check_Reg32_dest
{
local byte_mask:2 = 0:2;
byte_mask[0,1] = XmmReg2[7,1];
byte_mask[1,1] = XmmReg2[15,1];
byte_mask[2,1] = XmmReg2[23,1];
byte_mask[3,1] = XmmReg2[31,1];
byte_mask[4,1] = XmmReg2[39,1];
byte_mask[5,1] = XmmReg2[47,1];
byte_mask[6,1] = XmmReg2[55,1];
byte_mask[7,1] = XmmReg2[63,1];
byte_mask[8,1] = XmmReg2[71,1];
byte_mask[9,1] = XmmReg2[79,1];
byte_mask[10,1] = XmmReg2[87,1];
byte_mask[11,1] = XmmReg2[95,1];
byte_mask[12,1] = XmmReg2[103,1];
byte_mask[13,1] = XmmReg2[111,1];
byte_mask[14,1] = XmmReg2[119,1];
byte_mask[15,1] = XmmReg2[127,1];
Reg32 = zext(byte_mask);
build check_Reg32_dest;
}
# VZEROALL 5-563 PAGE 2387 LINE 122405
:VZEROALL is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x77
{
YMM0[0,64] = 0:8; YMM0[64,64] = 0:8; YMM0[128,64] = 0:8; YMM0[192,64] = 0:8;
YMM1[0,64] = 0:8; YMM1[64,64] = 0:8; YMM1[128,64] = 0:8; YMM1[192,64] = 0:8;
YMM2[0,64] = 0:8; YMM2[64,64] = 0:8; YMM2[128,64] = 0:8; YMM2[192,64] = 0:8;
YMM3[0,64] = 0:8; YMM3[64,64] = 0:8; YMM3[128,64] = 0:8; YMM3[192,64] = 0:8;
YMM4[0,64] = 0:8; YMM4[64,64] = 0:8; YMM4[128,64] = 0:8; YMM4[192,64] = 0:8;
YMM5[0,64] = 0:8; YMM5[64,64] = 0:8; YMM5[128,64] = 0:8; YMM5[192,64] = 0:8;
YMM6[0,64] = 0:8; YMM6[64,64] = 0:8; YMM6[128,64] = 0:8; YMM6[192,64] = 0:8;
YMM7[0,64] = 0:8; YMM7[64,64] = 0:8; YMM7[128,64] = 0:8; YMM7[192,64] = 0:8;
#TODO: Zmm
}
@ifdef IA64
:VZEROALL is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x77
{
YMM0[0,64] = 0:8; YMM0[64,64] = 0:8; YMM0[128,64] = 0:8; YMM0[192,64] = 0:8;
YMM1[0,64] = 0:8; YMM1[64,64] = 0:8; YMM1[128,64] = 0:8; YMM1[192,64] = 0:8;
YMM2[0,64] = 0:8; YMM2[64,64] = 0:8; YMM2[128,64] = 0:8; YMM2[192,64] = 0:8;
YMM3[0,64] = 0:8; YMM3[64,64] = 0:8; YMM3[128,64] = 0:8; YMM3[192,64] = 0:8;
YMM4[0,64] = 0:8; YMM4[64,64] = 0:8; YMM4[128,64] = 0:8; YMM4[192,64] = 0:8;
YMM5[0,64] = 0:8; YMM5[64,64] = 0:8; YMM5[128,64] = 0:8; YMM5[192,64] = 0:8;
YMM6[0,64] = 0:8; YMM6[64,64] = 0:8; YMM6[128,64] = 0:8; YMM6[192,64] = 0:8;
YMM7[0,64] = 0:8; YMM7[64,64] = 0:8; YMM7[128,64] = 0:8; YMM7[192,64] = 0:8;
YMM8[0,64] = 0:8; YMM8[64,64] = 0:8; YMM8[128,64] = 0:8; YMM8[192,64] = 0:8;
YMM9[0,64] = 0:8; YMM9[64,64] = 0:8; YMM9[128,64] = 0:8; YMM9[192,64] = 0:8;
YMM10[0,64] = 0:8; YMM10[64,64] = 0:8; YMM10[128,64] = 0:8; YMM10[192,64] = 0:8;
YMM11[0,64] = 0:8; YMM11[64,64] = 0:8; YMM11[128,64] = 0:8; YMM11[192,64] = 0:8;
YMM12[0,64] = 0:8; YMM12[64,64] = 0:8; YMM12[128,64] = 0:8; YMM12[192,64] = 0:8;
YMM13[0,64] = 0:8; YMM13[64,64] = 0:8; YMM13[128,64] = 0:8; YMM13[192,64] = 0:8;
YMM14[0,64] = 0:8; YMM14[64,64] = 0:8; YMM14[128,64] = 0:8; YMM14[192,64] = 0:8;
YMM15[0,64] = 0:8; YMM15[64,64] = 0:8; YMM15[128,64] = 0:8; YMM15[192,64] = 0:8;
#TODO: Zmm
}
@endif
# VZEROUPPER 5-565 PAGE 2389 LINE 122480
:VZEROUPPER is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x77
{
YMM0[128,64] = 0:8; YMM0[192,64] = 0:8;
YMM1[128,64] = 0:8; YMM1[192,64] = 0:8;
YMM2[128,64] = 0:8; YMM2[192,64] = 0:8;
YMM3[128,64] = 0:8; YMM3[192,64] = 0:8;
YMM4[128,64] = 0:8; YMM4[192,64] = 0:8;
YMM5[128,64] = 0:8; YMM5[192,64] = 0:8;
YMM6[128,64] = 0:8; YMM6[192,64] = 0:8;
YMM7[128,64] = 0:8; YMM7[192,64] = 0:8;
#TODO: Zmm
}
@ifdef IA64
:VZEROUPPER is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_WIG); byte=0x77
{
YMM0[128,64] = 0:8; YMM0[192,64] = 0:8;
YMM1[128,64] = 0:8; YMM1[192,64] = 0:8;
YMM2[128,64] = 0:8; YMM2[192,64] = 0:8;
YMM3[128,64] = 0:8; YMM3[192,64] = 0:8;
YMM4[128,64] = 0:8; YMM4[192,64] = 0:8;
YMM5[128,64] = 0:8; YMM5[192,64] = 0:8;
YMM6[128,64] = 0:8; YMM6[192,64] = 0:8;
YMM7[128,64] = 0:8; YMM7[192,64] = 0:8;
YMM8[128,64] = 0:8; YMM8[192,64] = 0:8;
YMM9[128,64] = 0:8; YMM9[192,64] = 0:8;
YMM10[128,64] = 0:8; YMM10[192,64] = 0:8;
YMM11[128,64] = 0:8; YMM11[192,64] = 0:8;
YMM12[128,64] = 0:8; YMM12[192,64] = 0:8;
YMM13[128,64] = 0:8; YMM13[192,64] = 0:8;
YMM14[128,64] = 0:8; YMM14[192,64] = 0:8;
YMM15[128,64] = 0:8; YMM15[192,64] = 0:8;
#TODO: Zmm
}
@endif

View File

@@ -0,0 +1,195 @@
macro tzcntflags(input, output) {
ZF = (output == 0);
CF = (input == 0);
# OF, SF, PF, AF are undefined
}
####
#### BMI1 instructions
####
# TODO remove ANDN from ia.sinc ?????
:ANDN Reg32, vexVVVV_r32, rm32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf2; Reg32 ... & check_Reg32_dest ... &rm32
{
Reg32 = ~(vexVVVV_r32) & rm32;
resultflags(Reg32);
OF = 0;
CF = 0;
build check_Reg32_dest;
}
@ifdef IA64
# TODO remove ANDN from ia.sinc ?????
:ANDN Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf2; Reg64 ... & rm64
{
Reg64 = ~(vexVVVV_r64) & rm64;
resultflags(Reg64);
OF = 0;
CF = 0;
}
@endif
:BEXTR Reg32, rm32, vexVVVV_r32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf7; Reg32 ... & check_Reg32_dest ... & rm32
{
sourceTmp:1 = vexVVVV_r32[0,8];
lengthTmp:1 = vexVVVV_r32[8,8];
Reg32 = (rm32 >> sourceTmp) & ((1 << lengthTmp) - 1);
build check_Reg32_dest;
ZF = (Reg32 == 0);
OF = 0;
CF = 0;
# AF, SF, and PF are undefined
}
@ifdef IA64
:BEXTR Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
sourceTmp:1 = vexVVVV_r64[0,8];
lengthTmp:1 = vexVVVV_r64[8,8];
Reg64 = (rm64 >> sourceTmp) & ((1 << lengthTmp) - 1);
ZF = (Reg64 == 0);
OF = 0;
CF = 0;
# AF, SF, and PF are undefined
}
@endif
:BLSI vexVVVV_r32, rm32 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf3; reg_opcode=3 ... & check_vexVVVV_r32_dest ... & rm32
{
vexVVVV_r32 = -rm32 & rm32;
build check_vexVVVV_r32_dest;
ZF = (vexVVVV_r32 == 0);
SF = (vexVVVV_r32 s< 0);
CF = (rm32 != 0);
OF = 0;
# AF and PF are undefined
}
@ifdef IA64
:BLSI vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=3 ... & rm64
{
vexVVVV_r64 = -rm64 & rm64;
ZF = (vexVVVV_r64 == 0);
SF = (vexVVVV_r64 s< 0);
CF = (rm64 != 0);
OF = 0;
# AF and PF are undefined
}
@endif
:BLSMSK vexVVVV_r32, rm32 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf3; reg_opcode=2 ... & check_vexVVVV_r32_dest ... &rm32
{
CF = (rm32 == 0);
vexVVVV_r32 = (rm32 - 1) ^ rm32;
SF = (vexVVVV_r32 s< 0);
build check_vexVVVV_r32_dest;
ZF = 0;
OF = 0;
# AF and PF are undefined
}
@ifdef IA64
:BLSMSK vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=2 ... & rm64
{
CF = (rm64 == 0);
vexVVVV_r64 = (rm64 - 1) ^ rm64;
SF = (vexVVVV_r64 s< 0);
ZF = 0;
OF = 0;
# AF and PF are undefined
}
@endif
:BLSR vexVVVV_r32, rm32 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf3; reg_opcode=1 ... & check_vexVVVV_r32_dest ... &rm32
{
CF = (rm32 == 0);
vexVVVV_r32 = (rm32 - 1) & rm32;
build check_vexVVVV_r32_dest;
ZF = (vexVVVV_r32 == 0);
SF = (vexVVVV_r32 s< 0);
OF = 0;
# AF and PF are undefined
}
@ifdef IA64
:BLSR vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=1 ... & rm64
{
CF = (rm64 == 0);
vexVVVV_r64 = (rm64 - 1) & rm64;
ZF = (vexVVVV_r64 == 0);
SF = (vexVVVV_r64 s< 0);
OF = 0;
# AF and PF are undefined
}
@endif
# not as documented in manual; requires PRE_66 prefix to get 16-bit operation
:TZCNT Reg16, rm16 is vexMode=0 & opsize=0 & $(PRE_66) & $(PRE_F3) & byte=0x0F; byte=0xBC; Reg16 ... & rm16 {
countTmp:2 = 0;
inputTmp:2 = rm16;
<loopbegin>
if ((inputTmp & 1) != 0) goto <loopend>;
countTmp = countTmp + 1;
inputTmp = (inputTmp >> 1) | 0x8000;
goto <loopbegin>;
<loopend>
tzcntflags(rm16, countTmp);
Reg16 = countTmp;
}
:TZCNT Reg32, rm32 is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x0F; byte=0xBC; Reg32 ... & check_Reg32_dest ... & rm32 {
countTmp:4 = 0;
inputTmp:4 = rm32;
<loopbegin>
if ((inputTmp & 1) != 0) goto <loopend>;
countTmp = countTmp + 1;
inputTmp = (inputTmp >> 1) | 0x80000000;
goto <loopbegin>;
<loopend>
tzcntflags(rm32, countTmp);
Reg32 = countTmp;
build check_Reg32_dest;
}
@ifdef IA64
:TZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBC; Reg64 ... & rm64 {
countTmp:8 = 0;
inputTmp:8 = rm64;
<loopbegin>
if ((inputTmp & 1) != 0) goto <loopend>;
countTmp = countTmp + 1;
inputTmp = (inputTmp >> 1) | 0x8000000000000000;
goto <loopbegin>;
<loopend>
tzcntflags(rm64, countTmp);
Reg64 = countTmp;
}
@endif

View File

@@ -0,0 +1,209 @@
####
#### BMI2 instructions
####
:BZHI Reg32, rm32, vexVVVV_r32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf5; Reg32 ... & check_Reg32_dest ... & rm32
{
indexTmp:1 = vexVVVV_r32:1;
# saturate index amount to 32; operand size or higher does not clear any bits
shift:1 = (indexTmp <= 32) * (32 - indexTmp);
# clear the upper bits
Reg32 = (rm32 << shift) >> shift;
build check_Reg32_dest;
ZF = (Reg32 == 0);
SF = (Reg32 s< 0);
CF = indexTmp > 31;
OF = 0;
# AF and PF are undefined
}
@ifdef IA64
:BZHI Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
{
indexTmp:1 = vexVVVV_r64:1;
# saturate index amount to 64; operand size or higher does not clear any bits
shift:1 = (indexTmp <= 64) * (64 - indexTmp);
# clear the upper bits
Reg64 = (rm64 << shift) >> shift;
ZF = (Reg64 == 0);
SF = (Reg64 s< 0);
CF = indexTmp > 63;
OF = 0;
# AF and PF are undefined
}
@endif
:MULX Reg32, vexVVVV_r32, rm32 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf6; Reg32 ... & check_Reg32_dest ... & check_vexVVVV_r32_dest ... & rm32
{
temp:8 = zext(EDX) * zext(rm32);
vexVVVV_r32 = temp:4;
build check_vexVVVV_r32_dest;
Reg32 = temp(4);
build check_Reg32_dest;
}
@ifdef IA64
:MULX Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf6; Reg64 ... & rm64
{
temp:16 = zext(RDX) * zext(rm64);
vexVVVV_r64 = temp:8;
Reg64 = temp(8);
}
@endif
:PDEP Reg32, vexVVVV_r32, rm32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf5; Reg32 ... & check_Reg32_dest ... & rm32
{
sourceTmp:4 = vexVVVV_r32;
indexTmp:4 = 1;
resultTmp:4 = 0;
<loop>
maskBit:4 = rm32 & indexTmp;
if (maskBit == 0) goto <nextMaskBit>;
resultTmp = resultTmp | (maskBit * (sourceTmp & 1));
sourceTmp = sourceTmp >> 1;
<nextMaskBit>
indexTmp = indexTmp << 1;
if (indexTmp != 0) goto <loop>;
Reg32 = resultTmp;
build check_Reg32_dest;
}
@ifdef IA64
:PDEP Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
{
sourceTmp:8 = vexVVVV_r64;
indexTmp:8 = 1;
resultTmp:8 = 0;
<loop>
maskBit:8 = rm64 & indexTmp;
if (maskBit == 0) goto <nextMaskBit>;
resultTmp = resultTmp | (maskBit * (sourceTmp & 1));
sourceTmp = sourceTmp >> 1;
<nextMaskBit>
indexTmp = indexTmp << 1;
if (indexTmp != 0) goto <loop>;
Reg64 = resultTmp;
}
@endif
:PEXT Reg32, vexVVVV_r32, rm32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf5; Reg32 ... & check_Reg32_dest ... & rm32
{
indexTmp:4 = 0x80000000;
resultTmp:4 = 0;
<loop>
maskBit:4 = rm32 & indexTmp;
if (maskBit == 0) goto <nextMaskBit>;
resultTmp = (resultTmp << 1) | zext((maskBit & vexVVVV_r32) != 0);
<nextMaskBit>
indexTmp = indexTmp >> 1;
if (indexTmp != 0) goto <loop>;
build check_Reg32_dest;
Reg32 = resultTmp;
}
@ifdef IA64
:PEXT Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
{
indexTmp:8 = 0x8000000000000000;
resultTmp:8 = 0;
<loop>
maskBit:8 = rm64 & indexTmp;
if (maskBit == 0) goto <nextMaskBit>;
resultTmp = (resultTmp << 1) | zext((maskBit & vexVVVV_r64) != 0);
<nextMaskBit>
indexTmp = indexTmp >> 1;
if (indexTmp != 0) goto <loop>;
Reg64 = resultTmp;
}
@endif
:RORX Reg32, rm32, imm8 is $(VEX_NONE) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F3A) & $(VEX_W0); byte=0xf0; Reg32 ... & check_Reg32_dest ... & rm32; imm8
{
shiftTmp:1 = (imm8:1 & 0x1F);
Reg32 = (rm32 >> shiftTmp) | ( rm32 << (32 - shiftTmp));
build check_Reg32_dest;
}
@ifdef IA64
:RORX Reg64, rm64, imm8 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F3A) & $(VEX_W1); byte=0xf0; Reg64 ... & rm64; imm8
{
shiftTmp:1 = (imm8:1 & 0x3F);
Reg64 = (rm64 >> shiftTmp) | ( rm64 << (64 - shiftTmp));
}
@endif
:SARX Reg32, rm32, vexVVVV_r32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf7; Reg32 ... & check_Reg32_dest ... & rm32
{
Reg32 = rm32 s>> (vexVVVV_r32 & 0x0000001F);
build check_Reg32_dest;
}
@ifdef IA64
:SARX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
Reg64 = rm64 s>> (vexVVVV_r64 & 0x000000000000003F);
}
@endif
:SHLX Reg32, rm32, vexVVVV_r32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf7; Reg32 ... & check_Reg32_dest ... & rm32
{
Reg32 = rm32 << (vexVVVV_r32 & 0x0000001F);
build check_Reg32_dest;
}
@ifdef IA64
:SHLX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
Reg64 = rm64 << (vexVVVV_r64 & 0x000000000000003F);
}
@endif
:SHRX Reg32, rm32, vexVVVV_r32 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32; byte=0xf7; Reg32 ... & check_Reg32_dest ... & rm32
{
Reg32 = rm32 >> (vexVVVV_r32 & 0x0000001F);
build check_Reg32_dest;
}
@ifdef IA64
:SHRX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
{
Reg64 = rm64 >> (vexVVVV_r64 & 0x000000000000003F);
}
@endif

View File

@@ -0,0 +1,84 @@
#
# Instructions based on Intel Control-flow Enforcement Technology Preview
#
# Note: Shadow Stack semantics is not currently implemented correctly in these instructions
# nor in the instructions affected by CET
#
define pcodeop ShadowStackPush8B;
define pcodeop ShadowStackPush4B;
define pcodeop ShadowStackLoad8B;
define pcodeop ShadowStackLoad4B;
:INCSSPD r32 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0xae; reg_opcode=5 & r32 {
SSP = SSP + zext(4 * r32:1);
}
@ifdef IA64
:INCSSPQ r64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0xae; reg_opcode=5 & r64 {
SSP = SSP + zext(8 * r64:1);
}
@endif
:RDSSPD r32 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; mod=3 & reg_opcode=1 & r32 {
r32 = SSP:4;
}
@ifdef IA64
:RDSSPQ r64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0x1e; mod=3 & reg_opcode=1 & r64 {
r64 = SSP;
}
@endif
:SAVEPREVSSP is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x01; byte=0xea {
tmp:8 = SSP;
SSP = SSP & ~0x7;
ShadowStackPush8B(tmp);
}
:RSTORSSP m64 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x01; ( mod != 0b11 & reg_opcode=5 ) ... & m64 {
tmp_SSP:8 = m64;
SSP = tmp_SSP & ~0x01;
}
define pcodeop writeToShadowStack;
define pcodeop writeToUserShadowStack;
:WRSSD rm32,Reg32 is vexMode=0 & byte=0x0f; byte=0x38; byte=0xf6; rm32 & Reg32 ... {
writeToShadowStack(rm32, Reg32);
}
@ifdef IA64
:WRSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
writeToShadowStack(rm64, Reg64);
}
@endif
:WRUSSD rm32,Reg32 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0xf5; rm32 & Reg32 ... {
writeToUserShadowStack(rm32, Reg32);
}
@ifdef IA64
:WRUSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
writeToUserShadowStack(rm64, Reg64);
}
@endif
define pcodeop markShadowStackBusy;
define pcodeop clearShadowStackBusy;
:SETSSBSY is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x01; byte=0xe8 {
SSP = markShadowStackBusy(IA32_PL0_SSP);
}
:CLRSSBSY m64 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0xae; reg_opcode=6 ... & m64 {
clearShadowStackBusy(m64);
SSP=0;
}
:ENDBR32 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfb {}
@ifdef IA64
:ENDBR64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfa {}
@endif

View File

@@ -0,0 +1,14 @@
define pcodeop clwb;
:CLWB m8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=6 ... {
clwb(m8);
}
@ifdef IA64
define pcodeop clflushopt;
:CLFLUSHOPT m8 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=7 ... {
clflushopt(m8);
}
@endif
# Note: PCOMMIT was deprecated prior to it ever being implemented in production processors.
# I never found the encoding for it. Therefore, no constructor.

View File

@@ -0,0 +1,800 @@
#
# x86 FMA instructions
#
# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101211
define pcodeop vfmadd132pd_fma ;
:VFMADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x98; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmadd132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101214
define pcodeop vfmadd213pd_fma ;
:VFMADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA8; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmadd213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101217
define pcodeop vfmadd231pd_fma ;
:VFMADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB8; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmadd231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101220
:VFMADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x98; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmadd132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101223
:VFMADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA8; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmadd213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101226
:VFMADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB8; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmadd231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101572
define pcodeop vfmadd132ps_fma ;
:VFMADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x98; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmadd132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101575
define pcodeop vfmadd213ps_fma ;
:VFMADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA8; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmadd213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101578
define pcodeop vfmadd231ps_fma ;
:VFMADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB8; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmadd231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101581
:VFMADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x98; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmadd132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101584
:VFMADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA8; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmadd213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101587
# WARNING: did not recognize VEX field 0 for "VFMADD231PS ymm1, ymm2, ymm3/m256"
:VFMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xB8; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMADD132PS/VFMADD213PS/VFMADD231PS 5-134 PAGE 1958 LINE 101931
define pcodeop vfmadd132sd_fma ;
:VFMADD132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x99; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfmadd132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132PS/VFMADD213PS/VFMADD231PS 5-134 PAGE 1958 LINE 101934
define pcodeop vfmadd213sd_fma ;
:VFMADD213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA9; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfmadd213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132PS/VFMADD213PS/VFMADD231PS 5-134 PAGE 1958 LINE 101937
define pcodeop vfmadd231sd_fma ;
:VFMADD231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB9; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfmadd231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-137 PAGE 1961 LINE 102099
define pcodeop vfmadd132ss_fma ;
:VFMADD132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x99; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfmadd132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-137 PAGE 1961 LINE 102102
define pcodeop vfmadd213ss_fma ;
:VFMADD213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA9; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfmadd213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-137 PAGE 1961 LINE 102105
define pcodeop vfmadd231ss_fma ;
:VFMADD231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB9; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfmadd231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102272
define pcodeop vfmaddsub132pd_fma ;
:VFMADDSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x96; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmaddsub132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102275
define pcodeop vfmaddsub213pd_fma ;
:VFMADDSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA6; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmaddsub213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102278
define pcodeop vfmaddsub231pd_fma ;
:VFMADDSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB6; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmaddsub231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102281
:VFMADDSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x96; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmaddsub132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102284
:VFMADDSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA6; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmaddsub213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102287
:VFMADDSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB6; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmaddsub231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102711
define pcodeop vfmaddsub132ps_fma ;
:VFMADDSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x96; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmaddsub132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102714
define pcodeop vfmaddsub213ps_fma ;
:VFMADDSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA6; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmaddsub213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102717
define pcodeop vfmaddsub231ps_fma ;
:VFMADDSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB6; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmaddsub231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102720
:VFMADDSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x96; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmaddsub132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102723
:VFMADDSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA6; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmaddsub213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102726
:VFMADDSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB6; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmaddsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103141
define pcodeop vfmsubadd132pd_fma ;
:VFMSUBADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x97; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsubadd132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103144
define pcodeop vfmsubadd213pd_fma ;
:VFMSUBADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA7; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsubadd213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103147
define pcodeop vfmsubadd231pd_fma ;
:VFMSUBADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB7; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsubadd231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103150
:VFMSUBADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x97; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsubadd132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103153
:VFMSUBADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA7; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsubadd213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103156
:VFMSUBADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB7; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsubadd231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103581
define pcodeop vfmsubadd132ps_fma ;
:VFMSUBADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x97; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsubadd132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103584
define pcodeop vfmsubadd213ps_fma ;
:VFMSUBADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA7; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsubadd213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103587
define pcodeop vfmsubadd231ps_fma ;
:VFMSUBADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB7; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsubadd231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103590
:VFMSUBADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x97; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsubadd132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103593
:VFMSUBADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA7; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsubadd213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103596
:VFMSUBADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB7; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsubadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104019
define pcodeop vfmsub132pd_fma ;
:VFMSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9A; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsub132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104022
define pcodeop vfmsub213pd_fma ;
:VFMSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAA; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsub213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104025
define pcodeop vfmsub231pd_fma ;
:VFMSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBA; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsub231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104028
:VFMSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9A; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsub132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104031
:VFMSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAA; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsub213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104034
:VFMSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBA; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsub231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104379
define pcodeop vfmsub132ps_fma ;
:VFMSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9A; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsub132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104382
define pcodeop vfmsub213ps_fma ;
:VFMSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAA; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsub213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104385
define pcodeop vfmsub231ps_fma ;
:VFMSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBA; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfmsub231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104388
:VFMSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9A; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsub132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104391
:VFMSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAA; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsub213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104394
# WARNING: did not recognize VEX field 0 for "VFMSUB231PS ymm1, ymm2, ymm3/m256"
:VFMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xBA; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfmsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD 5-193 PAGE 2017 LINE 104738
define pcodeop vfmsub132sd_fma ;
:VFMSUB132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9B; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfmsub132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD 5-193 PAGE 2017 LINE 104741
define pcodeop vfmsub213sd_fma ;
:VFMSUB213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAB; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfmsub213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD 5-193 PAGE 2017 LINE 104744
define pcodeop vfmsub231sd_fma ;
:VFMSUB231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBB; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfmsub231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS 5-196 PAGE 2020 LINE 104913
define pcodeop vfmsub132ss_fma ;
:VFMSUB132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9B; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfmsub132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS 5-196 PAGE 2020 LINE 104916
define pcodeop vfmsub213ss_fma ;
:VFMSUB213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAB; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfmsub213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS 5-196 PAGE 2020 LINE 104919
define pcodeop vfmsub231ss_fma ;
:VFMSUB231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBB; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfmsub231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105088
define pcodeop vfnmadd132pd_fma ;
:VFNMADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9C; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmadd132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105091
define pcodeop vfnmadd213pd_fma ;
:VFNMADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmadd213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105094
define pcodeop vfnmadd231pd_fma ;
:VFNMADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmadd231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105097
:VFNMADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9C; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmadd132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105100
:VFNMADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAC; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmadd213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105103
:VFNMADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBC; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmadd231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105447
define pcodeop vfnmadd132ps_fma ;
:VFNMADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9C; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmadd132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105450
define pcodeop vfnmadd213ps_fma ;
:VFNMADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmadd213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105453
define pcodeop vfnmadd231ps_fma ;
:VFNMADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmadd231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105456
:VFNMADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9C; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmadd132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105459
:VFNMADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAC; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmadd213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105462
# WARNING: did not recognize VEX field 0 for "VFNMADD231PS ymm1, ymm2, ymm3/m256"
:VFNMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xBC; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD 5-212 PAGE 2036 LINE 105794
define pcodeop vfnmadd132sd_fma ;
:VFNMADD132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9D; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfnmadd132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD 5-212 PAGE 2036 LINE 105797
define pcodeop vfnmadd213sd_fma ;
:VFNMADD213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAD; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfnmadd213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD 5-212 PAGE 2036 LINE 105800
define pcodeop vfnmadd231sd_fma ;
:VFNMADD231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBD; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfnmadd231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS 5-215 PAGE 2039 LINE 105966
define pcodeop vfnmadd132ss_fma ;
:VFNMADD132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9D; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfnmadd132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS 5-215 PAGE 2039 LINE 105969
define pcodeop vfnmadd213ss_fma ;
:VFNMADD213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAD; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfnmadd213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS 5-215 PAGE 2039 LINE 105972
define pcodeop vfnmadd231ss_fma ;
:VFNMADD231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBD; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfnmadd231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106138
define pcodeop vfnmsub132pd_fma ;
:VFNMSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9E; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmsub132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106141
define pcodeop vfnmsub213pd_fma ;
:VFNMSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAE; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmsub213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106144
define pcodeop vfnmsub231pd_fma ;
:VFNMSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBE; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmsub231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106147
:VFNMSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9E; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmsub132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106150
:VFNMSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAE; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmsub213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106153
:VFNMSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBE; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmsub231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106487
define pcodeop vfnmsub132ps_fma ;
:VFNMSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9E; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmsub132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106490
define pcodeop vfnmsub213ps_fma ;
:VFNMSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAE; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmsub213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106493
define pcodeop vfnmsub231ps_fma ;
:VFNMSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBE; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
local tmp:16 = vfnmsub231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106496
:VFNMSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9E; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmsub132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106499
:VFNMSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAE; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmsub213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106502
# WARNING: did not recognize VEX field 0 for "VFNMSUB231PS ymm1, ymm2, ymm3/m256"
:VFNMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xBE; YmmReg1 ... & YmmReg2_m256
{
YmmReg1 = vfnmsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
# TODO ZmmReg1 = zext(YmmReg1)
}
# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD 5-230 PAGE 2054 LINE 106832
define pcodeop vfnmsub132sd_fma ;
:VFNMSUB132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9F; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfnmsub132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD 5-230 PAGE 2054 LINE 106835
define pcodeop vfnmsub213sd_fma ;
:VFNMSUB213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAF; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfnmsub213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD 5-230 PAGE 2054 LINE 106838
define pcodeop vfnmsub231sd_fma ;
:VFNMSUB231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBF; (XmmReg1 & YmmReg1) ... & XmmReg2_m64
{
local tmp:16 = vfnmsub231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS 5-233 PAGE 2057 LINE 107004
define pcodeop vfnmsub132ss_fma ;
:VFNMSUB132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9F; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfnmsub132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS 5-233 PAGE 2057 LINE 107007
define pcodeop vfnmsub213ss_fma ;
:VFNMSUB213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAF; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfnmsub213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}
# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS 5-233 PAGE 2057 LINE 107010
define pcodeop vfnmsub231ss_fma ;
:VFNMSUB231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBF; (XmmReg1 & YmmReg1) ... & XmmReg2_m32
{
local tmp:16 = vfnmsub231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 );
YmmReg1 = zext(tmp);
# TODO ZmmReg1 = zext(XmmReg1)
}

View File

@@ -0,0 +1,32 @@
macro lzcntflags(input, output) {
ZF = (output == 0);
CF = (input == 0);
# OF, SF, PF, AF are undefined
}
####
#### LZCNT instructions
####
:LZCNT Reg16, rm16 is vexMode=0 & opsize=0 & $(PRE_66) & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg16 ... & rm16 {
Reg16 = lzcount(rm16);
lzcntflags(rm16, Reg16);
}
:LZCNT Reg32, rm32 is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg32 ... & check_Reg32_dest ... & rm32 {
Reg32 = lzcount(rm32);
lzcntflags(rm32, Reg32);
build check_Reg32_dest;
}
@ifdef IA64
:LZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
Reg64 = lzcount(rm64);
lzcntflags(rm64, Reg64);
}
@endif

View File

@@ -0,0 +1,3 @@
macro conditionalAssign(dest, cond, trueVal, falseVal) {
dest = zext(cond) * trueVal | zext(!cond) * falseVal;
}

View File

@@ -0,0 +1,234 @@
define pcodeop br_exception;
# BNDMK needs the base address register only
# - if no base register, needs 0
@ifdef IA64
bndmk_addr64: [Rmr64] is mod=0 & Rmr64 { export Rmr64; }
bndmk_addr64: [Rmr64 + simm8_64] is mod=1 & Rmr64; simm8_64 { export Rmr64; }
bndmk_addr64: [simm32_64 + Rmr64] is mod=2 & Rmr64; simm32_64 { export Rmr64; }
bndmk_addr64: [Rmr64] is mod=1 & r_m!=4 & Rmr64; simm8=0 { export Rmr64; }
bndmk_addr64: [Rmr64] is mod=2 & r_m!=4 & Rmr64; simm32=0 { export Rmr64; }
#invalid bndmk_addr64: [riprel] is mod=0 & r_m=5; simm32 [ riprel=inst_next+simm32; ] { export *[const]:8 riprel; }
bndmk_addr64: [Base64 + Index64*ss] is mod=0 & r_m=4; Index64 & Base64 & ss { export Base64; }
bndmk_addr64: [Base64] is mod=0 & r_m=4; rexXprefix=0 & index64=4 & Base64 { export Base64; }
bndmk_addr64: [simm32_64 + Index64*ss] is mod=0 & r_m=4; Index64 & base64=5 & ss; simm32_64 { tmp:8 = 0; export tmp; }
bndmk_addr64: [Index64*ss] is mod=0 & r_m=4; Index64 & base64=5 & ss; imm32=0 { tmp:8 = 0; export tmp; }
bndmk_addr64: [simm32_64] is mod=0 & r_m=4; rexXprefix=0 & index64=4 & base64=5; simm32_64 { tmp:8 = 0; export tmp; }
bndmk_addr64: [Base64 + Index64*ss + simm8_64] is mod=1 & r_m=4; Index64 & Base64 & ss; simm8_64 { export Base64; }
bndmk_addr64: [Base64 + Index64*ss] is mod=1 & r_m=4; Index64 & Base64 & ss; simm8=0 { export Base64; }
bndmk_addr64: [Base64 + simm8_64] is mod=1 & r_m=4; rexXprefix=0 & index64=4 & Base64; simm8_64 { export Base64; }
bndmk_addr64: [simm32_64 + Base64 + Index64*ss] is mod=2 & r_m=4; Index64 & Base64 & ss; simm32_64 { export Base64; }
bndmk_addr64: [simm32_64 + Base64] is mod=2 & r_m=4; rexXprefix=0 & index64=4 & Base64; simm32_64 { export Base64; }
bndmk_addr64: [Base64 + Index64*ss] is mod=2 & r_m=4; Index64 & Base64 & ss; imm32=0 { export Base64; }
bndmk_addr64: [Base64] is mod=2 & r_m=4; rexXprefix=0 & index64=4 & Base64; imm32=0 { export Base64; }
@endif
bndmk_addr32: [Rmr32] is mod=0 & Rmr32 { export Rmr32; }
bndmk_addr32: [Rmr32 + simm8_32] is mod=1 & Rmr32; simm8_32 { export Rmr32; }
bndmk_addr32: [Rmr32] is mod=1 & r_m!=4 & Rmr32; simm8=0 { export Rmr32; }
bndmk_addr32: [imm32 + Rmr32] is mod=2 & Rmr32; imm32 { export Rmr32; }
bndmk_addr32: [Rmr32] is mod=2 & r_m!=4 & Rmr32; imm32=0 { export Rmr32; }
bndmk_addr32: [imm32] is mod=0 & r_m=5; imm32 { tmp:4 = 0; export tmp; }
bndmk_addr32: [Base + Index*ss] is mod=0 & r_m=4; Index & Base & ss { export Base; }
bndmk_addr32: [Base] is mod=0 & r_m=4; index=4 & Base { export Base; }
bndmk_addr32: [imm32 + Index*ss] is mod=0 & r_m=4; Index & base=5 & ss; imm32 { tmp:4 = 0; export tmp; }
bndmk_addr32: [imm32] is mod=0 & r_m=4; index=4 & base=5; imm32 { tmp:4 = 0; export tmp; }
bndmk_addr32: [Base + Index*ss + simm8_32] is mod=1 & r_m=4; Index & Base & ss; simm8_32 { export Base; }
bndmk_addr32: [Base + simm8_32] is mod=1 & r_m=4; index=4 & Base; simm8_32 { export Base; }
bndmk_addr32: [Base + Index*ss] is mod=1 & r_m=4; Index & Base & ss; simm8=0 { export Base; }
bndmk_addr32: [Base] is mod=1 & r_m=4; index=4 & Base; simm8=0 { export Base; }
bndmk_addr32: [imm32 + Base + Index*ss] is mod=2 & r_m=4; Index & Base & ss; imm32 { export Base; }
bndmk_addr32: [imm32 + Base] is mod=2 & r_m=4; index=4 & Base; imm32 { export Base; }
bndmk_addr32: [Base + Index*ss] is mod=2 & r_m=4; Index & Base & ss; imm32=0 { export Base; }
bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export Base; }
@ifdef IA64
:BNDCL bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr64 {
# if (reg < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Rmr64 < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCL bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
# if (LEA(mem) < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Mem < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCU bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr64 {
# if (reg > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Rmr64 > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCU bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Mem > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCN bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr64 {
# if (reg > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Rmr64 > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCN bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(Mem > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
#TODO: This probably cannot be fully modeled
:BNDLDX bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & byte=0x0F; byte=0x1A; bnd1 ... & Mem {
# BNDSTATUS = bndldx_status( Mem, BNDCFGS, BNDCFGU );
# bnd1 = bndldx( Mem, BNDCFGS, BNDCFGU );
# core implementation
bnd1 = *:16 Mem;
}
:BNDMK bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr64 & Mem ) {
# BND.LB and BND.UB set from m64
bnd1_lb = bndmk_addr64;
bnd1_ub = Mem;
}
:BNDMOV bnd1, m128 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; bnd1 ... & m128 {
bnd1 = m128;
}
:BNDMOV bnd1, bnd2 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
bnd1 = bnd2;
}
:BNDMOV m128, bnd1 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; bnd1 ... & m128 {
m128 = bnd1;
}
:BNDMOV bnd2, bnd1 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
bnd2 = bnd1;
}
#TODO: This probably cannot be fully modeled
:BNDSTX Mem, bnd1 is $(LONGMODE_ON) & vexMode=0 & byte=0x0F; byte=0x1B; bnd1 ... & Mem {
# BNDSTATUS = bndstx_status( bnd1, BNDCFGS, BNDCFGU );
# Mem = bndstx( bnd1, BNDCFGS, BNDCFGU );
# core implementation
*:16 Mem = bnd1;
}
@endif
:BNDCL bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr32 {
# if (reg < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Rmr32) < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCL bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
# if (LEA(mem) < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Mem) < bnd1_lb) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCU bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr32 {
# if (reg > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Rmr32) > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCU bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Mem) > ~bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCN bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr32 {
# if (reg > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Rmr32) > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
:BNDCN bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
# if (LEA(mem) > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
if !(zext(Mem) > bnd1_ub) goto <done>;
BNDSTATUS = 0x01;
br_exception();
<done>
}
#TODO: This probably cannot be fully modeled
:BNDLDX bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
# BNDSTATUS = bndldx_status( Mem, BNDCFGS, BNDCFGU );
# bnd1 = bndldx( Mem, BNDCFGS, BNDCFGU );
# core implementation
tmp:8 = *:8 Mem;
bnd1_lb = zext(tmp:4);
tmp2:4 = tmp(4);
bnd1_ub = zext(tmp2);
}
:BNDMK bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr32 & Mem ) {
# BND.LB and BND.UB set from m32
bnd1_lb = zext(bndmk_addr32);
bnd1_ub = zext(Mem);
}
:BNDMOV bnd1, m64 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
tmp:8 = m64;
bnd1_lb = zext(tmp:4);
tmp2:4 = tmp(4);
bnd1_ub = zext(tmp2);
}
:BNDMOV bnd1, bnd2 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
bnd1 = bnd2;
}
:BNDMOV m64, bnd1 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
m64 = (zext(bnd1_ub:4) << 32) | zext(bnd1_lb:4);
}
:BNDMOV bnd2, bnd1 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
bnd2 = bnd1;
}
#TODO: This probably cannot be fully modeled
:BNDSTX Mem, bnd1 is $(LONGMODE_OFF) & vexMode=0 & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
# BNDSTATUS = bndstx_status( bnd1, BNDCFGS, BNDCFGU );
# Mem = bndstx( bnd1, BNDCFGS, BNDCFGU );
# core implementation
*:8 Mem = (zext(bnd1_ub:4) << 32) | zext(bnd1_lb:4);
}

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<language version="1" endian="little">
<description>
<id>x86:LE:16:Real Mode</id>
<processor>x86</processor>
</description>
<compiler name="default" id="default"/>
<spaces>
<segmented_space name="ram" default="yes" />
<space name="register" type="register" size="4" />
</spaces>
<registers>
<context_register name="contextreg" offset="0x2000" bitsize="32">
<field name="lockprefx" range="8,8" />
<field name="repprefx" range="7,7" />
<field name="repneprefx" range="6,6" />
<field name="sstype" range="5,5" />
<field name="segover" range="2,4" />
<field name="opsize" range="1,1" />
<field name="addrsize" range="0,0" />
</context_register>
<register name="EAX" offset="0x0" bitsize="32" />
<register name="ECX" offset="0x4" bitsize="32" />
<register name="EDX" offset="0x8" bitsize="32" />
<register name="EBX" offset="0xc" bitsize="32" />
<register name="ESP" offset="0x10" bitsize="32" />
<register name="EBP" offset="0x14" bitsize="32" />
<register name="ESI" offset="0x18" bitsize="32" />
<register name="EDI" offset="0x1c" bitsize="32" />
<register name="AX" offset="0x0" bitsize="16" />
<register name="CX" offset="0x4" bitsize="16" />
<register name="DX" offset="0x8" bitsize="16" />
<register name="BX" offset="0xc" bitsize="16" />
<register name="SP" offset="0x10" bitsize="16" />
<register name="BP" offset="0x14" bitsize="16" />
<register name="SI" offset="0x18" bitsize="16" />
<register name="DI" offset="0x1c" bitsize="16" />
<register name="AL" offset="0x0" bitsize="8" />
<register name="AH" offset="0x1" bitsize="8" />
<register name="CL" offset="0x4" bitsize="8" />
<register name="CH" offset="0x5" bitsize="8" />
<register name="DL" offset="0x8" bitsize="8" />
<register name="DH" offset="0x9" bitsize="8" />
<register name="BL" offset="0xc" bitsize="8" />
<register name="BH" offset="0xd" bitsize="8" />
<register name="ES" offset="0x100" bitsize="16" />
<register name="CS" offset="0x102" bitsize="16" />
<register name="SS" offset="0x104" bitsize="16" />
<register name="DS" offset="0x106" bitsize="16" />
<register name="FS" offset="0x108" bitsize="16" />
<register name="GS" offset="0x10a" bitsize="16" />
<register name="FS_OFFSET" offset="0x110" bitsize="32" />
<register name="CF" offset="0x200" bitsize="8" />
<register name="F1" offset="0x201" bitsize="8" />
<register name="PF" offset="0x202" bitsize="8" />
<register name="F3" offset="0x203" bitsize="8" />
<register name="AF" offset="0x204" bitsize="8" />
<register name="F5" offset="0x205" bitsize="8" />
<register name="ZF" offset="0x206" bitsize="8" />
<register name="SF" offset="0x207" bitsize="8" />
<register name="TF" offset="0x208" bitsize="8" />
<register name="IF" offset="0x209" bitsize="8" />
<register name="DF" offset="0x20a" bitsize="8" />
<register name="OF" offset="0x20b" bitsize="8" />
<register name="IOPL" offset="0x20c" bitsize="8" />
<register name="NT" offset="0x20d" bitsize="8" />
<register name="F15" offset="0x20e" bitsize="8" />
<register name="RF" offset="0x20f" bitsize="8" />
<register name="VM" offset="0x210" bitsize="8" />
<register name="AC" offset="0x211" bitsize="8" />
<register name="VIF" offset="0x212" bitsize="8" />
<register name="VIP" offset="0x213" bitsize="8" />
<register name="ID" offset="0x214" bitsize="8" />
<register name="eflags" offset="0x280" bitsize="32" />
<register name="EIP" offset="0x284" bitsize="32" />
<register name="flags" offset="0x280" bitsize="16" />
<register name="IP" offset="0x284" bitsize="16" />
<register name="DR0" offset="0x300" bitsize="32" />
<register name="DR1" offset="0x304" bitsize="32" />
<register name="DR2" offset="0x308" bitsize="32" />
<register name="DR3" offset="0x30c" bitsize="32" />
<register name="DR4" offset="0x310" bitsize="32" />
<register name="DR5" offset="0x314" bitsize="32" />
<register name="DR6" offset="0x318" bitsize="32" />
<register name="DR7" offset="0x31c" bitsize="32" />
<register name="CR0" offset="0x320" bitsize="32" />
<register name="CR2" offset="0x328" bitsize="32" />
<register name="CR3" offset="0x32c" bitsize="32" />
<register name="CR4" offset="0x330" bitsize="32" />
<register name="TR0" offset="0x400" bitsize="32" />
<register name="TR1" offset="0x404" bitsize="32" />
<register name="TR2" offset="0x408" bitsize="32" />
<register name="TR3" offset="0x40c" bitsize="32" />
<register name="TR4" offset="0x410" bitsize="32" />
<register name="TR5" offset="0x414" bitsize="32" />
<register name="TR6" offset="0x418" bitsize="32" />
<register name="TR7" offset="0x41c" bitsize="32" />
<register name="ST0" offset="0x1000" bitsize="80" />
<register name="ST1" offset="0x100a" bitsize="80" />
<register name="ST2" offset="0x1014" bitsize="80" />
<register name="ST3" offset="0x101e" bitsize="80" />
<register name="ST4" offset="0x1028" bitsize="80" />
<register name="ST5" offset="0x1032" bitsize="80" />
<register name="ST6" offset="0x103c" bitsize="80" />
<register name="ST7" offset="0x1046" bitsize="80" />
<register name="FPUControlWord" offset="0x1090" bitsize="16" />
<register name="FPUStatusWord" offset="0x1092" bitsize="16" />
<register name="FPUTagWord" offset="0x1094" bitsize="16" />
<register name="FPUDataPointer" offset="0x1096" bitsize="16" />
<register name="FPUInstructionPointer" offset="0x1098" bitsize="16" />
<register name="FPULastInstructionOpcode" offset="0x109a" bitsize="16" />
<register name="MM0" offset="0x1100" bitsize="64" />
<register name="MM1" offset="0x1108" bitsize="64" />
<register name="MM2" offset="0x1110" bitsize="64" />
<register name="MM3" offset="0x1118" bitsize="64" />
<register name="MM4" offset="0x1120" bitsize="64" />
<register name="MM5" offset="0x1128" bitsize="64" />
<register name="MM6" offset="0x1130" bitsize="64" />
<register name="MM7" offset="0x1138" bitsize="64" />
<register name="XMM0" offset="0x1200" bitsize="128" />
<register name="XMM1" offset="0x1210" bitsize="128" />
<register name="XMM2" offset="0x1220" bitsize="128" />
<register name="XMM3" offset="0x1230" bitsize="128" />
<register name="XMM4" offset="0x1240" bitsize="128" />
<register name="XMM5" offset="0x1250" bitsize="128" />
<register name="XMM6" offset="0x1260" bitsize="128" />
<register name="XMM7" offset="0x1270" bitsize="128" />
<register name="XMM8" offset="0x1280" bitsize="128" />
<register name="XMM9" offset="0x1290" bitsize="128" />
<register name="XMM10" offset="0x12a0" bitsize="128" />
<register name="XMM11" offset="0x12b0" bitsize="128" />
<register name="XMM12" offset="0x12c0" bitsize="128" />
<register name="XMM13" offset="0x12d0" bitsize="128" />
<register name="XMM14" offset="0x12e0" bitsize="128" />
<register name="XMM15" offset="0x12f0" bitsize="128" />
<register name="IDTR" offset="0x2200" bitsize="48" />
<register name="IDTR_Limit" offset="0x2200" bitsize="16" />
<register name="IDTR_Address" offset="0x2202" bitsize="32" />
<register name="GDTR" offset="0x2210" bitsize="48" />
<register name="GDTR_Limit" offset="0x2210" bitsize="16" />
<register name="GDTR_Address" offset="0x2212" bitsize="32" />
<register name="LDTR" offset="0x2220" bitsize="48" />
<register name="LDTR_Limit" offset="0x2220" bitsize="16" />
<register name="LDTR_Address" offset="0x2222" bitsize="32" />
<register name="TR" offset="0x2230" bitsize="48" />
<register name="TR_Limit" offset="0x2230" bitsize="16" />
<register name="TR_Address" offset="0x2232" bitsize="32" />
</registers>
</language>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_translation>
<from_language version="1">x86:LE:16:Real Mode</from_language>
<to_language version="2">x86:LE:16:Real Mode</to_language>
<map_compiler_spec from="default" to="default" />
</language_translation>

View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<language version="1" endian="little">
<description>
<id>x86:LE:32:default</id>
<processor>x86</processor>
</description>
<compiler name="Visual Studio" id="windows"/>
<compiler name="gcc" id="gcc"/>
<spaces>
<space name="ram" type="ram" size="4" default="yes" />
<space name="register" type="register" size="4" />
</spaces>
<registers>
<context_register name="contextreg" offset="0x2000" bitsize="32">
<field name="lockprefx" range="8,8" />
<field name="repprefx" range="7,7" />
<field name="repneprefx" range="6,6" />
<field name="sstype" range="5,5" />
<field name="segover" range="2,4" />
<field name="opsize" range="1,1" />
<field name="addrsize" range="0,0" />
</context_register>
<register name="EAX" offset="0x0" bitsize="32" />
<register name="ECX" offset="0x4" bitsize="32" />
<register name="EDX" offset="0x8" bitsize="32" />
<register name="EBX" offset="0xc" bitsize="32" />
<register name="ESP" offset="0x10" bitsize="32" />
<register name="EBP" offset="0x14" bitsize="32" />
<register name="ESI" offset="0x18" bitsize="32" />
<register name="EDI" offset="0x1c" bitsize="32" />
<register name="AX" offset="0x0" bitsize="16" />
<register name="CX" offset="0x4" bitsize="16" />
<register name="DX" offset="0x8" bitsize="16" />
<register name="BX" offset="0xc" bitsize="16" />
<register name="SP" offset="0x10" bitsize="16" />
<register name="BP" offset="0x14" bitsize="16" />
<register name="SI" offset="0x18" bitsize="16" />
<register name="DI" offset="0x1c" bitsize="16" />
<register name="AL" offset="0x0" bitsize="8" />
<register name="AH" offset="0x1" bitsize="8" />
<register name="CL" offset="0x4" bitsize="8" />
<register name="CH" offset="0x5" bitsize="8" />
<register name="DL" offset="0x8" bitsize="8" />
<register name="DH" offset="0x9" bitsize="8" />
<register name="BL" offset="0xc" bitsize="8" />
<register name="BH" offset="0xd" bitsize="8" />
<register name="ES" offset="0x100" bitsize="16" />
<register name="CS" offset="0x102" bitsize="16" />
<register name="SS" offset="0x104" bitsize="16" />
<register name="DS" offset="0x106" bitsize="16" />
<register name="FS" offset="0x108" bitsize="16" />
<register name="GS" offset="0x10a" bitsize="16" />
<register name="FS_OFFSET" offset="0x110" bitsize="32" />
<register name="CF" offset="0x200" bitsize="8" />
<register name="F1" offset="0x201" bitsize="8" />
<register name="PF" offset="0x202" bitsize="8" />
<register name="F3" offset="0x203" bitsize="8" />
<register name="AF" offset="0x204" bitsize="8" />
<register name="F5" offset="0x205" bitsize="8" />
<register name="ZF" offset="0x206" bitsize="8" />
<register name="SF" offset="0x207" bitsize="8" />
<register name="TF" offset="0x208" bitsize="8" />
<register name="IF" offset="0x209" bitsize="8" />
<register name="DF" offset="0x20a" bitsize="8" />
<register name="OF" offset="0x20b" bitsize="8" />
<register name="IOPL" offset="0x20c" bitsize="8" />
<register name="NT" offset="0x20d" bitsize="8" />
<register name="F15" offset="0x20e" bitsize="8" />
<register name="RF" offset="0x20f" bitsize="8" />
<register name="VM" offset="0x210" bitsize="8" />
<register name="AC" offset="0x211" bitsize="8" />
<register name="VIF" offset="0x212" bitsize="8" />
<register name="VIP" offset="0x213" bitsize="8" />
<register name="ID" offset="0x214" bitsize="8" />
<register name="eflags" offset="0x280" bitsize="32" />
<register name="EIP" offset="0x284" bitsize="32" />
<register name="flags" offset="0x280" bitsize="16" />
<register name="IP" offset="0x284" bitsize="16" />
<register name="DR0" offset="0x300" bitsize="32" />
<register name="DR1" offset="0x304" bitsize="32" />
<register name="DR2" offset="0x308" bitsize="32" />
<register name="DR3" offset="0x30c" bitsize="32" />
<register name="DR4" offset="0x310" bitsize="32" />
<register name="DR5" offset="0x314" bitsize="32" />
<register name="DR6" offset="0x318" bitsize="32" />
<register name="DR7" offset="0x31c" bitsize="32" />
<register name="CR0" offset="0x320" bitsize="32" />
<register name="CR2" offset="0x328" bitsize="32" />
<register name="CR3" offset="0x32c" bitsize="32" />
<register name="CR4" offset="0x330" bitsize="32" />
<register name="TR0" offset="0x400" bitsize="32" />
<register name="TR1" offset="0x404" bitsize="32" />
<register name="TR2" offset="0x408" bitsize="32" />
<register name="TR3" offset="0x40c" bitsize="32" />
<register name="TR4" offset="0x410" bitsize="32" />
<register name="TR5" offset="0x414" bitsize="32" />
<register name="TR6" offset="0x418" bitsize="32" />
<register name="TR7" offset="0x41c" bitsize="32" />
<register name="ST0" offset="0x1000" bitsize="80" />
<register name="ST1" offset="0x100a" bitsize="80" />
<register name="ST2" offset="0x1014" bitsize="80" />
<register name="ST3" offset="0x101e" bitsize="80" />
<register name="ST4" offset="0x1028" bitsize="80" />
<register name="ST5" offset="0x1032" bitsize="80" />
<register name="ST6" offset="0x103c" bitsize="80" />
<register name="ST7" offset="0x1046" bitsize="80" />
<register name="FPUControlWord" offset="0x1090" bitsize="16" />
<register name="FPUStatusWord" offset="0x1092" bitsize="16" />
<register name="FPUTagWord" offset="0x1094" bitsize="16" />
<register name="FPUDataPointer" offset="0x1096" bitsize="16" />
<register name="FPUInstructionPointer" offset="0x1098" bitsize="16" />
<register name="FPULastInstructionOpcode" offset="0x109a" bitsize="16" />
<register name="MM0" offset="0x1100" bitsize="64" />
<register name="MM1" offset="0x1108" bitsize="64" />
<register name="MM2" offset="0x1110" bitsize="64" />
<register name="MM3" offset="0x1118" bitsize="64" />
<register name="MM4" offset="0x1120" bitsize="64" />
<register name="MM5" offset="0x1128" bitsize="64" />
<register name="MM6" offset="0x1130" bitsize="64" />
<register name="MM7" offset="0x1138" bitsize="64" />
<register name="XMM0" offset="0x1200" bitsize="128" />
<register name="XMM1" offset="0x1210" bitsize="128" />
<register name="XMM2" offset="0x1220" bitsize="128" />
<register name="XMM3" offset="0x1230" bitsize="128" />
<register name="XMM4" offset="0x1240" bitsize="128" />
<register name="XMM5" offset="0x1250" bitsize="128" />
<register name="XMM6" offset="0x1260" bitsize="128" />
<register name="XMM7" offset="0x1270" bitsize="128" />
<register name="XMM8" offset="0x1280" bitsize="128" />
<register name="XMM9" offset="0x1290" bitsize="128" />
<register name="XMM10" offset="0x12a0" bitsize="128" />
<register name="XMM11" offset="0x12b0" bitsize="128" />
<register name="XMM12" offset="0x12c0" bitsize="128" />
<register name="XMM13" offset="0x12d0" bitsize="128" />
<register name="XMM14" offset="0x12e0" bitsize="128" />
<register name="XMM15" offset="0x12f0" bitsize="128" />
<register name="IDTR" offset="0x2200" bitsize="48" />
<register name="IDTR_Limit" offset="0x2200" bitsize="16" />
<register name="IDTR_Address" offset="0x2202" bitsize="32" />
<register name="GDTR" offset="0x2210" bitsize="48" />
<register name="GDTR_Limit" offset="0x2210" bitsize="16" />
<register name="GDTR_Address" offset="0x2212" bitsize="32" />
<register name="LDTR" offset="0x2220" bitsize="48" />
<register name="LDTR_Limit" offset="0x2220" bitsize="16" />
<register name="LDTR_Address" offset="0x2222" bitsize="32" />
<register name="TR" offset="0x2230" bitsize="48" />
<register name="TR_Limit" offset="0x2230" bitsize="16" />
<register name="TR_Address" offset="0x2232" bitsize="32" />
</registers>
</language>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_translation>
<from_language version="1">x86:LE:32:default</from_language>
<to_language version="2">x86:LE:32:default</to_language>
<map_compiler_spec from="windows" to="windows" />
<map_compiler_spec from="gcc" to="gcc" />
</language_translation>

View File

@@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<language version="1" endian="little">
<description>
<id>x64:LE:64:default</id>
<processor>x64</processor>
</description>
<compiler name="Visual Studio" id="windows"/>
<compiler name="gcc" id="gcc"/>
<spaces>
<space name="ram" type="ram" size="8" default="yes" />
<space name="register" type="register" size="4" />
</spaces>
<registers>
<context_register name="contextreg" offset="0x2000" bitsize="32">
<field name="rexprefix" range="15,15" />
<field name="rexBprefix" range="14,14" />
<field name="rexXprefix" range="13,13" />
<field name="rexRprefix" range="12,12" />
<field name="rexWprefix" range="11,11" />
<field name="lockprefx" range="10,10" />
<field name="repprefx" range="9,9" />
<field name="repneprefx" range="8,8" />
<field name="sstype" range="7,7" />
<field name="segover" range="4,6" />
<field name="opsize" range="2,3" />
<field name="addrsize" range="0,1" />
<field name="bit64" range="0,0" />
</context_register>
<register name="RAX" offset="0x0" bitsize="64" />
<register name="RCX" offset="0x8" bitsize="64" />
<register name="RDX" offset="0x10" bitsize="64" />
<register name="RBX" offset="0x18" bitsize="64" />
<register name="RSP" offset="0x20" bitsize="64" />
<register name="RBP" offset="0x28" bitsize="64" />
<register name="RSI" offset="0x30" bitsize="64" />
<register name="RDI" offset="0x38" bitsize="64" />
<register name="EAX" offset="0x0" bitsize="32" />
<register name="ECX" offset="0x8" bitsize="32" />
<register name="EDX" offset="0x10" bitsize="32" />
<register name="EBX" offset="0x18" bitsize="32" />
<register name="ESP" offset="0x20" bitsize="32" />
<register name="EBP" offset="0x28" bitsize="32" />
<register name="ESI" offset="0x30" bitsize="32" />
<register name="EDI" offset="0x38" bitsize="32" />
<register name="AX" offset="0x0" bitsize="16" />
<register name="CX" offset="0x8" bitsize="16" />
<register name="DX" offset="0x10" bitsize="16" />
<register name="BX" offset="0x18" bitsize="16" />
<register name="SP" offset="0x20" bitsize="16" />
<register name="BP" offset="0x28" bitsize="16" />
<register name="SI" offset="0x30" bitsize="16" />
<register name="DI" offset="0x38" bitsize="16" />
<register name="AL" offset="0x0" bitsize="8" />
<register name="AH" offset="0x1" bitsize="8" />
<register name="CL" offset="0x8" bitsize="8" />
<register name="CH" offset="0x9" bitsize="8" />
<register name="DL" offset="0x10" bitsize="8" />
<register name="DH" offset="0x11" bitsize="8" />
<register name="BL" offset="0x18" bitsize="8" />
<register name="BH" offset="0x19" bitsize="8" />
<register name="SPL" offset="0x20" bitsize="8" />
<register name="BPL" offset="0x28" bitsize="8" />
<register name="SIL" offset="0x30" bitsize="8" />
<register name="DIL" offset="0x38" bitsize="8" />
<register name="R8" offset="0x80" bitsize="64" />
<register name="R9" offset="0x88" bitsize="64" />
<register name="R10" offset="0x90" bitsize="64" />
<register name="R11" offset="0x98" bitsize="64" />
<register name="R12" offset="0xa0" bitsize="64" />
<register name="R13" offset="0xa8" bitsize="64" />
<register name="R14" offset="0xb0" bitsize="64" />
<register name="R15" offset="0xb8" bitsize="64" />
<register name="R8D" offset="0x80" bitsize="32" />
<register name="R9D" offset="0x88" bitsize="32" />
<register name="R10D" offset="0x90" bitsize="32" />
<register name="R11D" offset="0x98" bitsize="32" />
<register name="R12D" offset="0xa0" bitsize="32" />
<register name="R13D" offset="0xa8" bitsize="32" />
<register name="R14D" offset="0xb0" bitsize="32" />
<register name="R15D" offset="0xb8" bitsize="32" />
<register name="R8W" offset="0x80" bitsize="16" />
<register name="R9W" offset="0x88" bitsize="16" />
<register name="R10W" offset="0x90" bitsize="16" />
<register name="R11W" offset="0x98" bitsize="16" />
<register name="R12W" offset="0xa0" bitsize="16" />
<register name="R13W" offset="0xa8" bitsize="16" />
<register name="R14W" offset="0xb0" bitsize="16" />
<register name="R15W" offset="0xb8" bitsize="16" />
<register name="R8B" offset="0x80" bitsize="8" />
<register name="R9B" offset="0x88" bitsize="8" />
<register name="R10B" offset="0x90" bitsize="8" />
<register name="R11B" offset="0x98" bitsize="8" />
<register name="R12B" offset="0xa0" bitsize="8" />
<register name="R13B" offset="0xa8" bitsize="8" />
<register name="R14B" offset="0xb0" bitsize="8" />
<register name="R15B" offset="0xb8" bitsize="8" />
<register name="ES" offset="0x100" bitsize="16" />
<register name="CS" offset="0x102" bitsize="16" />
<register name="SS" offset="0x104" bitsize="16" />
<register name="DS" offset="0x106" bitsize="16" />
<register name="FS" offset="0x108" bitsize="16" />
<register name="GS" offset="0x10a" bitsize="16" />
<register name="FS_OFFSET" offset="0x110" bitsize="32" />
<register name="CF" offset="0x200" bitsize="8" />
<register name="F1" offset="0x201" bitsize="8" />
<register name="PF" offset="0x202" bitsize="8" />
<register name="F3" offset="0x203" bitsize="8" />
<register name="AF" offset="0x204" bitsize="8" />
<register name="F5" offset="0x205" bitsize="8" />
<register name="ZF" offset="0x206" bitsize="8" />
<register name="SF" offset="0x207" bitsize="8" />
<register name="TF" offset="0x208" bitsize="8" />
<register name="IF" offset="0x209" bitsize="8" />
<register name="DF" offset="0x20a" bitsize="8" />
<register name="OF" offset="0x20b" bitsize="8" />
<register name="IOPL" offset="0x20c" bitsize="8" />
<register name="NT" offset="0x20d" bitsize="8" />
<register name="F15" offset="0x20e" bitsize="8" />
<register name="RF" offset="0x20f" bitsize="8" />
<register name="VM" offset="0x210" bitsize="8" />
<register name="AC" offset="0x211" bitsize="8" />
<register name="VIF" offset="0x212" bitsize="8" />
<register name="VIP" offset="0x213" bitsize="8" />
<register name="ID" offset="0x214" bitsize="8" />
<register name="rflags" offset="0x280" bitsize="64" />
<register name="RIP" offset="0x288" bitsize="64" />
<register name="eflags" offset="0x280" bitsize="32" />
<register name="EIP" offset="0x288" bitsize="32" />
<register name="flags" offset="0x280" bitsize="16" />
<register name="IP" offset="0x288" bitsize="16" />
<register name="DR0" offset="0x300" bitsize="64" />
<register name="DR1" offset="0x308" bitsize="64" />
<register name="DR2" offset="0x310" bitsize="64" />
<register name="DR3" offset="0x318" bitsize="64" />
<register name="DR4" offset="0x320" bitsize="64" />
<register name="DR5" offset="0x328" bitsize="64" />
<register name="DR6" offset="0x330" bitsize="64" />
<register name="DR7" offset="0x338" bitsize="64" />
<register name="DR8" offset="0x340" bitsize="64" />
<register name="DR9" offset="0x348" bitsize="64" />
<register name="DR10" offset="0x350" bitsize="64" />
<register name="DR11" offset="0x358" bitsize="64" />
<register name="DR12" offset="0x360" bitsize="64" />
<register name="DR13" offset="0x368" bitsize="64" />
<register name="DR14" offset="0x370" bitsize="64" />
<register name="DR15" offset="0x378" bitsize="64" />
<register name="CR0" offset="0x380" bitsize="64" />
<register name="CR1" offset="0x388" bitsize="64" />
<register name="CR2" offset="0x390" bitsize="64" />
<register name="CR3" offset="0x398" bitsize="64" />
<register name="CR4" offset="0x3a0" bitsize="64" />
<register name="CR5" offset="0x3a8" bitsize="64" />
<register name="CR6" offset="0x3b0" bitsize="64" />
<register name="CR7" offset="0x3b8" bitsize="64" />
<register name="CR8" offset="0x3c0" bitsize="64" />
<register name="CR9" offset="0x3c8" bitsize="64" />
<register name="CR10" offset="0x3d0" bitsize="64" />
<register name="CR11" offset="0x3d8" bitsize="64" />
<register name="CR12" offset="0x3e0" bitsize="64" />
<register name="CR13" offset="0x3e8" bitsize="64" />
<register name="CR14" offset="0x3f0" bitsize="64" />
<register name="CR15" offset="0x3f8" bitsize="64" />
<register name="ST0" offset="0x1000" bitsize="80" />
<register name="ST1" offset="0x100a" bitsize="80" />
<register name="ST2" offset="0x1014" bitsize="80" />
<register name="ST3" offset="0x101e" bitsize="80" />
<register name="ST4" offset="0x1028" bitsize="80" />
<register name="ST5" offset="0x1032" bitsize="80" />
<register name="ST6" offset="0x103c" bitsize="80" />
<register name="ST7" offset="0x1046" bitsize="80" />
<register name="C0" offset="0x1080" bitsize="8" />
<register name="C1" offset="0x1081" bitsize="8" />
<register name="C2" offset="0x1082" bitsize="8" />
<register name="C3" offset="0x1083" bitsize="8" />
<register name="FPUControlWord" offset="0x1090" bitsize="16" />
<register name="FPUStatusWord" offset="0x1092" bitsize="16" />
<register name="FPUTagWord" offset="0x1094" bitsize="16" />
<register name="FPUDataPointer" offset="0x1096" bitsize="16" />
<register name="FPUInstructionPointer" offset="0x1098" bitsize="16" />
<register name="FPULastInstructionOpcode" offset="0x109a" bitsize="16" />
<register name="MM0" offset="0x1100" bitsize="64" />
<register name="MM1" offset="0x1108" bitsize="64" />
<register name="MM2" offset="0x1110" bitsize="64" />
<register name="MM3" offset="0x1118" bitsize="64" />
<register name="MM4" offset="0x1120" bitsize="64" />
<register name="MM5" offset="0x1128" bitsize="64" />
<register name="MM6" offset="0x1130" bitsize="64" />
<register name="MM7" offset="0x1138" bitsize="64" />
<register name="XMM0" offset="0x1200" bitsize="128" />
<register name="XMM1" offset="0x1210" bitsize="128" />
<register name="XMM2" offset="0x1220" bitsize="128" />
<register name="XMM3" offset="0x1230" bitsize="128" />
<register name="XMM4" offset="0x1240" bitsize="128" />
<register name="XMM5" offset="0x1250" bitsize="128" />
<register name="XMM6" offset="0x1260" bitsize="128" />
<register name="XMM7" offset="0x1270" bitsize="128" />
<register name="XMM8" offset="0x1280" bitsize="128" />
<register name="XMM9" offset="0x1290" bitsize="128" />
<register name="XMM10" offset="0x12a0" bitsize="128" />
<register name="XMM11" offset="0x12b0" bitsize="128" />
<register name="XMM12" offset="0x12c0" bitsize="128" />
<register name="XMM13" offset="0x12d0" bitsize="128" />
<register name="XMM14" offset="0x12e0" bitsize="128" />
<register name="XMM15" offset="0x12f0" bitsize="128" />
<register name="IDTR_Limit" offset="0x2200" bitsize="32" />
<register name="IDTR" offset="0x2200" bitsize="96" />
<register name="IDTR_Address" offset="0x2204" bitsize="64" />
<register name="GDTR_Limit" offset="0x2220" bitsize="32" />
<register name="GDTR" offset="0x2220" bitsize="96" />
<register name="GDTR_Address" offset="0x2224" bitsize="64" />
<register name="LDTR_Limit" offset="0x2240" bitsize="32" />
<register name="LDTR" offset="0x2240" bitsize="112" />
<register name="LDTR_Address" offset="0x2244" bitsize="64" />
<register name="LDTR_Attributes" offset="0x2248" bitsize="16" />
<register name="TR_Limit" offset="0x2260" bitsize="32" />
<register name="TR" offset="0x2260" bitsize="112" />
<register name="TR_Address" offset="0x2264" bitsize="64" />
<register name="TR_Attributes" offset="0x2268" bitsize="16" />
</registers>
</language>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_translation>
<from_language version="1">x64:LE:64:default</from_language>
<to_language version="2">x86:LE:64:default</to_language>
<map_compiler_spec from="windows" to="windows" />
<map_compiler_spec from="gcc" to="gcc" />
</language_translation>

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<language version="1" endian="little">
<description>
<id>x86:LE:32:System Management Mode</id>
<processor>x86</processor>
</description>
<compiler name="default" id="default"/>
<spaces>
<space name="ram" type="ram" size="4" default="yes" />
<space name="register" type="register" size="4" />
</spaces>
<registers>
<context_register name="contextreg" offset="0x2000" bitsize="32">
<field name="lockprefx" range="8,8" />
<field name="repprefx" range="7,7" />
<field name="repneprefx" range="6,6" />
<field name="sstype" range="5,5" />
<field name="segover" range="2,4" />
<field name="opsize" range="1,1" />
<field name="addrsize" range="0,0" />
</context_register>
<register name="EAX" offset="0x0" bitsize="32" />
<register name="ECX" offset="0x4" bitsize="32" />
<register name="EDX" offset="0x8" bitsize="32" />
<register name="EBX" offset="0xc" bitsize="32" />
<register name="ESP" offset="0x10" bitsize="32" />
<register name="EBP" offset="0x14" bitsize="32" />
<register name="ESI" offset="0x18" bitsize="32" />
<register name="EDI" offset="0x1c" bitsize="32" />
<register name="AX" offset="0x0" bitsize="16" />
<register name="CX" offset="0x4" bitsize="16" />
<register name="DX" offset="0x8" bitsize="16" />
<register name="BX" offset="0xc" bitsize="16" />
<register name="SP" offset="0x10" bitsize="16" />
<register name="BP" offset="0x14" bitsize="16" />
<register name="SI" offset="0x18" bitsize="16" />
<register name="DI" offset="0x1c" bitsize="16" />
<register name="AL" offset="0x0" bitsize="8" />
<register name="AH" offset="0x1" bitsize="8" />
<register name="CL" offset="0x4" bitsize="8" />
<register name="CH" offset="0x5" bitsize="8" />
<register name="DL" offset="0x8" bitsize="8" />
<register name="DH" offset="0x9" bitsize="8" />
<register name="BL" offset="0xc" bitsize="8" />
<register name="BH" offset="0xd" bitsize="8" />
<register name="ES" offset="0x100" bitsize="16" />
<register name="CS" offset="0x102" bitsize="16" />
<register name="SS" offset="0x104" bitsize="16" />
<register name="DS" offset="0x106" bitsize="16" />
<register name="FS" offset="0x108" bitsize="16" />
<register name="GS" offset="0x10a" bitsize="16" />
<register name="FS_OFFSET" offset="0x110" bitsize="32" />
<register name="CF" offset="0x200" bitsize="8" />
<register name="F1" offset="0x201" bitsize="8" />
<register name="PF" offset="0x202" bitsize="8" />
<register name="F3" offset="0x203" bitsize="8" />
<register name="AF" offset="0x204" bitsize="8" />
<register name="F5" offset="0x205" bitsize="8" />
<register name="ZF" offset="0x206" bitsize="8" />
<register name="SF" offset="0x207" bitsize="8" />
<register name="TF" offset="0x208" bitsize="8" />
<register name="IF" offset="0x209" bitsize="8" />
<register name="DF" offset="0x20a" bitsize="8" />
<register name="OF" offset="0x20b" bitsize="8" />
<register name="IOPL" offset="0x20c" bitsize="8" />
<register name="NT" offset="0x20d" bitsize="8" />
<register name="F15" offset="0x20e" bitsize="8" />
<register name="RF" offset="0x20f" bitsize="8" />
<register name="VM" offset="0x210" bitsize="8" />
<register name="AC" offset="0x211" bitsize="8" />
<register name="VIF" offset="0x212" bitsize="8" />
<register name="VIP" offset="0x213" bitsize="8" />
<register name="ID" offset="0x214" bitsize="8" />
<register name="eflags" offset="0x280" bitsize="32" />
<register name="EIP" offset="0x284" bitsize="32" />
<register name="flags" offset="0x280" bitsize="16" />
<register name="IP" offset="0x284" bitsize="16" />
<register name="DR0" offset="0x300" bitsize="32" />
<register name="DR1" offset="0x304" bitsize="32" />
<register name="DR2" offset="0x308" bitsize="32" />
<register name="DR3" offset="0x30c" bitsize="32" />
<register name="DR4" offset="0x310" bitsize="32" />
<register name="DR5" offset="0x314" bitsize="32" />
<register name="DR6" offset="0x318" bitsize="32" />
<register name="DR7" offset="0x31c" bitsize="32" />
<register name="CR0" offset="0x320" bitsize="32" />
<register name="CR2" offset="0x328" bitsize="32" />
<register name="CR3" offset="0x32c" bitsize="32" />
<register name="CR4" offset="0x330" bitsize="32" />
<register name="TR0" offset="0x400" bitsize="32" />
<register name="TR1" offset="0x404" bitsize="32" />
<register name="TR2" offset="0x408" bitsize="32" />
<register name="TR3" offset="0x40c" bitsize="32" />
<register name="TR4" offset="0x410" bitsize="32" />
<register name="TR5" offset="0x414" bitsize="32" />
<register name="TR6" offset="0x418" bitsize="32" />
<register name="TR7" offset="0x41c" bitsize="32" />
<register name="ST0" offset="0x1000" bitsize="80" />
<register name="ST1" offset="0x100a" bitsize="80" />
<register name="ST2" offset="0x1014" bitsize="80" />
<register name="ST3" offset="0x101e" bitsize="80" />
<register name="ST4" offset="0x1028" bitsize="80" />
<register name="ST5" offset="0x1032" bitsize="80" />
<register name="ST6" offset="0x103c" bitsize="80" />
<register name="ST7" offset="0x1046" bitsize="80" />
<register name="FPUControlWord" offset="0x1090" bitsize="16" />
<register name="FPUStatusWord" offset="0x1092" bitsize="16" />
<register name="FPUTagWord" offset="0x1094" bitsize="16" />
<register name="FPUDataPointer" offset="0x1096" bitsize="16" />
<register name="FPUInstructionPointer" offset="0x1098" bitsize="16" />
<register name="FPULastInstructionOpcode" offset="0x109a" bitsize="16" />
<register name="MM0" offset="0x1100" bitsize="64" />
<register name="MM1" offset="0x1108" bitsize="64" />
<register name="MM2" offset="0x1110" bitsize="64" />
<register name="MM3" offset="0x1118" bitsize="64" />
<register name="MM4" offset="0x1120" bitsize="64" />
<register name="MM5" offset="0x1128" bitsize="64" />
<register name="MM6" offset="0x1130" bitsize="64" />
<register name="MM7" offset="0x1138" bitsize="64" />
<register name="XMM0" offset="0x1200" bitsize="128" />
<register name="XMM1" offset="0x1210" bitsize="128" />
<register name="XMM2" offset="0x1220" bitsize="128" />
<register name="XMM3" offset="0x1230" bitsize="128" />
<register name="XMM4" offset="0x1240" bitsize="128" />
<register name="XMM5" offset="0x1250" bitsize="128" />
<register name="XMM6" offset="0x1260" bitsize="128" />
<register name="XMM7" offset="0x1270" bitsize="128" />
<register name="XMM8" offset="0x1280" bitsize="128" />
<register name="XMM9" offset="0x1290" bitsize="128" />
<register name="XMM10" offset="0x12a0" bitsize="128" />
<register name="XMM11" offset="0x12b0" bitsize="128" />
<register name="XMM12" offset="0x12c0" bitsize="128" />
<register name="XMM13" offset="0x12d0" bitsize="128" />
<register name="XMM14" offset="0x12e0" bitsize="128" />
<register name="XMM15" offset="0x12f0" bitsize="128" />
<register name="IDTR" offset="0x2200" bitsize="48" />
<register name="IDTR_Limit" offset="0x2200" bitsize="16" />
<register name="IDTR_Address" offset="0x2202" bitsize="32" />
<register name="GDTR" offset="0x2210" bitsize="48" />
<register name="GDTR_Limit" offset="0x2210" bitsize="16" />
<register name="GDTR_Address" offset="0x2212" bitsize="32" />
<register name="LDTR" offset="0x2220" bitsize="48" />
<register name="LDTR_Limit" offset="0x2220" bitsize="16" />
<register name="LDTR_Address" offset="0x2222" bitsize="32" />
<register name="TR" offset="0x2230" bitsize="48" />
<register name="TR_Limit" offset="0x2230" bitsize="16" />
<register name="TR_Address" offset="0x2232" bitsize="32" />
</registers>
</language>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_translation>
<from_language version="1">x86:LE:32:System Management Mode</from_language>
<to_language version="2">x86:LE:32:System Management Mode</to_language>
<map_compiler_spec from="default" to="default" />
</language_translation>

View File

@@ -0,0 +1,173 @@
# Due to limitations on variable length matching that preclude opcode matching afterwards, all memory addressing forms of PCLMULQDQ are decoded to PCLMULQDQ, not the macro names.
# Display is non-standard, but semantics, and de-compilation should be correct.
macro pclmul(src1, src2, dest) {
local i:4 = 0:4;
local temp:16 = 0;
<start>
if (i > 63:4) goto <end>;
if ((src1 & (1 << i)) == 0) goto <skip>;
temp = temp ^ (src2 << i);
<skip>
i = i+1;
goto <start>;
<end>
dest = temp;
}
:PCLMULLQLQDQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x3a; byte=0x44; xmmmod=3 & XmmReg1 & XmmReg2; byte=0x00
{
local src1:16 = zext(XmmReg1[0,64]);
local src2:16 = zext(XmmReg2[0,64]);
pclmul(src1,src2,XmmReg1);
}
:PCLMULHQLQDQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x3a; byte=0x44; xmmmod=3 & XmmReg1 & XmmReg2; byte=0x01
{
local src1:16 = zext(XmmReg1[64,64]);
local src2:16 = zext(XmmReg2[0,64]);
pclmul(src1,src2,XmmReg1);
}
:PCLMULLQHQDQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x3a; byte=0x44; xmmmod=3 & XmmReg1 & XmmReg2; byte=0x10
{
local src1:16 = zext(XmmReg1[0,64]);
local src2:16 = zext(XmmReg2[64,64]);
pclmul(src1,src2,XmmReg1);
}
:PCLMULHQHQDQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x3a; byte=0x44; xmmmod=3 & XmmReg1 & XmmReg2; byte=0x11
{
local src1:16 = zext(XmmReg1[64,64]);
local src2:16 = zext(XmmReg2[64,64]);
pclmul(src1,src2,XmmReg1);
}
:PCLMULQDQ XmmReg1, XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x3a; byte=0x44; xmmmod=3 & XmmReg1 & XmmReg2; imm8 & imm8_4 & imm8_0
{
if (imm8_0:1) goto <src1_b>;
src1:16 = zext(XmmReg1[0,64]);
goto <done1>;
<src1_b>
src1 = zext(XmmReg1[64,64]);
<done1>
if (imm8_4:1) goto <src2_b>;
src2:16 = zext(XmmReg2[0,64]);
goto <done2>;
<src2_b>
src2 = zext(XmmReg2[64,64]);
<done2>
pclmul(src1,src2,XmmReg1);
}
:PCLMULQDQ XmmReg, m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0x3a; byte=0x44; XmmReg ... & m128; imm8 & imm8_4 & imm8_0
{
if (imm8_0:1) goto <src1_b>;
src1:16 = zext(XmmReg[0,64]);
goto <done1>;
<src1_b>
src1 = zext(XmmReg[64,64]);
<done1>
local m:16 = m128;
if (imm8_4:1) goto <src2_b>;
src2:16 = zext(m[0,64]);
goto <done2>;
<src2_b>
src2 = zext(m[64,64]);
<done2>
pclmul(src1,src2,XmmReg);
}
:VPCLMULLQLQDQ XmmReg1, vexVVVV_XmmReg, XmmReg2 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x44; xmmmod=3 & (XmmReg1 & YmmReg1) & XmmReg2; byte=0x00
{
local src1:16 = zext(vexVVVV_XmmReg[0,64]);
local src2:16 = zext(XmmReg2[0,64]);
pclmul(src1,src2,XmmReg1);
YmmReg1 = zext(XmmReg1);
}
:VPCLMULHQLQDQ XmmReg1, vexVVVV_XmmReg, XmmReg2 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x44; xmmmod=3 & (XmmReg1 & YmmReg1) & XmmReg2; byte=0x01
{
local src1:16 = zext(vexVVVV_XmmReg[64,64]);
local src2:16 = zext(XmmReg2[0,64]);
pclmul(src1,src2,XmmReg1);
YmmReg1 = zext(XmmReg1);
}
:VPCLMULLQHQDQ XmmReg1, vexVVVV_XmmReg, XmmReg2 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x44; xmmmod=3 & (XmmReg1 & YmmReg1) & XmmReg2; byte=0x10
{
local src1:16 = zext(vexVVVV_XmmReg[0,64]);
local src2:16 = zext(XmmReg2[64,64]);
pclmul(src1,src2,XmmReg1);
YmmReg1 = zext(XmmReg1);
}
:VPCLMULHQHQDQ XmmReg1, vexVVVV_XmmReg, XmmReg2 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x44; xmmmod=3 & (XmmReg1 & YmmReg1) & XmmReg2; byte=0x11
{
local src1:16 = zext(vexVVVV_XmmReg[64,64]);
local src2:16 = zext(XmmReg2[64,64]);
pclmul(src1,src2,XmmReg1);
YmmReg1 = zext(XmmReg1);
}
:VPCLMULQDQ XmmReg1, vexVVVV_XmmReg, XmmReg2, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x44; xmmmod=3 & (XmmReg1 & YmmReg1) & XmmReg2; imm8 & imm8_4 & imm8_0
{
if (imm8_0:1) goto <src1_b>;
src1:16 = zext(vexVVVV_XmmReg[0,64]);
goto <done1>;
<src1_b>
src1 = zext(vexVVVV_XmmReg[64,64]);
<done1>
if (imm8_4:1) goto <src2_b>;
src2:16 = zext(XmmReg2[0,64]);
goto <done2>;
<src2_b>
src2 = zext(XmmReg2[64,64]);
<done2>
pclmul(src1,src2,XmmReg1);
YmmReg1 = zext(XmmReg1);
}
:VPCLMULQDQ XmmReg1, vexVVVV_XmmReg, m128, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x44; (XmmReg1 & YmmReg1) ... & m128; imm8 & imm8_4 & imm8_0
{
if (imm8_0:1) goto <src1_b>;
src1:16 = zext(vexVVVV_XmmReg[0,64]);
goto <done1>;
<src1_b>
src1 = zext(vexVVVV_XmmReg[64,64]);
<done1>
local m:16 = m128;
if (imm8_4:1) goto <src2_b>;
src2:16 = zext(m[0,64]);
goto <done2>;
<src2_b>
src2 = zext(m[64,64]);
<done2>
pclmul(src1,src2,XmmReg1);
YmmReg1 = zext(XmmReg1);
}

View File

@@ -0,0 +1,51 @@
define pcodeop rdrand;
define pcodeop rdrandIsValid;
macro rdflags(){
OF = 0; SF = 0; ZF = 0; AF = 0; PF = 0;
}
:RDRAND Rmr16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; mod=3 & Rmr16 & reg_opcode=6
{
Rmr16 = rdrand();
CF=rdrandIsValid();
rdflags();
}
:RDRAND Rmr32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; mod=3 & Rmr32 & reg_opcode=6
{
Rmr32 = rdrand();
CF=rdrandIsValid();
rdflags();
}
@ifdef IA64
:RDRAND Rmr64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; mod=3 & Rmr64 & reg_opcode=6
{
Rmr64 = rdrand();
CF=rdrandIsValid();
rdflags();
}
@endif
define pcodeop rdseed;
define pcodeop rdseedIsValid;
:RDSEED Rmr16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; mod=3 & Rmr16 & reg_opcode=7
{
Rmr16 = rdseed();
CF=rdseedIsValid();
rdflags();
}
:RDSEED Rmr32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; mod=3 & Rmr32 & reg_opcode=7
{
Rmr32 = rdseed();
CF=rdseedIsValid();
rdflags();
}
@ifdef IA64
:RDSEED Rmr64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; mod=3 & Rmr64 & reg_opcode=7
{
Rmr64 = rdseed();
CF=rdseedIsValid();
rdflags();
}
@endif

View File

@@ -0,0 +1,257 @@
define pcodeop encls_ecreate;
define pcodeop encls_eadd;
define pcodeop encls_einit;
define pcodeop encls_einit_ZF;
define pcodeop encls_eremove;
define pcodeop encls_eremove_ZF;
define pcodeop encls_edbgrd;
define pcodeop encls_edbgrd_RBX;
define pcodeop encls_edbgwr;
define pcodeop encls_eextend;
define pcodeop encls_eldb;
define pcodeop encls_eldb_ZF;
define pcodeop encls_eldu;
define pcodeop encls_eldu_ZF;
define pcodeop encls_eblock;
define pcodeop encls_eblock_ZF;
define pcodeop encls_epa;
define pcodeop encls_ewb;
define pcodeop encls_ewb_ZF;
define pcodeop encls_ewb_CF;
define pcodeop encls_etrack;
define pcodeop encls_etrack_ZF;
define pcodeop encls_eaug;
define pcodeop encls_emodpr;
define pcodeop encls_emodpr_ZF;
define pcodeop encls_emodt;
define pcodeop encls_emodt_ZF;
define pcodeop encls_unknown;
:ENCLS is vexMode=0 & byte=0x0f; byte=0x01; byte=0xcf {
if ( EAX != 0x0 ) goto <leaf_1>;
encls_ecreate( RBX, RCX );
goto <done>;
<leaf_1>
if ( EAX != 0x1 ) goto <leaf_2>;
encls_eadd( RBX, RCX );
goto <done>;
<leaf_2>
if ( EAX != 0x2 ) goto <leaf_3>;
RAX = encls_einit( RBX, RCX, RDX );
ZF = encls_einit_ZF( RBX, RCX, RDX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_3>
if ( EAX != 0x3 ) goto <leaf_4>;
RAX = encls_eremove( RCX );
ZF = encls_eremove_ZF( RBX, RCX, RDX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_4>
if ( EAX != 0x4 ) goto <leaf_5>;
RAX = encls_edbgrd( RCX );
RBX = encls_edbgrd_RBX( RCX );
goto <done>;
<leaf_5>
if ( EAX != 0x5 ) goto <leaf_6>;
RAX = encls_edbgwr( RBX, RCX );
goto <done>;
<leaf_6>
if ( EAX != 0x6 ) goto <leaf_7>;
encls_eextend( RBX, RCX );
goto <done>;
<leaf_7>
if ( EAX != 0x7 ) goto <leaf_8>;
RAX = encls_eldb( RBX, RCX, RDX );
ZF = encls_eldb_ZF( RBX, RCX, RDX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_8>
if ( EAX != 0x8 ) goto <leaf_9>;
RAX = encls_eldu( RBX, RCX, RDX );
ZF = encls_eldu_ZF( RBX, RCX, RDX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_9>
if ( EAX != 0x9 ) goto <leaf_A>;
RAX = encls_eblock( RCX );
ZF = encls_eblock_ZF( RCX );
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_A>
if ( EAX != 0xA ) goto <leaf_B>;
encls_epa( RBX, RCX );
goto <done>;
<leaf_B>
if ( EAX != 0xB ) goto <leaf_C>;
RAX = encls_ewb( RBX, RCX, RDX );
ZF = encls_ewb_ZF( RBX, RCX, RDX );
CF = encls_ewb_CF( RBX, RCX, RDX );
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_C>
if ( EAX != 0xC ) goto <leaf_D>;
RAX = encls_etrack( RCX );
ZF = encls_etrack_ZF( RBX, RCX, RDX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_D>
if ( EAX != 0xD ) goto <leaf_E>;
encls_eaug( RBX, RCX, RDX );
goto <done>;
<leaf_E>
if ( EAX != 0xE ) goto <leaf_F>;
RAX = encls_emodpr( RBX, RCX );
ZF = encls_emodpr_ZF( RCX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_F>
if ( EAX != 0xF ) goto <unknown>;
RAX = encls_emodt( RBX, RCX );
ZF = encls_emodt_ZF( RCX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<unknown>
encls_unknown();
<done>
}
define pcodeop enclu_ereport;
define pcodeop enclu_egetkey;
define pcodeop enclu_egetkey_ZF;
define pcodeop enclu_eenter_EAX;
define pcodeop enclu_eenter_RCX;
define pcodeop enclu_eenter_TF;
define pcodeop enclu_eresume;
define pcodeop enclu_eexit;
define pcodeop enclu_eexit_TF;
define pcodeop enclu_eaccept;
define pcodeop enclu_eaccept_ZF;
define pcodeop enclu_emodpe;
define pcodeop enclu_eacceptcopy;
define pcodeop enclu_eacceptcopy_ZF;
define pcodeop enclu_unknown;
:ENCLU is vexMode=0 & byte=0x0f; byte=0x01; byte=0xd7 {
if ( EAX != 0x0 ) goto <leaf_1>;
enclu_ereport( RBX, RCX, RDX );
goto <done>;
<leaf_1>
if ( EAX != 0x1 ) goto <leaf_2>;
RAX = enclu_egetkey( RBX, RCX );
ZF = enclu_egetkey_ZF( RBX, RCX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_2>
if ( EAX != 0x2 ) goto <leaf_3>;
tempBX:8 = RBX;
tempCX:8 = RCX;
EAX = enclu_eenter_EAX( tempBX, tempCX );
RCX = enclu_eenter_RCX( tempBX, tempCX );
TF = enclu_eenter_TF( tempBX, tempCX );
goto <done>;
<leaf_3>
if ( EAX != 0x3 ) goto <leaf_4>;
TF = enclu_eresume( RBX, RCX );
goto <done>;
<leaf_4>
if ( EAX != 0x4 ) goto <leaf_5>;
RCX = enclu_eexit( RBX );
TF = enclu_eexit_TF( RBX );
goto <done>;
<leaf_5>
if ( EAX != 0x5 ) goto <leaf_6>;
RAX = enclu_eaccept( RBX, RCX );
ZF = enclu_eaccept_ZF( RBX, RCX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<leaf_6>
if ( EAX != 0x6 ) goto <leaf_7>;
enclu_emodpe( RBX, RCX );
goto <done>;
<leaf_7>
if ( EAX != 0x7 ) goto <unknown>;
RAX = enclu_eacceptcopy( RBX, RCX, RDX );
ZF = enclu_eacceptcopy_ZF( RBX, RCX, RDX );
CF = 0;
PF = 0;
AF = 0;
OF = 0;
SF = 0;
goto <done>;
<unknown>
enclu_unknown();
<done>
}

View File

@@ -0,0 +1,53 @@
# INFO This file automatically generated by andre on Fri Mar 16 15:13:25 2018
# INFO Direct edits to this file may be lost in future updates
# INFO Command line arguments: ['--sinc', '--cpuid-match', 'SHA']
# SHA1RNDS4 4-602 PAGE 1722 LINE 89511
define pcodeop sha1rnds4_sha ;
:SHA1RNDS4 XmmReg1, XmmReg2_m128, imm8 is vexMode=0 & byte=0x0F; byte=0x3A; byte=0xCC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128; imm8
{
XmmReg1 = sha1rnds4_sha( XmmReg1, XmmReg2_m128, imm8:1 );
}
# SHA1NEXTE 4-604 PAGE 1724 LINE 89602
define pcodeop sha1nexte_sha ;
:SHA1NEXTE XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xC8; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
XmmReg1 = sha1nexte_sha( XmmReg1, XmmReg2_m128 );
}
# SHA1MSG1 4-605 PAGE 1725 LINE 89654
define pcodeop sha1msg1_sha ;
:SHA1MSG1 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xC9; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
XmmReg1 = sha1msg1_sha( XmmReg1, XmmReg2_m128 );
}
# SHA1MSG2 4-606 PAGE 1726 LINE 89708
define pcodeop sha1msg2_sha ;
:SHA1MSG2 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCA; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
XmmReg1 = sha1msg2_sha( XmmReg1, XmmReg2_m128 );
}
# SHA256RNDS2 4-607 PAGE 1727 LINE 89765
define pcodeop sha256rnds2_sha ;
:SHA256RNDS2 XmmReg1, XmmReg2_m128, XMM0 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCB; (XmmReg1 & YmmReg1) ... & XmmReg2_m128 & XMM0
{
XmmReg1 = sha256rnds2_sha( XmmReg1, XmmReg2_m128, XMM0 );
}
# SHA256MSG1 4-609 PAGE 1729 LINE 89847
define pcodeop sha256msg1_sha ;
:SHA256MSG1 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCC; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
XmmReg1 = sha256msg1_sha( XmmReg1, XmmReg2_m128 );
}
# SHA256MSG2 4-610 PAGE 1730 LINE 89900
define pcodeop sha256msg2_sha ;
:SHA256MSG2 XmmReg1, XmmReg2_m128 is vexMode=0 & byte=0x0F; byte=0x38; byte=0xCD; (XmmReg1 & YmmReg1) ... & XmmReg2_m128
{
XmmReg1 = sha256msg2_sha( XmmReg1, XmmReg2_m128 );
}

View File

@@ -0,0 +1,67 @@
define pcodeop getsec_capabilities;
define pcodeop getsec_enteraccs;
define pcodeop getsec_exitac;
define pcodeop getsec_senter;
define pcodeop getsec_sexit;
define pcodeop getsec_parameters_EAX;
define pcodeop getsec_parameters_EBX;
define pcodeop getsec_parameters_ECX;
define pcodeop getsec_smctrl;
define pcodeop getsec_wakeup;
define pcodeop getsec_unknown;
:GETSEC is vexMode=0 & byte=0x0f; byte=0x37 {
if ( EAX != 0x0 ) goto <leaf_1>;
EAX = 0;
if ( EBX != 0x0 ) goto <done>;
EAX = getsec_capabilities( EBX );
goto <done>;
<leaf_1>
if ( EAX != 0x2 ) goto <leaf_2>;
getsec_enteraccs( EBX, ECX );
goto <done>;
<leaf_2>
if ( EAX != 0x3 ) goto <leaf_3>;
@ifdef IA64
getsec_exitac( RBX, EDX );
@else
getsec_exitac( EBX, EDX );
@endif
goto <done>;
<leaf_3>
if ( EAX != 0x4 ) goto <leaf_4>;
getsec_senter( EBX, ECX, EDX);
goto <done>;
<leaf_4>
if ( EAX != 0x5 ) goto <leaf_5>;
getsec_sexit();
goto <done>;
<leaf_5>
if ( EAX != 0x6 ) goto <leaf_6>;
EAX = getsec_parameters_EAX( EBX );
ECX = getsec_parameters_ECX( EBX );
EBX = getsec_parameters_EBX( EBX );
goto <done>;
<leaf_6>
if ( EAX != 0x7 ) goto <leaf_7>;
getsec_smctrl(EBX);
goto <done>;
<leaf_7>
if ( EAX != 0x8 ) goto <unknown>;
getsec_wakeup();
goto <done>;
<unknown>
getsec_unknown();
<done>
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Set up x86 16-bit in real mode -->
<processor_spec>
<properties>
<property key="useOperandReferenceAnalyzerSwitchTables" value="true"/>
</properties>
<programcounter register="EIP"/>
<segmented_address space="ram" type="real" />
<segmentop space="ram" userop="segment" farpointer="yes">
<pcode>
<input name="base" size="2"/>
<input name="inner" size="2"/>
<output name="res" size="4"/>
<body><![CDATA[
res = (zext(base) << 4) + zext(inner);
]]></body>
</pcode>
<constresolve>
<register name="DS"/>
</constresolve>
</segmentop>
<context_data>
<context_set space="ram">
<set name="addrsize" val="0"/>
<set name="opsize" val="0"/>
<set name="protectedMode" val="0"/>
</context_set>
<tracked_set space="ram">
<set name="DF" val="0"/>
</tracked_set>
</context_data>
</processor_spec>

View File

@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" /> <!-- no maximum alignment -->
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="2" />
<pointer_size value="2" /> <!-- near pointer, TODO: how do we define far 4-byte pointer? -->
<wchar_size value="2" />
<short_size value="2" />
<integer_size value="2" />
<long_size value="4" />
<long_long_size value="4" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="10" />
<!-- alignment varies between MIcrosoft and Borland -->
<!--
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="2" />
<entry size="8" alignment="2" />
</size_alignment_map>
-->
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="SP" space="ram"/>
<default_proto>
<prototype name="__stdcall16near" extrapop="unknown" stackshift="2">
<input>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="2" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="AX"/>
</pentry>
<pentry minsize="3" maxsize="4">
<addr space="join" piece1="DX" piece2="AX"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="BP"/>
<register name="SI"/>
<register name="DI"/>
<register name="DS"/>
<register name="CS"/>
<register name="ES"/>
<register name="SS"/>
<register name="DF"/>
</unaffected>
</prototype>
</default_proto>
<prototype name="__cdecl16near" extrapop="2" stackshift="2">
<input>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="2" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="AX"/>
</pentry>
<pentry minsize="3" maxsize="4">
<addr space="join" piece1="DX" piece2="AX"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="BP"/>
<register name="SI"/>
<register name="DI"/>
<register name="DS"/>
<register name="CS"/>
<register name="ES"/>
<register name="SS"/>
<register name="DF"/>
</unaffected>
</prototype>
<prototype name="__stdcall16far" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="AX"/>
</pentry>
<pentry minsize="3" maxsize="4">
<addr space="join" piece1="DX" piece2="AX"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="BP"/>
<register name="SI"/>
<register name="DI"/>
<register name="DS"/>
<register name="CS"/>
<register name="ES"/>
<register name="SS"/>
<register name="DF"/>
</unaffected>
</prototype>
<prototype name="__cdecl16far" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="AX"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="BP"/>
<register name="SI"/>
<register name="DI"/>
<register name="DS"/>
<register name="CS"/>
<register name="ES"/>
<register name="SS"/>
<register name="DF"/>
</unaffected>
</prototype>
<prototype name="__regcall" extrapop="2" stackshift="2">
<input>
<pentry minsize="1" maxsize="2">
<register name="AX"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="BX"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="CX"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="DX"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="AX"/>
</pentry>
<pentry minsize="3" maxsize="4">
<addr space="join" piece1="DX" piece2="AX"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="BP"/>
<register name="CX"/>
<register name="DX"/>
<register name="SI"/>
<register name="DI"/>
<register name="DS"/>
<register name="CS"/>
<register name="ES"/>
<register name="SS"/>
<register name="DF"/>
</unaffected>
</prototype>
</compiler_spec>

View File

@@ -0,0 +1,3 @@
<gdis>
<global optstring="intel"/>
</gdis>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Set up x86 16-bit in protected mode -->
<processor_spec>
<properties>
<property key="useOperandReferenceAnalyzerSwitchTables" value="true"/>
</properties>
<programcounter register="EIP"/>
<segmented_address space="ram" type="protected"/>
<segmentop space="ram" userop="segment" farpointer="yes">
<pcode>
<input name="base" size="2"/>
<input name="inner" size="2"/>
<output name="res" size="4"/>
<body><![CDATA[
res = (zext(base) << 16) + zext(inner);
]]></body>
</pcode>
<constresolve>
<register name="DS"/>
</constresolve>
</segmentop>
<context_data>
<context_set space="ram">
<set name="addrsize" val="0"/>
<set name="opsize" val="0"/>
<set name="protectedMode" val="1"/>
</context_set>
<tracked_set space="ram">
<set name="DF" val="0"/>
</tracked_set>
</context_data>
</processor_spec>

View File

@@ -0,0 +1,324 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" />
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="4" />
<pointer_size value="4" />
<wchar_size value="4" /> <!-- matches go's 'rune' -->
<short_size value="2" />
<integer_size value="4" />
<long_size value="8" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="4" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
</global>
<context_data>
</context_data>
<stackpointer register="ESP" space="ram"/>
<returnaddress>
<varnode space="stack" offset="0" size="4"/>
</returnaddress>
<default_proto>
<prototype name="abi0" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
</unaffected>
</prototype>
</default_proto>
<prototype name="duffzero" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EDI"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EDI"/>
</pentry>
</output>
<killedbycall>
<register name="EDI"/>
</killedbycall>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
</unaffected>
</prototype>
<prototype name="duffcopy" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EDI"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ESI"/>
</pentry>
</input>
<output>
</output>
<killedbycall>
<register name="EDI"/>
<register name="ESI"/>
<register name="ECX"/>
</killedbycall>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
</unaffected>
</prototype>
<prototype name="__cdeclf" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="10">
<register name="ST0"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__thiscall" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__regparm3" extrapop="4" stackshift="4"> <!-- Used particularly by linux kernel -->
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__regparm2" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__regparm1" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="syscall" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EBX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ESI"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDI"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EBP"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<register name="EBX"/>
<register name="ECX"/>
<register name="EDX"/>
<register name="EBP"/>
<register name="EDI"/>
<register name="ESI"/>
<register name="ESP"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="EAX"/>
</killedbycall>
</prototype>
</compiler_spec>

View File

@@ -0,0 +1,9 @@
<golang>
<register_info versions="all">
<int_registers list=""/>
<float_registers list=""/>
<stack initialoffset="4" maxalign="4"/>
<current_goroutine register=""/>
<zero_register register=""/>
</register_info>
</golang>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<processor_spec>
<properties>
<property key="useOperandReferenceAnalyzerSwitchTables" value="true"/>
<property key="assemblyRating:x86:LE:64:compat32" value="GOLD"/>
</properties>
<programcounter register="RIP"/>
<context_data>
<context_set space="ram">
<set name="addrsize" val="1"/>
<set name="opsize" val="1"/>
<set name="rexprefix" val="0"/>
<set name="longMode" val="0"/>
</context_set>
<tracked_set space="ram">
<set name="DF" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="DR0" group="DEBUG"/>
<register name="DR1" group="DEBUG"/>
<register name="DR2" group="DEBUG"/>
<register name="DR3" group="DEBUG"/>
<register name="DR4" group="DEBUG"/>
<register name="DR5" group="DEBUG"/>
<register name="DR6" group="DEBUG"/>
<register name="DR7" group="DEBUG"/>
<register name="DR8" group="DEBUG"/>
<register name="DR9" group="DEBUG"/>
<register name="DR10" group="DEBUG"/>
<register name="DR11" group="DEBUG"/>
<register name="DR12" group="DEBUG"/>
<register name="DR13" group="DEBUG"/>
<register name="DR14" group="DEBUG"/>
<register name="DR15" group="DEBUG"/>
<register name="CR0" group="CONTROL"/>
<register name="CR1" group="CONTROL"/>
<register name="CR2" group="CONTROL"/>
<register name="CR3" group="CONTROL"/>
<register name="CR4" group="CONTROL"/>
<register name="CR5" group="CONTROL"/>
<register name="CR6" group="CONTROL"/>
<register name="CR7" group="CONTROL"/>
<register name="CR8" group="CONTROL"/>
<register name="CR9" group="CONTROL"/>
<register name="CR10" group="CONTROL"/>
<register name="CR11" group="CONTROL"/>
<register name="CR12" group="CONTROL"/>
<register name="CR13" group="CONTROL"/>
<register name="CR14" group="CONTROL"/>
<register name="CR15" group="CONTROL"/>
<register name="C0" group="Cx"/>
<register name="C1" group="Cx"/>
<register name="C2" group="Cx"/>
<register name="C3" group="Cx"/>
<register name="ST0" group="ST"/>
<register name="ST1" group="ST"/>
<register name="ST2" group="ST"/>
<register name="ST3" group="ST"/>
<register name="ST4" group="ST"/>
<register name="ST5" group="ST"/>
<register name="ST6" group="ST"/>
<register name="ST7" group="ST"/>
<register name="FPUControlWord" group="FPU"/>
<register name="FPUStatusWord" group="FPU"/>
<register name="FPUTagWord" group="FPU"/>
<register name="FPUDataPointer" group="FPU"/>
<register name="FPUInstructionPointer" group="FPU"/>
<register name="FPULastInstructionOpcode" group="FPU"/>
<register name="MM0" group="MMX"/>
<register name="MM1" group="MMX"/>
<register name="MM2" group="MMX"/>
<register name="MM3" group="MMX"/>
<register name="MM4" group="MMX"/>
<register name="MM5" group="MMX"/>
<register name="MM6" group="MMX"/>
<register name="MM7" group="MMX"/>
<register name="YMM0" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM1" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM2" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM3" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM4" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM5" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM6" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM7" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM8" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM9" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM10" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM11" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM12" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM13" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM14" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM15" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="XMM0" vector_lane_sizes="1,2,4,8"/>
<register name="XMM1" vector_lane_sizes="1,2,4,8"/>
<register name="XMM2" vector_lane_sizes="1,2,4,8"/>
<register name="XMM3" vector_lane_sizes="1,2,4,8"/>
<register name="XMM4" vector_lane_sizes="1,2,4,8"/>
<register name="XMM5" vector_lane_sizes="1,2,4,8"/>
<register name="XMM6" vector_lane_sizes="1,2,4,8"/>
<register name="XMM7" vector_lane_sizes="1,2,4,8"/>
<register name="XMM8" vector_lane_sizes="1,2,4,8"/>
<register name="XMM9" vector_lane_sizes="1,2,4,8"/>
<register name="XMM10" vector_lane_sizes="1,2,4,8"/>
<register name="XMM11" vector_lane_sizes="1,2,4,8"/>
<register name="XMM12" vector_lane_sizes="1,2,4,8"/>
<register name="XMM13" vector_lane_sizes="1,2,4,8"/>
<register name="XMM14" vector_lane_sizes="1,2,4,8"/>
<register name="XMM15" vector_lane_sizes="1,2,4,8"/>
<register name="CF" group="FLAGS"/>
<register name="F1" group="FLAGS"/>
<register name="PF" group="FLAGS"/>
<register name="F3" group="FLAGS"/>
<register name="AF" group="FLAGS"/>
<register name="F5" group="FLAGS"/>
<register name="ZF" group="FLAGS"/>
<register name="SF" group="FLAGS"/>
<register name="TF" group="FLAGS"/>
<register name="IF" group="FLAGS"/>
<register name="DF" group="FLAGS"/>
<register name="OF" group="FLAGS"/>
<register name="IOPL" group="FLAGS"/>
<register name="NT" group="FLAGS"/>
<register name="F15" group="FLAGS"/>
<register name="RF" group="FLAGS"/>
<register name="VM" group="FLAGS"/>
<register name="AC" group="FLAGS"/>
<register name="VIF" group="FLAGS"/>
<register name="VIP" group="FLAGS"/>
<register name="ID" group="FLAGS"/>
<register name="rflags" group="FLAGS"/>
<register name="eflags" group="FLAGS"/>
<register name="flags" group="FLAGS"/>
<register name="bit64" hidden="true"/>
<register name="segover" hidden="true"/>
<register name="repneprefx" hidden="true"/>
<register name="repprefx" hidden="true"/>
<register name="rexWprefix" hidden="true"/>
<register name="rexRprefix" hidden="true"/>
<register name="rexXprefix" hidden="true"/>
<register name="rexBprefix" hidden="true"/>
<register name="xmmTmp1" hidden="true"/>
<register name="xmmTmp1_Qa" hidden="true"/>
<register name="xmmTmp1_Da" hidden="true"/>
<register name="xmmTmp1_Db" hidden="true"/>
<register name="xmmTmp1_Qb" hidden="true"/>
<register name="xmmTmp1_Dc" hidden="true"/>
<register name="xmmTmp1_Dd" hidden="true"/>
<register name="xmmTmp2" hidden="true"/>
<register name="xmmTmp2_Qa" hidden="true"/>
<register name="xmmTmp2_Da" hidden="true"/>
<register name="xmmTmp2_Db" hidden="true"/>
<register name="xmmTmp2_Qb" hidden="true"/>
<register name="xmmTmp2_Dc" hidden="true"/>
<register name="xmmTmp2_Dd" hidden="true"/>
<register name="rexprefix" hidden="true"/>
</register_data>
</processor_spec>

View File

@@ -0,0 +1,373 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="8" />
<pointer_size value="8" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="8" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="10" /> <!-- aligned-length=16 -->
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
<entry size="16" alignment="16" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="RSP" space="ram"/>
<returnaddress>
<varnode space="stack" offset="0" size="8"/>
</returnaddress>
<default_proto>
<prototype name="__stdcall" extrapop="8" stackshift="8">
<!-- Derived from "System V Application Binary Interface AMD64 Architecture Processor Supplement" April 2016 -->
<input>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM4_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM5_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM6_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM7_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RSI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="8" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
<pentry minsize="9" maxsize="16">
<addr space="join" piece1="RDX" piece2="RAX"/>
</pentry>
</output>
<killedbycall>
<register name="RAX"/>
<register name="RDX"/>
<register name="XMM0"/>
</killedbycall>
<unaffected>
<register name="RBX"/>
<register name="RSP"/>
<register name="RBP"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
</unaffected>
</prototype>
</default_proto>
<prototype name="MSABI" extrapop="8" stackshift="8">
<input pointermax="8">
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="40" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="8"/>
<register name="RBX"/>
<register name="RBP"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="RSP"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="RAX"/>
<register name="XMM0"/>
</killedbycall>
<localrange>
<range space="stack" first="0xfffffffffff0bdc1" last="0xffffffffffffffff"/>
<range space="stack" first="8" last="39"/>
</localrange>
</prototype>
<prototype name="syscall" extrapop="8" stackshift="8">
<input pointermax="8">
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RSI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R10"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="8"/>
<register name="RBX"/>
<register name="RDX"/>
<register name="RBP"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="RSP"/>
<register name="R8"/>
<register name="R9"/>
<register name="R10"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="RCX"/>
<register name="R11"/>
</killedbycall>
</prototype>
<prototype name="processEntry" extrapop="0" stackshift="0">
<input pointermax="8">
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<register name="RSP"/>
</unaffected>
<!-- Functions with this prototype don't have a return address. But, if we don't specify one, this prototype will
use the default, which is to have the return address on the stack. That conflicts with how this prototype actually
uses the stack, so we set a fake return address at a RBP, which is unspecified at process entry -->
<returnaddress>
<register name="RBP"/>
</returnaddress>
</prototype>
<callfixup name="x86_return_thunk">
<target name="__x86_return_thunk"/>
<pcode>
<body><![CDATA[
RIP = *:8 RSP;
RSP = RSP + 8;
return [RIP];
]]></body>
</pcode>
</callfixup>
<callfixup name="fentry">
<target name="__fentry__"/>
<pcode>
<body><![CDATA[
temp:1 = 0;
]]></body>
</pcode>
</callfixup>
<callfixup name="mcount">
<target name="mcount"/>
<pcode>
<body><![CDATA[
temp:1 = 0;
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_rbp">
<target name="__x86_indirect_thunk_rbp"/>
<pcode>
<body><![CDATA[
call [RBP];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_rax">
<target name="__x86_indirect_thunk_rax"/>
<pcode>
<body><![CDATA[
call [RAX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_rbx">
<target name="__x86_indirect_thunk_rbx"/>
<pcode>
<body><![CDATA[
call [RBX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_rcx">
<target name="__x86_indirect_thunk_rcx"/>
<pcode>
<body><![CDATA[
call [RCX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_rdx">
<target name="__x86_indirect_thunk_rdx"/>
<pcode>
<body><![CDATA[
call [RDX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r8">
<target name="__x86_indirect_thunk_r8"/>
<pcode>
<body><![CDATA[
call [R8];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r9">
<target name="__x86_indirect_thunk_r9"/>
<pcode>
<body><![CDATA[
call [R9];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r10">
<target name="__x86_indirect_thunk_r10"/>
<pcode>
<body><![CDATA[
call [R10];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r11">
<target name="__x86_indirect_thunk_r11"/>
<pcode>
<body><![CDATA[
call [R11];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r12">
<target name="__x86_indirect_thunk_r12"/>
<pcode>
<body><![CDATA[
call [R12];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r13">
<target name="__x86_indirect_thunk_r13"/>
<pcode>
<body><![CDATA[
call [R13];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r14">
<target name="__x86_indirect_thunk_r14"/>
<pcode>
<body><![CDATA[
call [R14];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_r15">
<target name="__x86_indirect_thunk_r15"/>
<pcode>
<body><![CDATA[
call [R15];
]]></body>
</pcode>
</callfixup>
</compiler_spec>

View File

@@ -0,0 +1,428 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" />
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="8" />
<pointer_size value="8" />
<wchar_size value="4" /> <!-- matches go's 'rune' -->
<short_size value="2" />
<integer_size value="8" />
<long_size value="8" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
</global>
<context_data>
</context_data>
<stackpointer register="RSP" space="ram"/>
<returnaddress>
<varnode space="stack" offset="0" size="8"/>
</returnaddress>
<default_proto>
<prototype name="abi-internal" extrapop="8" stackshift="8">
<input>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM4_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM5_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM6_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM7_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RBX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RSI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R10"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R11"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="8" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
<pentry minsize="9" maxsize="16">
<addr space="join" piece2="RAX" piece1="RBX"/>
</pentry>
<pentry minsize="17" maxsize="24">
<addr space="join" piece3="RAX" piece2="RBX" piece1="RCX"/>
</pentry>
<pentry minsize="25" maxsize="32">
<addr space="join" piece4="RAX" piece3="RBX" piece2="RCX" piece1="RDI"/>
</pentry>
<pentry minsize="33" maxsize="40">
<addr space="join" piece5="RAX" piece4="RBX" piece3="RCX" piece2="RDI" piece1="RSI"/>
</pentry>
<pentry minsize="41" maxsize="48">
<addr space="join" piece6="RAX" piece5="RBX" piece4="RCX" piece3="RDI" piece2="RSI" piece1="R8"/>
</pentry>
<pentry minsize="49" maxsize="56">
<addr space="join" piece7="RAX" piece6="RBX" piece5="RCX" piece4="RDI" piece3="RSI" piece2="R8" piece1="R9"/>
</pentry>
<pentry minsize="57" maxsize="64">
<addr space="join" piece8="RAX" piece7="RBX" piece6="RCX" piece5="RDI" piece4="RSI" piece3="R8" piece2="R9" piece1="R10"/>
</pentry>
<pentry minsize="65" maxsize="72">
<addr space="join" piece9="RAX" piece8="RBX" piece7="RCX" piece6="RDI" piece5="RSI" piece4="R8" piece3="R9" piece2="R10" piece1="R11"/>
</pentry>
</output>
<killedbycall>
<register name="RAX"/>
<register name="RBX"/>
<register name="RCX"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="R8"/>
<register name="R9"/>
<register name="R10"/>
<register name="R11"/>
</killedbycall>
<unaffected>
<register name="RSP"/>
<register name="RBP"/>
<register name="R14"/>
</unaffected>
</prototype>
</default_proto>
<prototype name="abi0" extrapop="8" stackshift="8">
<input>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="8" space="stack"/>
</pentry>
</input>
<output>
</output>
<killedbycall>
<register name="RAX"/>
<register name="RBX"/>
<register name="RCX"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="R8"/>
<register name="R9"/>
<register name="R10"/>
<register name="R11"/>
</killedbycall>
<unaffected>
<register name="RSP"/>
<register name="RBP"/>
<register name="R14"/>
</unaffected>
</prototype>
<prototype name="duffzero" extrapop="8" stackshift="8">
<input>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
</output>
<killedbycall>
<register name="RDI"/>
</killedbycall>
<unaffected>
<register name="RSP"/>
<register name="RBP"/>
<register name="R14"/>
</unaffected>
</prototype>
<prototype name="duffcopy" extrapop="8" stackshift="8">
<input>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RSI"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="9" maxsize="16">
<addr space="join" piece2="RDI" piece1="RSI"/>
</pentry>
</output>
<killedbycall>
<register name="RDI"/>
<register name="RSI"/>
</killedbycall>
<unaffected>
<register name="RAX"/>
<register name="RBX"/>
<register name="RCX"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="R8"/>
<register name="R9"/>
<register name="R10"/>
<register name="R11"/>
<register name="RSP"/>
<register name="RBP"/>
<register name="R14"/>
</unaffected>
</prototype>
<prototype name="__stdcall" extrapop="8" stackshift="8">
<!-- Derived from "System V Application Binary Interface AMD64 Architecture Processor Supplement" April 2016 -->
<input>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM4_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM5_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM6_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM7_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RSI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="8" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
<pentry minsize="9" maxsize="16">
<addr space="join" piece1="RDX" piece2="RAX"/>
</pentry>
</output>
<killedbycall>
<register name="RAX"/>
<register name="RDX"/>
<register name="XMM0"/>
</killedbycall>
<unaffected>
<register name="RBX"/>
<register name="RSP"/>
<register name="RBP"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
</unaffected>
</prototype>
<prototype name="MSABI" extrapop="8" stackshift="8">
<input pointermax="8">
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="40" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="8"/>
<register name="RBX"/>
<register name="RBP"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="RSP"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="RAX"/>
<register name="XMM0"/>
</killedbycall>
<localrange>
<range space="stack" first="0xfffffffffff0bdc1" last="0xffffffffffffffff"/>
<range space="stack" first="8" last="39"/>
</localrange>
</prototype>
<prototype name="syscall" extrapop="8" stackshift="8">
<input pointermax="8">
<pentry minsize="1" maxsize="8">
<register name="RDI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RSI"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R10"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="8"/>
<register name="RBX"/>
<register name="RDX"/>
<register name="RBP"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="RSP"/>
<register name="R8"/>
<register name="R9"/>
<register name="R10"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="RCX"/>
<register name="R11"/>
</killedbycall>
</prototype>
</compiler_spec>

View File

@@ -0,0 +1,10 @@
<golang>
<!-- see https://github.com/golang/go/blob/master/src/internal/abi/abi_amd64.go -->
<register_info versions="V1_17,V1_18,V1_19,V1_20"> <!-- "all", or comma list of: V1_2,V1_16,V1_17,V1_18 -->
<int_registers list="RAX,RBX,RCX,RDI,RSI,R8,R9,R10,R11"/>
<float_registers list="XMM0,XMM1,XMM2,XMM3,XMM4,XMM5,XMM6,XMM7,XMM8,XMM9,XMM10,XMM11,XMM12,XMM13,XMM14"/>
<stack initialoffset="8" maxalign="8"/>
<current_goroutine register="R14"/>
<zero_register register="XMM15"/>
</register_info>
</golang>

View File

@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- see: -->
<!-- https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions#register-usage -->
<!-- https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention -->
<!-- https://docs.microsoft.com/en-us/cpp/c-runtime-library/direction-flag -->
<!-- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall -->
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" />
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="8" />
<pointer_size value="8" />
<wchar_size value="2" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="4" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="8" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
<bitfield_packing>
<use_MS_convention value="true"/>
</bitfield_packing>
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="RSP" space="ram"/>
<returnaddress>
<varnode space="stack" offset="0" size="8"/>
</returnaddress>
<default_proto>
<prototype name="__fastcall" extrapop="8" stackshift="8">
<input pointermax="8">
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
</group>
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
</group>
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
</group>
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
</group>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="40" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="8"/>
<register name="RBX"/>
<register name="RBP"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="RSP"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
<register name="DF"/>
<register name="GS_OFFSET"/>
<register name="XMM6"/>
<register name="XMM7"/>
<register name="XMM8"/>
<register name="XMM9"/>
<register name="XMM10"/>
<register name="XMM11"/>
<register name="XMM12"/>
<register name="XMM13"/>
<register name="XMM14"/>
<register name="XMM15"/>
</unaffected>
<killedbycall>
<register name="RAX"/>
<register name="XMM0"/>
</killedbycall>
<localrange>
<range space="stack" first="0xfffffffffff0bdc1" last="0xffffffffffffffff"/>
<range space="stack" first="8" last="39"/>
</localrange>
</prototype>
</default_proto>
<prototype name="__thiscall" extrapop="8" stackshift="8">
<input pointermax="8" thisbeforeretpointer="true">
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RCX"/>
</pentry>
</group>
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM1_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RDX"/>
</pentry>
</group>
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM2_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R8"/>
</pentry>
</group>
<group>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM3_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="R9"/>
</pentry>
</group>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="40" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="XMM0_Qa"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="RAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="8"/>
<register name="RBX"/>
<register name="RBP"/>
<register name="RDI"/>
<register name="RSI"/>
<register name="RSP"/>
<register name="R12"/>
<register name="R13"/>
<register name="R14"/>
<register name="R15"/>
<register name="DF"/>
<register name="GS_OFFSET"/>
<register name="XMM6"/>
<register name="XMM7"/>
<register name="XMM8"/>
<register name="XMM9"/>
<register name="XMM10"/>
<register name="XMM11"/>
<register name="XMM12"/>
<register name="XMM13"/>
<register name="XMM14"/>
<register name="XMM15"/>
</unaffected>
<killedbycall>
<register name="RAX"/>
<register name="XMM0"/>
</killedbycall>
<localrange>
<range space="stack" first="0xfffffffffff0bdc1" last="0xffffffffffffffff"/>
<range space="stack" first="8" last="39"/>
</localrange>
</prototype>
<modelalias name="__cdecl" parent="__fastcall"/>
<modelalias name="__stdcall" parent="__fastcall"/>
<callfixup name="alloca_probe">
<target name="_alloca_probe"/>
<target name="_alloca_probe2"/>
<target name="__chkstk"/>
<target name="__chkstk2"/>
<target name="___chkstk_ms"/>
<pcode>
<body><![CDATA[
RSP = RSP + 0;
]]></body>
</pcode>
</callfixup>
<callfixup name="guard_dispatch_icall">
<target name="_guard_dispatch_icall"/>
<pcode>
<body><![CDATA[
call [RAX];
]]></body>
</pcode>
</callfixup>
</compiler_spec>

View File

@@ -0,0 +1,34 @@
<dwarf>
<register_mappings>
<register_mapping dwarf="0" ghidra="RAX"/>
<register_mapping dwarf="1" ghidra="RDX"/>
<register_mapping dwarf="2" ghidra="RCX"/>
<register_mapping dwarf="3" ghidra="RBX"/>
<register_mapping dwarf="4" ghidra="RSI"/>
<register_mapping dwarf="5" ghidra="RDI"/>
<register_mapping dwarf="6" ghidra="RBP"/>
<register_mapping dwarf="7" ghidra="RSP" stackpointer="true"/>
<register_mapping dwarf="8" ghidra="R8" auto_count="8"/> <!-- R8..R15 -->
<register_mapping dwarf="16" ghidra="RIP"/>
<register_mapping dwarf="17" ghidra="XMM0" auto_count="16"/> <!-- XMM0..XMM15 -->
<register_mapping dwarf="33" ghidra="ST0" auto_count="8"/> <!-- ST0..ST7 -->
<register_mapping dwarf="41" ghidra="MM0" auto_count="8"/> <!-- MM0..MM7 -->
<register_mapping dwarf="49" ghidra="rflags"/>
<register_mapping dwarf="50" ghidra="ES"/>
<register_mapping dwarf="51" ghidra="CS"/>
<register_mapping dwarf="52" ghidra="SS"/>
<register_mapping dwarf="53" ghidra="DS"/>
<register_mapping dwarf="54" ghidra="FS"/>
<register_mapping dwarf="55" ghidra="GS"/>
<!-- <register_mapping dwarf="58" ghidra="FSBASE"/> **not implemented** -->
<!-- <register_mapping dwarf="59" ghidra="GSBASE"/> **not implemented** -->
<register_mapping dwarf="62" ghidra="TR"/>
<register_mapping dwarf="63" ghidra="LDTR"/>
<register_mapping dwarf="64" ghidra="MXCSR"/>
<!-- <register_mapping dwarf="65" ghidra="FCW"/> **not implemented** -->
<!-- <register_mapping dwarf="66" ghidra="FSW"/> **not implemented** -->
<!-- <register_mapping dwarf="68" ghidra="XMM16" auto_count="16"/> **not implemented yet** --> <!-- XMM16..XMM31 -->
<!-- <register_mapping dwarf="118" ghidra="K0" auto_count="8"/> **not implemented yet** -->
</register_mappings>
<call_frame_cfa value="8"/>
</dwarf>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<processor_spec>
<properties>
<property key="useOperandReferenceAnalyzerSwitchTables" value="true"/>
<property key="assemblyRating:x86:LE:64:default" value="GOLD"/>
</properties>
<programcounter register="RIP"/>
<context_data>
<context_set space="ram">
<set name="addrsize" val="2"/>
<set name="opsize" val="1"/>
<set name="rexprefix" val="0"/>
<set name="longMode" val="1"/>
</context_set>
<tracked_set space="ram">
<set name="DF" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="DR0" group="DEBUG"/>
<register name="DR1" group="DEBUG"/>
<register name="DR2" group="DEBUG"/>
<register name="DR3" group="DEBUG"/>
<register name="DR4" group="DEBUG"/>
<register name="DR5" group="DEBUG"/>
<register name="DR6" group="DEBUG"/>
<register name="DR7" group="DEBUG"/>
<register name="DR8" group="DEBUG"/>
<register name="DR9" group="DEBUG"/>
<register name="DR10" group="DEBUG"/>
<register name="DR11" group="DEBUG"/>
<register name="DR12" group="DEBUG"/>
<register name="DR13" group="DEBUG"/>
<register name="DR14" group="DEBUG"/>
<register name="DR15" group="DEBUG"/>
<register name="CR0" group="CONTROL"/>
<register name="CR1" group="CONTROL"/>
<register name="CR2" group="CONTROL"/>
<register name="CR3" group="CONTROL"/>
<register name="CR4" group="CONTROL"/>
<register name="CR5" group="CONTROL"/>
<register name="CR6" group="CONTROL"/>
<register name="CR7" group="CONTROL"/>
<register name="CR8" group="CONTROL"/>
<register name="CR9" group="CONTROL"/>
<register name="CR10" group="CONTROL"/>
<register name="CR11" group="CONTROL"/>
<register name="CR12" group="CONTROL"/>
<register name="CR13" group="CONTROL"/>
<register name="CR14" group="CONTROL"/>
<register name="CR15" group="CONTROL"/>
<register name="C0" group="Cx"/>
<register name="C1" group="Cx"/>
<register name="C2" group="Cx"/>
<register name="C3" group="Cx"/>
<register name="ST0" group="ST"/>
<register name="ST1" group="ST"/>
<register name="ST2" group="ST"/>
<register name="ST3" group="ST"/>
<register name="ST4" group="ST"/>
<register name="ST5" group="ST"/>
<register name="ST6" group="ST"/>
<register name="ST7" group="ST"/>
<register name="FPUControlWord" group="FPU"/>
<register name="FPUStatusWord" group="FPU"/>
<register name="FPUTagWord" group="FPU"/>
<register name="FPUDataPointer" group="FPU"/>
<register name="FPUInstructionPointer" group="FPU"/>
<register name="FPULastInstructionOpcode" group="FPU"/>
<register name="MM0" group="MMX"/>
<register name="MM1" group="MMX"/>
<register name="MM2" group="MMX"/>
<register name="MM3" group="MMX"/>
<register name="MM4" group="MMX"/>
<register name="MM5" group="MMX"/>
<register name="MM6" group="MMX"/>
<register name="MM7" group="MMX"/>
<register name="YMM0" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM1" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM2" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM3" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM4" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM5" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM6" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM7" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM8" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM9" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM10" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM11" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM12" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM13" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM14" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM15" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="XMM0" vector_lane_sizes="1,2,4,8"/>
<register name="XMM1" vector_lane_sizes="1,2,4,8"/>
<register name="XMM2" vector_lane_sizes="1,2,4,8"/>
<register name="XMM3" vector_lane_sizes="1,2,4,8"/>
<register name="XMM4" vector_lane_sizes="1,2,4,8"/>
<register name="XMM5" vector_lane_sizes="1,2,4,8"/>
<register name="XMM6" vector_lane_sizes="1,2,4,8"/>
<register name="XMM7" vector_lane_sizes="1,2,4,8"/>
<register name="XMM8" vector_lane_sizes="1,2,4,8"/>
<register name="XMM9" vector_lane_sizes="1,2,4,8"/>
<register name="XMM10" vector_lane_sizes="1,2,4,8"/>
<register name="XMM11" vector_lane_sizes="1,2,4,8"/>
<register name="XMM12" vector_lane_sizes="1,2,4,8"/>
<register name="XMM13" vector_lane_sizes="1,2,4,8"/>
<register name="XMM14" vector_lane_sizes="1,2,4,8"/>
<register name="XMM15" vector_lane_sizes="1,2,4,8"/>
<register name="CF" group="FLAGS"/>
<register name="F1" group="FLAGS"/>
<register name="PF" group="FLAGS"/>
<register name="F3" group="FLAGS"/>
<register name="AF" group="FLAGS"/>
<register name="F5" group="FLAGS"/>
<register name="ZF" group="FLAGS"/>
<register name="SF" group="FLAGS"/>
<register name="TF" group="FLAGS"/>
<register name="IF" group="FLAGS"/>
<register name="DF" group="FLAGS"/>
<register name="OF" group="FLAGS"/>
<register name="IOPL" group="FLAGS"/>
<register name="NT" group="FLAGS"/>
<register name="F15" group="FLAGS"/>
<register name="RF" group="FLAGS"/>
<register name="VM" group="FLAGS"/>
<register name="AC" group="FLAGS"/>
<register name="VIF" group="FLAGS"/>
<register name="VIP" group="FLAGS"/>
<register name="ID" group="FLAGS"/>
<register name="rflags" group="FLAGS"/>
<register name="eflags" group="FLAGS"/>
<register name="flags" group="FLAGS"/>
<register name="bit64" hidden="true"/>
<register name="segover" hidden="true"/>
<register name="repneprefx" hidden="true"/>
<register name="repprefx" hidden="true"/>
<register name="rexWprefix" hidden="true"/>
<register name="rexRprefix" hidden="true"/>
<register name="rexXprefix" hidden="true"/>
<register name="rexBprefix" hidden="true"/>
<register name="xmmTmp1" hidden="true"/>
<register name="xmmTmp1_Qa" hidden="true"/>
<register name="xmmTmp1_Da" hidden="true"/>
<register name="xmmTmp1_Db" hidden="true"/>
<register name="xmmTmp1_Qb" hidden="true"/>
<register name="xmmTmp1_Dc" hidden="true"/>
<register name="xmmTmp1_Dd" hidden="true"/>
<register name="xmmTmp2" hidden="true"/>
<register name="xmmTmp2_Qa" hidden="true"/>
<register name="xmmTmp2_Da" hidden="true"/>
<register name="xmmTmp2_Db" hidden="true"/>
<register name="xmmTmp2_Qb" hidden="true"/>
<register name="xmmTmp2_Dc" hidden="true"/>
<register name="xmmTmp2_Dd" hidden="true"/>
<register name="rexprefix" hidden="true"/>
</register_data>
</processor_spec>

View File

@@ -0,0 +1,6 @@
@define IA64 "IA64"
@include "x86.slaspec"
with : lockprefx=0 {
@include "sgx.sinc"
@include "fma.sinc"
}

View File

@@ -0,0 +1,34 @@
<dwarf>
<register_mappings>
<register_mapping dwarf="0" ghidra="EAX"/>
<register_mapping dwarf="1" ghidra="ECX"/>
<register_mapping dwarf="2" ghidra="EDX"/>
<register_mapping dwarf="3" ghidra="EBX"/>
<register_mapping dwarf="4" ghidra="ESP" stackpointer="true"/>
<register_mapping dwarf="5" ghidra="EBP"/>
<register_mapping dwarf="6" ghidra="ESI"/>
<register_mapping dwarf="7" ghidra="EDI"/>
<register_mapping dwarf="8" ghidra="EIP"/>
<register_mapping dwarf="9" ghidra="eflags"/>
<!-- <register_mapping dwarf="10" ghidra="TRAPNO"/> **not implemented** -->
<register_mapping dwarf="11" ghidra="ST0" auto_count="8"/> <!-- ST0..ST7 -->
<register_mapping dwarf="21" ghidra="XMM0" auto_count="8"/> <!-- XMM0..XMM7 -->
<register_mapping dwarf="29" ghidra="MM0" auto_count="8"/> <!-- MM0..MM7 -->
<!-- <register_mapping dwarf="37" ghidra="FCW"/> **not implemented** -->
<!-- <register_mapping dwarf="38" ghidra="FSW"/> **not implemented** -->
<register_mapping dwarf="39" ghidra="MXCSR"/>
<register_mapping dwarf="40" ghidra="ES"/>
<register_mapping dwarf="41" ghidra="CS"/>
<register_mapping dwarf="42" ghidra="SS"/>
<register_mapping dwarf="43" ghidra="DS"/>
<register_mapping dwarf="44" ghidra="FS"/>
<register_mapping dwarf="45" ghidra="GS"/>
<register_mapping dwarf="48" ghidra="TR"/>
<register_mapping dwarf="49" ghidra="LDTR"/>
</register_mappings>
<call_frame_cfa value="4"/>
</dwarf>

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_definitions>
<language processor="x86"
endian="little"
size="32"
variant="default"
version="2.14"
slafile="x86.sla"
processorspec="x86.pspec"
manualindexfile="../manuals/x86.idx"
id="x86:LE:32:default">
<description>Intel/AMD 32-bit x86</description>
<compiler name="Visual Studio" spec="x86win.cspec" id="windows"/>
<compiler name="clang" spec="x86win.cspec" id="clangwindows"/>
<compiler name="gcc" spec="x86gcc.cspec" id="gcc"/>
<compiler name="Borland C++" spec="x86borland.cspec" id="borlandcpp"/>
<compiler name="Delphi" spec="x86delphi.cspec" id="borlanddelphi"/>
<compiler name="golang" spec="x86-32-golang.cspec" id="golang"/>
<external_name tool="gnu" name="i386:intel"/>
<external_name tool="IDA-PRO" name="8086"/>
<external_name tool="IDA-PRO" name="80486p"/>
<external_name tool="IDA-PRO" name="80586p"/>
<external_name tool="IDA-PRO" name="80686p"/>
<external_name tool="IDA-PRO" name="k62"/>
<external_name tool="IDA-PRO" name="p2"/>
<external_name tool="IDA-PRO" name="p3"/>
<external_name tool="IDA-PRO" name="athlon"/>
<external_name tool="IDA-PRO" name="p4"/>
<external_name tool="IDA-PRO" name="metapc"/>
<external_name tool="DWARF.register.mapping.file" name="x86.dwarf"/>
<external_name tool="Golang.register.info.file" name="x86-32-golang.register.info"/>
</language>
<language processor="x86"
endian="little"
size="32"
variant="System Management Mode"
version="2.14"
slafile="x86.sla"
processorspec="x86-16.pspec"
manualindexfile="../manuals/x86.idx"
id="x86:LE:32:System Management Mode">
<description>Intel/AMD 32-bit x86 System Management Mode</description>
<compiler name="default" spec="x86-16.cspec" id="default"/>
<external_name tool="DWARF.register.mapping.file" name="x86.dwarf"/>
</language>
<language processor="x86"
endian="little"
size="16"
variant="Real Mode"
version="2.14"
slafile="x86.sla"
processorspec="x86-16-real.pspec"
manualindexfile="../manuals/x86.idx"
id="x86:LE:16:Real Mode">
<description>Intel/AMD 16-bit x86 Real Mode</description>
<compiler name="default" spec="x86-16.cspec" id="default"/>
<external_name tool="IDA-PRO" name="8086"/>
<external_name tool="IDA-PRO" name="8086r"/>
<external_name tool="IDA-PRO" name="80386r"/>
<external_name tool="IDA-PRO" name="80486r"/>
<external_name tool="IDA-PRO" name="80586r"/>
<external_name tool="IDA-PRO" name="metapc"/>
<external_name tool="gnu" name="i8086"/>
<external_name tool="gdis.disassembler.options.file" name="x86-16.gdis"/>
</language>
<language processor="x86"
endian="little"
size="16"
variant="Protected Mode"
version="2.14"
slafile="x86.sla"
processorspec="x86-16.pspec"
manualindexfile="../manuals/x86.idx"
id="x86:LE:16:Protected Mode">
<description>Intel/AMD 16-bit x86 Protected Mode</description>
<compiler name="default" spec="x86-16.cspec" id="default"/>
<external_name tool="IDA-PRO" name="8086p"/>
<external_name tool="gnu" name="i8086"/>
<external_name tool="gdis.disassembler.options.file" name="x86-16.gdis"/>
</language>
<language processor="x86"
endian="little"
size="64"
variant="default"
version="2.14"
slafile="x86-64.sla"
processorspec="x86-64.pspec"
manualindexfile="../manuals/x86.idx"
id="x86:LE:64:default">
<description>Intel/AMD 64-bit x86</description>
<compiler name="Visual Studio" spec="x86-64-win.cspec" id="windows"/>
<compiler name="clang" spec="x86-64-win.cspec" id="clangwindows"/>
<compiler name="gcc" spec="x86-64-gcc.cspec" id="gcc"/>
<compiler name="golang" spec="x86-64-golang.cspec" id="golang"/>
<external_name tool="gnu" name="i386:x86-64:intel"/>
<external_name tool="gnu" name="i386:x86-64"/>
<external_name tool="IDA-PRO" name="metapc"/>
<external_name tool="DWARF.register.mapping.file" name="x86-64.dwarf"/>
<external_name tool="Golang.register.info.file" name="x86-64-golang.register.info"/>
</language>
<language processor="x86"
endian="little"
size="64"
variant="compat32"
version="2.14"
slafile="x86-64.sla"
processorspec="x86-64-compat32.pspec"
manualindexfile="../manuals/x86.idx"
id="x86:LE:64:compat32">
<description>Intel/AMD 64-bit x86 in 32-bit compatibility mode (long mode off)</description>
<compiler name="Visual Studio" spec="x86win.cspec" id="windows"/>
<compiler name="gcc" spec="x86gcc.cspec" id="gcc"/>
<external_name tool="DWARF.register.mapping.file" name="x86.dwarf"/>
</language>
</language_definitions>

View File

@@ -0,0 +1,86 @@
<opinions>
<!-- NOTE: variant="default" is specified for 64-bit to give preference to the default variant -->
<constraint loader="Portable Executable (PE)">
<constraint compilerSpecID="windows">
<constraint primary="332" processor="x86" endian="little" size="32" />
<constraint primary="333" processor="x86" endian="little" size="32" />
<constraint primary="334" processor="x86" endian="little" size="32" />
<constraint primary="34404" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint compilerSpecID="clangwindows">
<constraint primary="332" secondary="clang" processor="x86" endian="little" size="32" />
<constraint primary="333" secondary="clang" processor="x86" endian="little" size="32" />
<constraint primary="334" secondary="clang" processor="x86" endian="little" size="32" />
<constraint primary="34404" secondary="clang" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint compilerSpecID="borlandcpp">
<constraint primary="332" secondary="borlandcpp" processor="x86" endian="little" size="32" />
<constraint primary="333" secondary="borlandcpp" processor="x86" endian="little" size="32" />
<constraint primary="334" secondary="borlandcpp" processor="x86" endian="little" size="32" />
</constraint>
<constraint compilerSpecID="borlanddelphi">
<constraint primary="332" secondary="borlanddelphi" processor="x86" endian="little" size="32" />
<constraint primary="333" secondary="borlanddelphi" processor="x86" endian="little" size="32" />
<constraint primary="334" secondary="borlanddelphi" processor="x86" endian="little" size="32" />
</constraint>
<constraint compilerSpecID="golang">
<constraint primary="332" secondary="golang" processor="x86" endian="little" size="32" />
<constraint primary="34404" secondary="golang" processor="x86" endian="little" size="64" variant="default" />
</constraint>
</constraint>
<constraint loader="Debug Symbols (DBG)" compilerSpecID="windows">
<constraint primary="332" processor="x86" endian="little" size="32" />
<constraint primary="333" processor="x86" endian="little" size="32" />
<constraint primary="334" processor="x86" endian="little" size="32" />
<constraint primary="34404" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="gcc">
<constraint primary="3" processor="x86" endian="little" size="32" />
<constraint primary="62" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint loader="Module Definition (DEF)" compilerSpecID="windows">
<constraint primary="0" processor="x86" endian="little" size="32" />
</constraint>
<constraint loader="Program Mapfile (MAP)" compilerSpecID="windows">
<constraint primary="0" processor="x86" endian="little" size="32" />
</constraint>
<constraint loader="Old-style DOS Executable (MZ)" compilerSpecID="default">
<constraint primary="23117" processor="x86" endian="little" size="16" variant="Real Mode"/>
</constraint>
<constraint loader="New Executable (NE)" compilerSpecID="default">
<constraint primary="17742" processor="x86" endian="little" size="16" variant="Protected Mode"/>
</constraint>
<constraint loader="Mac OS X Mach-O" compilerSpecID="gcc">
<constraint primary="7" processor="x86" endian="little" size="32" />
<constraint primary="16777223" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint loader="DYLD Cache" compilerSpecID="gcc">
<constraint primary="x86_64" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint loader="Common Object File Format (COFF)" compilerSpecID="gcc">
<constraint primary="332" processor="x86" endian="little" size="32" />
<constraint primary="-31132" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint loader="MS Common Object File Format (COFF)" compilerSpecID="windows">
<constraint primary="332" processor="x86" endian="little" size="32" />
<constraint primary="-31132" processor="x86" endian="little" size="64" variant="default" />
</constraint>
<constraint loader="Assembler Output (AOUT)" compilerSpecID="gcc">
<constraint primary="134" processor="x86" endian="little" size="32" />
</constraint>
<constraint loader="Relocatable Object Module Format (OMF)">
<constraint compilerSpecID="windows">
<constraint primary="32bit" processor="x86" endian="little" size="32" />
</constraint>
<constraint compilerSpecID="default">
<constraint primary="16bit" processor="x86" endian="little" size="16" />
</constraint>
<constraint compilerSpecID="borlandcpp">
<constraint primary="32bit" secondary="borlandcpp" processor="x86" endian="little" size="32" />
<constraint primary="32bit" secondary="codegearcpp" processor="x86" endian="little" size="32" />
</constraint>
<constraint compilerSpecID="borlanddelphi">
<constraint primary="32bit" secondary="borlanddelphi" processor="x86" endian="little" size="32" />
</constraint>
</constraint>
</opinions>

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<processor_spec>
<properties>
<property key="useOperandReferenceAnalyzerSwitchTables" value="true"/>
<property key="assemblyRating:x86:LE:32:default" value="GOLD"/>
</properties>
<programcounter register="EIP"/>
<incidentalcopy>
<register name="ST0"/>
<register name="ST1"/>
<register name="ST2"/>
<register name="ST3"/>
<register name="ST4"/>
<register name="ST5"/>
<register name="ST6"/>
<register name="ST7"/>
</incidentalcopy>
<context_data>
<context_set space="ram">
<set name="addrsize" val="1"/>
<set name="opsize" val="1"/>
</context_set>
<tracked_set space="ram">
<set name="DF" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="DR0" group="DEBUG"/>
<register name="DR1" group="DEBUG"/>
<register name="DR2" group="DEBUG"/>
<register name="DR3" group="DEBUG"/>
<register name="DR4" group="DEBUG"/>
<register name="DR5" group="DEBUG"/>
<register name="DR6" group="DEBUG"/>
<register name="DR7" group="DEBUG"/>
<register name="CR0" group="CONTROL"/>
<register name="CR2" group="CONTROL"/>
<register name="CR3" group="CONTROL"/>
<register name="CR4" group="CONTROL"/>
<register name="ST0" group="ST"/>
<register name="ST1" group="ST"/>
<register name="ST2" group="ST"/>
<register name="ST3" group="ST"/>
<register name="ST4" group="ST"/>
<register name="ST5" group="ST"/>
<register name="ST6" group="ST"/>
<register name="ST7" group="ST"/>
<register name="FPUControlWord" group="FPU"/>
<register name="FPUStatusWord" group="FPU"/>
<register name="FPUTagWord" group="FPU"/>
<register name="FPUInstructionPointer" group="FPU"/>
<register name="FPULastInstructionOpcode" group="FPU"/>
<register name="FPUDataPointer" group="FPU"/>
<register name="MM0" group="MMX"/>
<register name="MM1" group="MMX"/>
<register name="MM2" group="MMX"/>
<register name="MM3" group="MMX"/>
<register name="MM4" group="MMX"/>
<register name="MM5" group="MMX"/>
<register name="MM6" group="MMX"/>
<register name="MM7" group="MMX"/>
<register name="YMM0" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM1" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM2" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM3" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM4" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM5" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM6" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM7" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM8" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM9" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM10" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM11" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM12" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM13" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM14" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="YMM15" group="AVX" vector_lane_sizes="1,2,4,8"/>
<register name="XMM0" vector_lane_sizes="1,2,4,8"/>
<register name="XMM1" vector_lane_sizes="1,2,4,8"/>
<register name="XMM2" vector_lane_sizes="1,2,4,8"/>
<register name="XMM3" vector_lane_sizes="1,2,4,8"/>
<register name="XMM4" vector_lane_sizes="1,2,4,8"/>
<register name="XMM5" vector_lane_sizes="1,2,4,8"/>
<register name="XMM6" vector_lane_sizes="1,2,4,8"/>
<register name="XMM7" vector_lane_sizes="1,2,4,8"/>
<register name="XMM8" vector_lane_sizes="1,2,4,8"/>
<register name="XMM9" vector_lane_sizes="1,2,4,8"/>
<register name="XMM10" vector_lane_sizes="1,2,4,8"/>
<register name="XMM11" vector_lane_sizes="1,2,4,8"/>
<register name="XMM12" vector_lane_sizes="1,2,4,8"/>
<register name="XMM13" vector_lane_sizes="1,2,4,8"/>
<register name="XMM14" vector_lane_sizes="1,2,4,8"/>
<register name="XMM15" vector_lane_sizes="1,2,4,8"/>
<register name="CF" group="FLAGS"/>
<register name="F1" group="FLAGS"/>
<register name="PF" group="FLAGS"/>
<register name="F3" group="FLAGS"/>
<register name="AF" group="FLAGS"/>
<register name="F5" group="FLAGS"/>
<register name="ZF" group="FLAGS"/>
<register name="SF" group="FLAGS"/>
<register name="TF" group="FLAGS"/>
<register name="IF" group="FLAGS"/>
<register name="DF" group="FLAGS"/>
<register name="OF" group="FLAGS"/>
<register name="IOPL" group="FLAGS"/>
<register name="NT" group="FLAGS"/>
<register name="F15" group="FLAGS"/>
<register name="RF" group="FLAGS"/>
<register name="VM" group="FLAGS"/>
<register name="AC" group="FLAGS"/>
<register name="VIF" group="FLAGS"/>
<register name="VIP" group="FLAGS"/>
<register name="ID" group="FLAGS"/>
<register name="eflags" group="FLAGS"/>
<register name="flags" group="FLAGS"/>
<register name="repneprefx" hidden="true"/>
<register name="segover" hidden="true"/>
</register_data>
</processor_spec>

View File

@@ -0,0 +1,19 @@
@include "ia.sinc"
@include "lockable.sinc"
with : lockprefx=0 {
@include "avx.sinc"
@include "avx_manual.sinc"
@include "avx2.sinc"
@include "avx2_manual.sinc"
@include "adx.sinc"
@include "clwb.sinc"
@include "pclmulqdq.sinc"
@include "mpx.sinc"
@include "lzcnt.sinc"
@include "bmi1.sinc"
@include "bmi2.sinc"
@include "sha.sinc"
@include "smx.sinc"
@include "cet.sinc"
@include "rdrand.sinc"
}

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" />
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="4" />
<pointer_size value="4" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="4" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="10" /> <!-- aligned-length=12 -->
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="4" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="ESP" space="ram"/>
<default_proto>
<prototype name="__fastcall" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
</prototype>
</default_proto>
<prototype name="__stdcall" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
<prototype name="__cdecl" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
<prototype name="__thiscall" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<resolveprototype name="__stdcall/__fastcall">
<model name="__stdcall"/> <!-- The default case -->
<model name="__fastcall"/>
</resolveprototype>
<eval_current_prototype name="__stdcall/__fastcall"/>
</compiler_spec>

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<global>
<range space="ram"/>
</global>
<stackpointer register="ESP" space="ram"/>
<default_proto>
<prototype name="__register" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
</prototype>
</default_proto>
<!--there is also a "pascal" calling convention, which is the same as stdcall except that arguments are pushed left-to-right-->
<prototype name="__stdcall" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
<prototype name="__cdecl" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
</compiler_spec>

View File

@@ -0,0 +1,463 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<machine_alignment value="2" />
<default_alignment value="1" />
<default_pointer_alignment value="4" />
<pointer_size value="4" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="4" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="10" /> <!-- aligned-length=12 -->
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="4" />
<entry size="16" alignment="16" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
<range space="OTHER"/>
</global>
<stackpointer register="ESP" space="ram"/>
<returnaddress>
<varnode space="stack" offset="0" size="4"/>
</returnaddress>
<default_proto>
<prototype name="__cdecl" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
</default_proto>
<prototype name="__cdeclf" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="10">
<register name="ST0"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__thiscall" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__regparm3" extrapop="4" stackshift="4"> <!-- Used particularly by linux kernel -->
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__regparm2" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="__regparm1" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="EAX"/>
</likelytrash>
</prototype>
<prototype name="syscall" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="EBX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="ESI"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDI"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EBP"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<register name="EBX"/>
<register name="ECX"/>
<register name="EDX"/>
<register name="EBP"/>
<register name="EDI"/>
<register name="ESI"/>
<register name="ESP"/>
<register name="DF"/>
</unaffected>
<killedbycall>
<register name="EAX"/>
</killedbycall>
</prototype>
<prototype name="processEntry" extrapop="0" stackshift="0">
<input pointermax="4">
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
</output>
<unaffected>
<register name="ESP"/>
</unaffected>
<!-- Functions with this prototype don't have a return address. But, if we don't specify one, this prototype will
use the default, which is to have the return address on the stack. That conflicts with how this prototype actually
uses the stack, so we set a fake return address at a EBP, which is unspecified at process entry -->
<returnaddress>
<register name="EBP"/>
</returnaddress>
</prototype>
<resolveprototype name="__cdecl/__regparm">
<model name="__cdecl"/> <!-- The default case -->
<model name="__regparm3"/>
<model name="__regparm2"/>
<model name="__regparm1"/>
</resolveprototype>
<eval_current_prototype name="__cdecl/__regparm"/>
<callfixup name="get_pc_thunk_ax">
<target name="__i686.get_pc_thunk.ax"/>
<target name="__x86.get_pc_thunk.ax"/>
<pcode>
<body><![CDATA[
EAX = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<callfixup name="get_pc_thunk.bp">
<target name="__i686.get_pc_thunk.bp"/>
<target name="__x86.get_pc_thunk.bp"/>
<pcode>
<body><![CDATA[
EBP = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<callfixup name="get_pc_thunk_bx">
<target name="__i686.get_pc_thunk.bx"/>
<target name="__x86.get_pc_thunk.bx"/>
<pcode>
<body><![CDATA[
EBX = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<callfixup name="get_pc_thunk_cx">
<target name="__i686.get_pc_thunk.cx"/>
<target name="__x86.get_pc_thunk.cx"/>
<pcode>
<body><![CDATA[
ECX = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<callfixup name="get_pc_thunk_dx">
<target name="__i686.get_pc_thunk.dx"/>
<target name="__x86.get_pc_thunk.dx"/>
<pcode>
<body><![CDATA[
EDX = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<callfixup name="get_pc_thunk_si">
<target name="__i686.get_pc_thunk.si"/>
<target name="__x86.get_pc_thunk.si"/>
<pcode>
<body><![CDATA[
ESI = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_return_thunk">
<target name="__x86_return_thunk"/>
<pcode>
<body><![CDATA[
EIP = *:4 ESP;
ESP = ESP + 4;
return [EIP];
]]></body>
</pcode>
</callfixup>
<callfixup name="fentry">
<target name="__fentry__"/>
<pcode>
<body><![CDATA[
temp:1 = 0;
]]></body>
</pcode>
</callfixup>
<callfixup name="mcount">
<target name="mcount"/>
<pcode>
<body><![CDATA[
temp:1 = 0;
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_ebp">
<target name="__x86_indirect_thunk_ebp"/>
<pcode>
<body><![CDATA[
call [EBP];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_eax">
<target name="__x86_indirect_thunk_eax"/>
<pcode>
<body><![CDATA[
call [EAX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_ebx">
<target name="__x86_indirect_thunk_ebx"/>
<pcode>
<body><![CDATA[
call [EBX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_ecx">
<target name="__x86_indirect_thunk_ecx"/>
<pcode>
<body><![CDATA[
call [ECX];
]]></body>
</pcode>
</callfixup>
<callfixup name="x86_indirect_thunk_edx">
<target name="__x86_indirect_thunk_edx"/>
<pcode>
<body><![CDATA[
call [EDX];
]]></body>
</pcode>
</callfixup>
</compiler_spec>

View File

@@ -0,0 +1,388 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<absolute_max_alignment value="0" /> <!-- no maximum alignment -->
<machine_alignment value="8" />
<default_alignment value="1" />
<default_pointer_alignment value="4" />
<pointer_size value="4" />
<wchar_size value="2" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="4" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="8" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
<bitfield_packing>
<use_MS_convention value="true"/>
</bitfield_packing>
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="ESP" space="ram"/>
<returnaddress>
<varnode space="stack" offset="0" size="4"/>
</returnaddress>
<default_proto>
<prototype name="__stdcall" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
<register name="FS_OFFSET"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
</default_proto>
<prototype name="__cdecl" extrapop="4" stackshift="4">
<input>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
<register name="FS_OFFSET"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
<prototype name="__fastcall" extrapop="unknown" stackshift="4">
<input>
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EDX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
<register name="FS_OFFSET"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
<prototype name="__thiscall" extrapop="unknown" stackshift="4">
<input thisbeforeretpointer="true">
<pentry minsize="1" maxsize="4">
<register name="ECX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="4" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="4" maxsize="10" metatype="float" extension="float">
<register name="ST0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="EAX"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="EDX" piece2="EAX"/>
</pentry>
</output>
<unaffected>
<varnode space="ram" offset="0" size="4"/>
<register name="ESP"/>
<register name="EBP"/>
<register name="ESI"/>
<register name="EDI"/>
<register name="EBX"/>
<register name="DF"/>
<register name="FS_OFFSET"/>
</unaffected>
<killedbycall>
<register name="ECX"/>
<register name="EDX"/>
<register name="ST0"/>
<register name="ST1"/>
</killedbycall>
<likelytrash>
<register name="ECX"/>
</likelytrash>
</prototype>
<resolveprototype name="__fastcall/__thiscall/__stdcall">
<model name="__stdcall"/> <!-- The default case -->
<model name="__fastcall"/>
<model name="__thiscall"/>
</resolveprototype>
<eval_current_prototype name="__fastcall/__thiscall/__stdcall"/>
<!-- Injections for various compiler helper functions -->
<callfixup name="EH_prolog">
<target name="__EH_prolog"/>
<target name="_EH_prolog"/>
<target name="thunk_EH_prolog"/>
<pcode>
<body><![CDATA[
ESP = ESP - 4;
*:4 ESP = -1;
ESP = ESP - 4;
* ESP = EAX;
EAX = * FS_OFFSET;
ESP = ESP - 4;
* ESP = EAX;
* FS_OFFSET = ESP;
tmp = ESP + 12;
* tmp = EBP;
EBP = tmp;
]]></body>
</pcode>
</callfixup>
<callfixup name="EH_prolog3">
<target name="_EH_prolog3"/>
<target name="__EH_prolog3"/>
<target name="EH_prolog3_GS"/>
<target name="_EH_prolog3_GS"/>
<target name="__EH_prolog3_GS"/>
<target name="EH_prolog3_catch"/>
<target name="_EH_prolog3_catch"/>
<target name="__EH_prolog3_catch"/>
<target name="EH_prolog3_catch_GS"/>
<target name="_EH_prolog3_catch_GS"/>
<target name="__EH_prolog3_catch_GS"/>
<target name="EH_prolog3_catch"/>
<target name="_EH_prolog3_catch"/>
<target name="__EH_prolog3_catch"/>
<target name="EH_prolog3_catch_GS"/>
<target name="_EH_prolog3_catch_GS"/>
<target name="__EH_prolog3_catch_GS"/>
<pcode>
<body><![CDATA[
EBP = ESP + 4;
tmp = * EBP;
ESP = ESP - tmp;
ESP = ESP - 24;
]]></body>
</pcode>
</callfixup>
<callfixup name="EH_epilog3">
<target name="_EH_epilog3"/>
<target name="__EH_epilog3"/>
<target name="EH_epilog3_GS"/>
<target name="_EH_epilog3_GS"/>
<target name="__EH_epilog3_GS"/>
<target name="EH_epilog3_catch"/>
<target name="_EH_epilog3_catch"/>
<target name="__EH_epilog3_catch"/>
<target name="EH_epilog3_catch_GS"/>
<target name="_EH_epilog3_catch_GS"/>
<target name="FID_conflict:__EH_epilog3_GS"/>
<target name="FID_conflict:__EH_epilog3_catch"/>
<target name="FID_conflict:__EH_epilog3_catch_GS"/>
<target name="SEH_epilog"/>
<target name="_SEH_epilog"/>
<target name="__SEH_epilog"/>
<target name="SEH_epilog4"/>
<target name="_SEH_epilog4"/>
<target name="__SEH_epilog4"/>
<target name="SEH_epilog4_GS"/>
<target name="_SEH_epilog4_GS"/>
<target name="__SEH_epilog4_GS"/>
<target name="FID_conflict:__SEH_epilog4_GS"/>
<pcode>
<body><![CDATA[
ESP = EBP;
EBP = * ESP;
ESP = ESP + 4;
]]></body>
</pcode>
</callfixup>
<!-- Not sure if these are ever used, and how they affect the stack
<callfixup name="EH_prolog3_align">
<target name="_EH_prolog3_align"/>
<target name="__EH_prolog3_align"/>
<target name="EH_prolog3_GS_align"/>
<target name="_EH_prolog3_GS_align"/>
<target name="__EH_prolog3_GS_align"/>
<target name="EH_prolog3_catch_align"/>
<target name="_EH_prolog3_catch_align"/>
<target name="__EH_prolog3_catch_align"/>
<target name="EH_prolog3_catch_GS_align"/>
<target name="_EH_prolog3_catch_GS_align"/>
<target name="__EH_prolog3_catch_GS_align"/>
<pcode>
<body><![CDATA[
EBP = ESP + 4;
tmp = * EBP;
ESP = ESP - tmp;
ESP = ESP - 24;
]]></body>
</pcode>
</callfixup>
<callfixup name="EH_epilog3_align">
<target name="_EH_epilog3_align"/>
<target name="__EH_epilog3_align"/>
<target name="EH_epilog3_GS_align"/>
<target name="_EH_epilog3_GS_align"/>
<target name="__EH_epilog3_GS_align"/>
<pcode>
<body><![CDATA[
ESP = EBP;
EBP = * ESP;
ESP = ESP - 4;
]]></body>
</pcode>
</callfixup>
-->
<callfixup name="alloca_probe">
<target name="__alloca_probe"/>
<target name="__alloca_probe_8"/>
<target name="__alloca_probe_16"/>
<target name="__chkstk"/>
<pcode>
<body><![CDATA[
ESP = ESP + 4 - EAX;
]]></body>
</pcode>
</callfixup>
<callfixup name="SEH_prolog">
<target name="_SEH_prolog"/>
<target name="__SEH_prolog"/>
<pcode>
<body><![CDATA[
newframetmp = ESP + 8;
localsizetmp:4 = * newframetmp;
ESP = ESP - localsizetmp;
ESP = ESP - 20;
* newframetmp = EBP;
EBP = newframetmp;
*ESP = EDI;
*(ESP+4) = ESI;
*(ESP+8) = EBX;
]]></body>
</pcode>
</callfixup>
<callfixup name="SEH_prolog4">
<target name="_SEH_prolog4"/>
<target name="__SEH_prolog4"/>
<target name="SEH_prolog4_GS"/>
<target name="_SEH_prolog4_GS"/>
<target name="__SEH_prolog4_GS"/>
<pcode>
<body><![CDATA[
newframetmp = ESP + 8;
localsizetmp:4 = * newframetmp;
ESP = ESP - localsizetmp;
ESP = ESP - 24;
* newframetmp = EBP;
EBP = newframetmp;
*(ESP+4) = EDI;
*(ESP+8) = ESI;
*(ESP+12) = EBX;
]]></body>
</pcode>
</callfixup>
<callfixup name="__RTC_CheckEsp">
<target name="__RTC_CheckEsp"/>
<pcode>
<body><![CDATA[
temp:4 = 0;
]]></body>
</pcode>
</callfixup>
</compiler_spec>

View File

@@ -0,0 +1,631 @@
use icicle_cpu::ExceptionCode;
use icicle_cpu::ValueSource;
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::registers;
fn create_x64_vm() -> icicle_vm::Vm {
let mut cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none");
cpu_config.enable_jit = false;
cpu_config.enable_jit_mem = true;
cpu_config.enable_shadow_stack = false;
cpu_config.enable_recompilation = true;
cpu_config.track_uninitialized = false;
cpu_config.optimize_instructions = true;
cpu_config.optimize_block = false;
return icicle_vm::build(&cpu_config).unwrap();
}
const FOREIGN_READ: u8 = 1 << 0;
const FOREIGN_WRITE: u8 = 1 << 1;
const FOREIGN_EXEC: u8 = 1 << 2;
fn map_permissions(foreign_permissions: u8) -> u8 {
let mut permissions: u8 = 0;
if (foreign_permissions & FOREIGN_READ) != 0 {
permissions |= icicle_vm::cpu::mem::perm::READ;
}
if (foreign_permissions & FOREIGN_WRITE) != 0 {
permissions |= icicle_vm::cpu::mem::perm::WRITE;
}
if (foreign_permissions & FOREIGN_EXEC) != 0 {
permissions |= icicle_vm::cpu::mem::perm::EXEC;
}
return permissions;
}
#[repr(u8)]
#[allow(dead_code)]
#[derive(PartialEq)]
enum HookType {
Syscall = 1,
Read,
Write,
ExecuteGeneric,
ExecuteSpecific,
Violation,
Interrupt,
Unknown,
}
fn u8_to_hook_type_unsafe(value: u8) -> HookType {
unsafe { std::mem::transmute(value) }
}
fn split_hook_id(id: u32) -> (u32, HookType) {
let hook_id = id & 0xFFFFFF;
let hook_type = u8_to_hook_type_unsafe((id >> 24) as u8);
return (hook_id, hook_type);
}
fn qualify_hook_id(hook_id: u32, hook_type: HookType) -> u32 {
let hook_type: u32 = (hook_type as u8).into();
let hook_type_mask: u32 = hook_type << 24;
return (hook_id | hook_type_mask).into();
}
pub struct HookContainer<Func: ?Sized> {
hook_id: u32,
hooks: HashMap<u32, Box<Func>>,
}
impl<Func: ?Sized> HookContainer<Func> {
pub fn new() -> Self {
Self {
hook_id: 0,
hooks: HashMap::new(),
}
}
pub fn add_hook(&mut self, callback: Box<Func>) -> u32 {
self.hook_id += 1;
let id = self.hook_id;
self.hooks.insert(id, callback);
return id;
}
pub fn get_hooks(&self) -> &HashMap<u32, Box<Func>> {
return &self.hooks;
}
pub fn remove_hook(&mut self, id: u32) {
self.hooks.remove(&id);
}
}
struct InstructionHookInjector {
hook: pcode::HookId,
}
impl icicle_vm::CodeInjector for InstructionHookInjector {
fn inject(
&mut self,
_cpu: &mut icicle_vm::cpu::Cpu,
group: &icicle_vm::cpu::BlockGroup,
code: &mut icicle_vm::BlockTable,
) {
for id in group.range() {
let block = &mut code.blocks[id];
let mut tmp_block = pcode::Block::new();
tmp_block.next_tmp = block.pcode.next_tmp;
for stmt in block.pcode.instructions.drain(..) {
tmp_block.push(stmt);
if let pcode::Op::InstructionMarker = stmt.op {
tmp_block.push(pcode::Op::Hook(self.hook));
code.modified.insert(id);
}
}
std::mem::swap(&mut tmp_block.instructions, &mut block.pcode.instructions);
}
}
}
struct ExecutionHooks {
stop: Rc<RefCell<bool>>,
generic_hooks: HookContainer<dyn Fn(u64)>,
specific_hooks: HookContainer<dyn Fn(u64)>,
address_mapping: HashMap<u64, Vec<u32>>,
}
impl ExecutionHooks {
pub fn new(stop_value: Rc<RefCell<bool>>) -> Self {
Self {
stop: stop_value,
generic_hooks: HookContainer::new(),
specific_hooks: HookContainer::new(),
address_mapping: HashMap::new(),
}
}
fn run_hooks(&self, address: u64) {
for (_key, func) in self.generic_hooks.get_hooks() {
func(address);
}
let mapping = self.address_mapping.get(&address);
if mapping.is_none(){
return;
}
for id in mapping.unwrap() {
let func = self.specific_hooks.get_hooks().get(&id);
if func.is_some() {
func.unwrap()(address);
}
}
}
pub fn execute(&mut self,cpu: &mut icicle_cpu::Cpu, address: u64) {
self.run_hooks(address);
if *self.stop.borrow() {
cpu.exception.code = ExceptionCode::InstructionLimit as u32;
cpu.exception.value = address;
}
}
pub fn add_generic_hook(&mut self, callback: Box<dyn Fn(u64)>) -> u32 {
self.generic_hooks.add_hook(callback)
}
pub fn add_specific_hook(&mut self, address: u64, callback: Box<dyn Fn(u64)>) -> u32 {
let id = self.specific_hooks.add_hook(callback);
let mapping = self.address_mapping.entry(address).or_insert_with(Vec::new);
mapping.push(id);
return id;
}
pub fn remove_generic_hook(&mut self, id: u32) {
self.generic_hooks.remove_hook(id);
}
pub fn remove_specific_hook(&mut self, id: u32) {
self.address_mapping.retain(|_, vec| {
vec.retain(|&x| x != id);
!vec.is_empty()
});
self.specific_hooks.remove_hook(id);
}
}
pub struct IcicleEmulator {
executing_thread: std::thread::ThreadId,
vm: icicle_vm::Vm,
reg: registers::X64RegisterNodes,
syscall_hooks: HookContainer<dyn Fn()>,
interrupt_hooks: HookContainer<dyn Fn(i32)>,
violation_hooks: HookContainer<dyn Fn(u64, u8, bool) -> bool>,
execution_hooks: Rc<RefCell<ExecutionHooks>>,
stop: Rc<RefCell<bool>>,
}
struct MemoryHook {
callback: Box<dyn Fn(u64, &[u8])>,
}
impl icicle_cpu::mem::WriteHook for MemoryHook {
fn write(&mut self, _mem: &mut icicle_cpu::Mmu, addr: u64, value: &[u8]) {
(self.callback)(addr, value);
}
}
impl icicle_cpu::mem::ReadAfterHook for MemoryHook {
fn read(&mut self, _mem: &mut icicle_cpu::Mmu, addr: u64, value: &[u8]) {
(self.callback)(addr, value);
}
}
pub struct MmioHandler {
read_handler: Box<dyn Fn(u64, &mut [u8])>,
write_handler: Box<dyn Fn(u64, &[u8])>,
}
impl MmioHandler {
pub fn new(
read_function: Box<dyn Fn(u64, &mut [u8])>,
write_function: Box<dyn Fn(u64, &[u8])>,
) -> Self {
Self {
read_handler: read_function,
write_handler: write_function,
}
}
}
impl icicle_cpu::mem::IoMemory for MmioHandler {
fn read(&mut self, addr: u64, buf: &mut [u8]) -> icicle_cpu::mem::MemResult<()> {
(self.read_handler)(addr, buf);
return Ok(());
}
fn write(&mut self, addr: u64, value: &[u8]) -> icicle_cpu::mem::MemResult<()> {
(self.write_handler)(addr, value);
return Ok(());
}
}
impl IcicleEmulator {
pub fn new() -> Self {
let mut virtual_machine = create_x64_vm();
let stop_value = Rc::new(RefCell::new(false));
let exec_hooks = Rc::new(RefCell::new(ExecutionHooks::new(stop_value.clone())));
let exec_hooks_clone = Rc::clone(&exec_hooks);
let hook = icicle_cpu::InstHook::new(move |cpu: &mut icicle_cpu::Cpu, addr: u64| {
exec_hooks_clone.borrow_mut().execute(cpu, addr);
});
let hook = virtual_machine.cpu.add_hook(hook);
virtual_machine.add_injector(InstructionHookInjector { hook });
Self {
stop: stop_value,
executing_thread: std::thread::current().id(),
reg: registers::X64RegisterNodes::new(&virtual_machine.cpu.arch),
vm: virtual_machine,
syscall_hooks: HookContainer::new(),
interrupt_hooks: HookContainer::new(),
violation_hooks: HookContainer::new(),
execution_hooks: exec_hooks,
}
}
fn get_mem(&mut self) -> &mut icicle_vm::cpu::Mmu {
return &mut self.vm.cpu.mem;
}
pub fn start(&mut self, count: u64) {
self.executing_thread = std::thread::current().id();
self.vm.icount_limit = match count {
0 => u64::MAX,
_ => self.vm.cpu.icount.saturating_add(count),
};
loop {
self.vm.cpu.block_id = u64::MAX;
self.vm.cpu.block_offset = 0;
self.vm.cpu.pending_exception = None;
self.vm.cpu.exception.clear();
*self.stop.borrow_mut() = false;
let reason = self.vm.run();
match reason {
icicle_vm::VmExit::InstructionLimit => break,
icicle_vm::VmExit::UnhandledException((code, value)) => {
let continue_execution = self.handle_exception(code, value);
if !continue_execution {
break;
}
}
_ => break,
};
}
}
fn handle_interrupt(&self, code: i32) -> bool {
for (_key, func) in self.interrupt_hooks.get_hooks() {
func(code);
}
return true;
}
fn handle_exception(&mut self, code: ExceptionCode, value: u64) -> bool {
let continue_execution = match code {
ExceptionCode::Syscall => self.handle_syscall(),
ExceptionCode::ReadPerm => self.handle_violation(value, FOREIGN_READ, false),
ExceptionCode::WritePerm => self.handle_violation(value, FOREIGN_WRITE, false),
ExceptionCode::ReadUnmapped => self.handle_violation(value, FOREIGN_READ, true),
ExceptionCode::WriteUnmapped => self.handle_violation(value, FOREIGN_WRITE, true),
ExceptionCode::InvalidInstruction => self.handle_interrupt(6),
ExceptionCode::DivisionException => self.handle_interrupt(0),
_ => false,
};
return continue_execution;
}
fn handle_violation(&mut self, address: u64, permission: u8, unmapped: bool) -> bool {
let hooks = &self.violation_hooks.get_hooks();
if hooks.is_empty() {
return false;
}
let mut continue_execution = true;
for (_key, func) in self.violation_hooks.get_hooks() {
continue_execution &= func(address, permission, unmapped);
}
return continue_execution;
}
fn handle_syscall(&mut self) -> bool {
for (_key, func) in self.syscall_hooks.get_hooks() {
func();
}
self.vm.cpu.write_pc(self.vm.cpu.read_pc() + 2);
return true;
}
pub fn stop(&mut self) {
self.vm.icount_limit = 0;
if self.executing_thread == std::thread::current().id() {
*self.stop.borrow_mut() = true;
}
}
pub fn add_violation_hook(&mut self, callback: Box<dyn Fn(u64, u8, bool) -> bool>) -> u32 {
let hook_id = self.violation_hooks.add_hook(callback);
return qualify_hook_id(hook_id, HookType::Violation);
}
pub fn add_execution_hook(&mut self, address:u64, callback: Box<dyn Fn(u64)>) -> u32 {
let hook_id = self.execution_hooks.borrow_mut().add_specific_hook(address, callback);
return qualify_hook_id(hook_id, HookType::ExecuteSpecific);
}
pub fn add_generic_execution_hook(&mut self, callback: Box<dyn Fn(u64)>) -> u32 {
let hook_id = self.execution_hooks.borrow_mut().add_generic_hook(callback);
return qualify_hook_id(hook_id, HookType::ExecuteGeneric);
}
pub fn add_syscall_hook(&mut self, callback: Box<dyn Fn()>) -> u32 {
let hook_id = self.syscall_hooks.add_hook(callback);
return qualify_hook_id(hook_id, HookType::Syscall);
}
pub fn add_interrupt_hook(&mut self, callback: Box<dyn Fn(i32)>) -> u32 {
let hook_id = self.interrupt_hooks.add_hook(callback);
return qualify_hook_id(hook_id, HookType::Interrupt);
}
pub fn add_read_hook(
&mut self,
start: u64,
end: u64,
callback: Box<dyn Fn(u64, &[u8])>,
) -> u32 {
let id = self.get_mem().add_read_after_hook(start, end, Box::new(MemoryHook { callback }));
if id.is_none() {
return 0;
}
return qualify_hook_id(id.unwrap(), HookType::Read);
}
pub fn add_write_hook(
&mut self,
start: u64,
end: u64,
callback: Box<dyn Fn(u64, &[u8])>,
) -> u32 {
let id = self.get_mem().add_write_hook(start, end, Box::new(MemoryHook { callback }));
if id.is_none() {
return 0;
}
return qualify_hook_id(id.unwrap(), HookType::Write);
}
pub fn remove_hook(&mut self, id: u32) {
let (hook_id, hook_type) = split_hook_id(id);
match hook_type {
HookType::Syscall => self.syscall_hooks.remove_hook(hook_id),
HookType::Violation => self.violation_hooks.remove_hook(hook_id),
HookType::Interrupt => self.interrupt_hooks.remove_hook(hook_id),
HookType::ExecuteGeneric => self.execution_hooks.borrow_mut().remove_generic_hook(hook_id),
HookType::ExecuteSpecific => self.execution_hooks.borrow_mut().remove_specific_hook(hook_id),
HookType::Read => {self.get_mem().remove_read_after_hook(hook_id);()},
HookType::Write => {self.get_mem().remove_write_hook(hook_id);()},
_ => {}
}
}
pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool {
const MAPPING_PERMISSIONS: u8 = icicle_vm::cpu::mem::perm::MAP
| icicle_vm::cpu::mem::perm::INIT
| icicle_vm::cpu::mem::perm::IN_CODE_CACHE;
let native_permissions = map_permissions(permissions);
let mapping = icicle_vm::cpu::mem::Mapping {
perm: native_permissions | MAPPING_PERMISSIONS,
value: 0x0,
};
let layout = icicle_vm::cpu::mem::AllocLayout {
addr: Some(address),
size: length,
align: 0x1000,
};
let res = self.get_mem().alloc_memory(layout, mapping);
return res.is_ok();
}
pub fn map_mmio(
&mut self,
address: u64,
length: u64,
read_function: Box<dyn Fn(u64, &mut [u8])>,
write_function: Box<dyn Fn(u64, &[u8])>,
) -> bool {
let mem = self.get_mem();
let handler = MmioHandler::new(read_function, write_function);
let handler_id = mem.register_io_handler(handler);
let layout = icicle_vm::cpu::mem::AllocLayout {
addr: Some(address),
size: length,
align: 0x1000,
};
let res = mem.alloc_memory(layout, handler_id);
return res.is_ok();
}
pub fn unmap_memory(&mut self, address: u64, length: u64) -> bool {
return self.get_mem().unmap_memory_len(address, length);
}
pub fn protect_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool {
let native_permissions = map_permissions(permissions);
let res = self
.get_mem()
.update_perm(address, length, native_permissions);
return res.is_ok();
}
pub fn write_memory(&mut self, address: u64, data: &[u8]) -> bool {
let res = self
.get_mem()
.write_bytes(address, data, icicle_vm::cpu::mem::perm::NONE);
return res.is_ok();
}
pub fn read_memory(&mut self, address: u64, data: &mut [u8]) -> bool {
let res = self
.get_mem()
.read_bytes(address, data, icicle_vm::cpu::mem::perm::NONE);
return res.is_ok();
}
pub fn save_registers(&self) -> Vec<u8> {
const REG_SIZE: usize = std::mem::size_of::<icicle_cpu::Regs>();
unsafe {
let data: [u8; REG_SIZE] = self.vm.cpu.regs.read_at(0);
return data.to_vec();
}
}
pub fn restore_registers(&mut self, data: &[u8]) {
const REG_SIZE: usize = std::mem::size_of::<icicle_cpu::Regs>();
let mut buffer: [u8; REG_SIZE] = [0; REG_SIZE];
let size = std::cmp::min(REG_SIZE, data.len());
buffer.copy_from_slice(&data[..size]);
unsafe {
self.vm.cpu.regs.write_at(0, buffer);
};
}
fn read_generic_register(&mut self, reg: registers::X64Register, buffer: &mut [u8]) -> usize {
let reg_node = self.reg.get_node(reg);
let res = self.vm.cpu.read_dynamic(pcode::Value::Var(reg_node));
let bytes: [u8; 32] = res.zxt();
let len = std::cmp::min(bytes.len(), buffer.len());
buffer[..len].copy_from_slice(&bytes[..len]);
return reg_node.size.into();
}
fn read_flags<T>(&mut self, data: &mut [u8]) -> usize
{
const REAL_SIZE: usize = std::mem::size_of::<u64>();
let limit: usize = std::mem::size_of::<T>();
let size = std::cmp::min(REAL_SIZE, limit);
let flags: u64 = self.reg.get_flags(&mut self.vm.cpu);
let copy_size = std::cmp::min(data.len(), size);
data[..copy_size].copy_from_slice(&flags.to_ne_bytes()[..copy_size]);
return limit;
}
pub fn read_register(&mut self, reg: registers::X64Register, data: &mut [u8]) -> usize {
match reg {
registers::X64Register::Rflags => self.read_flags::<u64>(data),
registers::X64Register::Eflags => self.read_flags::<u32>(data),
registers::X64Register::Flags => self.read_flags::<u16>(data),
_ => self.read_generic_register(reg, data),
}
}
fn write_flags<T>(&mut self, data: &[u8]) -> usize
{
const REAL_SIZE: usize = std::mem::size_of::<u64>();
let limit: usize = std::mem::size_of::<T>();
let size = std::cmp::min(REAL_SIZE, limit);
let copy_size = std::cmp::min(data.len(), size);
let mut buffer = [0u8; REAL_SIZE];
self.read_flags::<u64>(&mut buffer);
buffer[..copy_size].copy_from_slice(&data[..copy_size]);
let flags = u64::from_ne_bytes(buffer);
self.reg.set_flags(&mut self.vm.cpu, flags);
return limit;
}
pub fn write_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize {
match reg {
registers::X64Register::Rflags => self.write_flags::<u64>(data),
registers::X64Register::Eflags => self.write_flags::<u32>(data),
registers::X64Register::Flags => self.write_flags::<u16>(data),
_ => self.write_generic_register(reg, data),
}
}
fn write_generic_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize {
let reg_node = self.reg.get_node(reg);
let mut buffer = [0u8; 32];
let len = std::cmp::min(data.len(), buffer.len());
buffer[..len].copy_from_slice(&data[..len]);
//let value = icicle_cpu::regs::DynamicValue::new(buffer, reg_node.size.into());
//self.vm.cpu.write_trunc(reg_node, value);
let cpu = &mut self.vm.cpu;
match reg_node.size {
1 => cpu.write_var::<[u8; 1]>(reg_node, buffer[..1].try_into().unwrap()),
2 => cpu.write_var::<[u8; 2]>(reg_node, buffer[..2].try_into().unwrap()),
3 => cpu.write_var::<[u8; 3]>(reg_node, buffer[..3].try_into().unwrap()),
4 => cpu.write_var::<[u8; 4]>(reg_node, buffer[..4].try_into().unwrap()),
5 => cpu.write_var::<[u8; 5]>(reg_node, buffer[..5].try_into().unwrap()),
6 => cpu.write_var::<[u8; 6]>(reg_node, buffer[..6].try_into().unwrap()),
7 => cpu.write_var::<[u8; 7]>(reg_node, buffer[..7].try_into().unwrap()),
8 => cpu.write_var::<[u8; 8]>(reg_node, buffer[..8].try_into().unwrap()),
9 => cpu.write_var::<[u8; 9]>(reg_node, buffer[..9].try_into().unwrap()),
10 => cpu.write_var::<[u8; 10]>(reg_node, buffer[..10].try_into().unwrap()),
11 => cpu.write_var::<[u8; 11]>(reg_node, buffer[..11].try_into().unwrap()),
12 => cpu.write_var::<[u8; 12]>(reg_node, buffer[..12].try_into().unwrap()),
13 => cpu.write_var::<[u8; 13]>(reg_node, buffer[..13].try_into().unwrap()),
14 => cpu.write_var::<[u8; 14]>(reg_node, buffer[..14].try_into().unwrap()),
15 => cpu.write_var::<[u8; 15]>(reg_node, buffer[..15].try_into().unwrap()),
16 => cpu.write_var::<[u8; 16]>(reg_node, buffer[..16].try_into().unwrap()),
_ => panic!("invalid dynamic value size"),
}
return reg_node.size.into();
}
}

View File

@@ -0,0 +1,305 @@
mod icicle;
mod registers;
use icicle::IcicleEmulator;
use registers::X64Register;
use std::os::raw::c_void;
fn to_cbool(value: bool) -> i32 {
if value {
return 1;
}
return 0;
}
#[unsafe(no_mangle)]
pub fn icicle_create_emulator() -> *mut c_void {
let emulator = Box::new(IcicleEmulator::new());
return Box::into_raw(emulator) as *mut c_void;
}
#[unsafe(no_mangle)]
pub fn icicle_start(ptr: *mut c_void, count: usize) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
emulator.start(count as u64);
}
}
#[unsafe(no_mangle)]
pub fn icicle_stop(ptr: *mut c_void) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
emulator.stop();
}
}
type RawFunction = extern "C" fn(*mut c_void);
type PtrFunction = extern "C" fn(*mut c_void, u64);
type DataFunction = extern "C" fn(*mut c_void, *const c_void, usize);
type MmioReadFunction = extern "C" fn(*mut c_void, u64, *mut c_void, usize);
type MmioWriteFunction = extern "C" fn(*mut c_void, u64, *const c_void, usize);
type ViolationFunction = extern "C" fn(*mut c_void, u64, u8, i32) -> i32;
type InterruptFunction = extern "C" fn(*mut c_void, i32);
type MemoryAccessFunction = MmioWriteFunction;
#[unsafe(no_mangle)]
pub fn icicle_map_mmio(
ptr: *mut c_void,
address: u64,
length: u64,
read_cb: MmioReadFunction,
read_data: *mut c_void,
write_cb: MmioWriteFunction,
write_data: *mut c_void,
) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let read_wrapper = Box::new(move |addr: u64, data: &mut [u8]| {
let raw_pointer: *mut u8 = data.as_mut_ptr();
read_cb(read_data, addr, raw_pointer as *mut c_void, data.len());
});
let write_wrapper = Box::new(move |addr: u64, data: &[u8]| {
let raw_pointer: *const u8 = data.as_ptr();
write_cb(write_data, addr, raw_pointer as *const c_void, data.len());
});
let res = emulator.map_mmio(address, length, read_wrapper, write_wrapper);
return to_cbool(res);
}
}
#[unsafe(no_mangle)]
pub fn icicle_map_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let res = emulator.map_memory(address, length, permissions);
return to_cbool(res);
}
}
#[unsafe(no_mangle)]
pub fn icicle_unmap_memory(ptr: *mut c_void, address: u64, length: u64) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let res = emulator.unmap_memory(address, length);
return to_cbool(res);
}
}
#[unsafe(no_mangle)]
pub fn icicle_protect_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let res = emulator.protect_memory(address, length, permissions);
return to_cbool(res);
}
}
#[unsafe(no_mangle)]
pub fn icicle_write_memory(
ptr: *mut c_void,
address: u64,
data: *const c_void,
size: usize,
) -> i32 {
if size == 0 {
return 1;
}
if data.is_null() {
return 0;
}
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts(data as *const u8, size);
let res = emulator.write_memory(address, u8_slice);
return to_cbool(res);
}
}
#[unsafe(no_mangle)]
pub fn icicle_save_registers(ptr: *mut c_void, accessor: DataFunction, accessor_data: *mut c_void) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let registers = emulator.save_registers();
accessor(
accessor_data,
registers.as_ptr() as *const c_void,
registers.len(),
);
}
}
#[unsafe(no_mangle)]
pub fn icicle_restore_registers(ptr: *mut c_void, data: *const c_void, size: usize) {
if size == 0 || data.is_null() {
return;
}
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts(data as *const u8, size);
emulator.restore_registers(u8_slice);
}
}
#[unsafe(no_mangle)]
pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, size: usize) -> i32 {
if size == 0 {
return 1;
}
if data.is_null() {
return 0;
}
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts_mut(data as *mut u8, size);
let res = emulator.read_memory(address, u8_slice);
return to_cbool(res);
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_interrupt_hook(ptr: *mut c_void, callback: InterruptFunction, data: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_interrupt_hook(Box::new(
move |code: i32| callback(data, code),
));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_violation_hook(ptr: *mut c_void, callback: ViolationFunction, data: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_violation_hook(Box::new(
move |address: u64, permission: u8, unmapped: bool| {
let result = callback(data, address, permission, to_cbool(unmapped));
if result == 0 {
return false;
}
return true;
},
));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_read_hook(ptr: *mut c_void, start: u64, end: u64, callback: MemoryAccessFunction, user: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_read_hook(start, end, Box::new(
move |address: u64, data: &[u8]| {
callback(user, address, data.as_ptr() as *const c_void, data.len());
},
));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_write_hook(ptr: *mut c_void, start: u64, end: u64, callback: MemoryAccessFunction, user: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_write_hook(start, end, Box::new(
move |address: u64, data: &[u8]| {
callback(user, address, data.as_ptr() as *const c_void, data.len());
},
));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: RawFunction, data: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_syscall_hook(Box::new(move || callback(data)));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_generic_execution_hook(ptr: *mut c_void, callback: PtrFunction, data: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_generic_execution_hook(Box::new(move |ptr: u64| callback(data, ptr)));
}
}
#[unsafe(no_mangle)]
pub fn icicle_add_execution_hook(ptr: *mut c_void, address: u64, callback: PtrFunction, data: *mut c_void) -> u32 {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
return emulator.add_execution_hook(address, Box::new(move |ptr: u64| callback(data, ptr)));
}
}
#[unsafe(no_mangle)]
pub fn icicle_remove_hook(ptr: *mut c_void, id: u32) {
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
emulator.remove_hook(id);
}
}
#[unsafe(no_mangle)]
pub fn icicle_read_register(
ptr: *mut c_void,
reg: X64Register,
data: *mut c_void,
size: usize,
) -> usize {
if size == 0 {
return 1;
}
if data.is_null() {
return 0;
}
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts_mut(data as *mut u8, size);
return emulator.read_register(reg, u8_slice);
}
}
#[unsafe(no_mangle)]
pub fn icicle_write_register(
ptr: *mut c_void,
reg: X64Register,
data: *const c_void,
size: usize,
) -> usize {
if size == 0 {
return 1;
}
if data.is_null() {
return 0;
}
unsafe {
let emulator = &mut *(ptr as *mut IcicleEmulator);
let u8_slice = std::slice::from_raw_parts(data as *const u8, size);
return emulator.write_register(reg, u8_slice);
}
}
#[unsafe(no_mangle)]
pub fn icicle_destroy_emulator(ptr: *mut c_void) {
if ptr.is_null() {
return;
}
unsafe {
let _ = Box::from_raw(ptr as *mut IcicleEmulator);
}
}

View File

@@ -0,0 +1,965 @@
#[repr(i32)]
#[derive(PartialEq)]
pub enum X64Register {
Invalid = 0,
Ah,
Al,
Ax,
Bh,
Bl,
Bp,
Bpl,
Bx,
Ch,
Cl,
Cs,
Cx,
Dh,
Di,
Dil,
Dl,
Ds,
Dx,
Eax,
Ebp,
Ebx,
Ecx,
Edi,
Edx,
Eflags,
Eip,
Es = 26 + 2,
Esi,
Esp,
Fpsw,
Fs,
Gs,
Ip,
Rax,
Rbp,
Rbx,
Rcx,
Rdi,
Rdx,
Rip,
Rsi = 41 + 2,
Rsp,
Si,
Sil,
Sp,
Spl,
Ss,
Cr0,
Cr1,
Cr2,
Cr3,
Cr4,
Cr8 = 54 + 4,
Dr0 = 58 + 8,
Dr1,
Dr2,
Dr3,
Dr4,
Dr5,
Dr6,
Dr7,
Fp0 = 73 + 9,
Fp1,
Fp2,
Fp3,
Fp4,
Fp5,
Fp6,
Fp7,
K0,
K1,
K2,
K3,
K4,
K5,
K6,
K7,
Mm0,
Mm1,
Mm2,
Mm3,
Mm4,
Mm5,
Mm6,
Mm7,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
St0,
St1,
St2,
St3,
St4,
St5,
St6,
St7,
Xmm0,
Xmm1,
Xmm2,
Xmm3,
Xmm4,
Xmm5,
Xmm6,
Xmm7,
Xmm8,
Xmm9,
Xmm10,
Xmm11,
Xmm12,
Xmm13,
Xmm14,
Xmm15,
Xmm16,
Xmm17,
Xmm18,
Xmm19,
Xmm20,
Xmm21,
Xmm22,
Xmm23,
Xmm24,
Xmm25,
Xmm26,
Xmm27,
Xmm28,
Xmm29,
Xmm30,
Xmm31,
Ymm0,
Ymm1,
Ymm2,
Ymm3,
Ymm4,
Ymm5,
Ymm6,
Ymm7,
Ymm8,
Ymm9,
Ymm10,
Ymm11,
Ymm12,
Ymm13,
Ymm14,
Ymm15,
Ymm16,
Ymm17,
Ymm18,
Ymm19,
Ymm20,
Ymm21,
Ymm22,
Ymm23,
Ymm24,
Ymm25,
Ymm26,
Ymm27,
Ymm28,
Ymm29,
Ymm30,
Ymm31,
Zmm0,
Zmm1,
Zmm2,
Zmm3,
Zmm4,
Zmm5,
Zmm6,
Zmm7,
Zmm8,
Zmm9,
Zmm10,
Zmm11,
Zmm12,
Zmm13,
Zmm14,
Zmm15,
Zmm16,
Zmm17,
Zmm18,
Zmm19,
Zmm20,
Zmm21,
Zmm22,
Zmm23,
Zmm24,
Zmm25,
Zmm26,
Zmm27,
Zmm28,
Zmm29,
Zmm30,
Zmm31,
R8b,
R9b,
R10b,
R11b,
R12b,
R13b,
R14b,
R15b,
R8d,
R9d,
R10d,
R11d,
R12d,
R13d,
R14d,
R15d,
R8w,
R9w,
R10w,
R11w,
R12w,
R13w,
R14w,
R15w,
Idtr,
Gdtr,
Ldtr,
Tr,
Fpcw,
Fptag,
Msr,
Mxcsr,
FsBase,
GsBase,
Flags,
Rflags,
Fip,
Fcs,
Fdp,
Fds,
Fop,
End, // Must be last
}
#[derive(Clone)]
pub(crate) struct X64RegisterNodes {
rax: pcode::VarNode,
rbx: pcode::VarNode,
rcx: pcode::VarNode,
rdx: pcode::VarNode,
rsi: pcode::VarNode,
rdi: pcode::VarNode,
rbp: pcode::VarNode,
rsp: pcode::VarNode,
r8: pcode::VarNode,
r9: pcode::VarNode,
r10: pcode::VarNode,
r11: pcode::VarNode,
r12: pcode::VarNode,
r13: pcode::VarNode,
r14: pcode::VarNode,
r15: pcode::VarNode,
rip: pcode::VarNode,
cs: pcode::VarNode,
ds: pcode::VarNode,
es: pcode::VarNode,
fs: pcode::VarNode,
gs: pcode::VarNode,
ss: pcode::VarNode,
ah: pcode::VarNode,
al: pcode::VarNode,
ax: pcode::VarNode,
bh: pcode::VarNode,
bl: pcode::VarNode,
bpl: pcode::VarNode,
ch: pcode::VarNode,
cl: pcode::VarNode,
cx: pcode::VarNode,
dh: pcode::VarNode,
dil: pcode::VarNode,
dl: pcode::VarNode,
dx: pcode::VarNode,
eax: pcode::VarNode,
ebp: pcode::VarNode,
ebx: pcode::VarNode,
ecx: pcode::VarNode,
edi: pcode::VarNode,
edx: pcode::VarNode,
esi: pcode::VarNode,
esp: pcode::VarNode,
fpsw: pcode::VarNode,
gdtr: pcode::VarNode,
idtr: pcode::VarNode,
ldtr: pcode::VarNode,
tr: pcode::VarNode,
cr0: pcode::VarNode,
cr1: pcode::VarNode,
cr2: pcode::VarNode,
cr3: pcode::VarNode,
cr4: pcode::VarNode,
cr8: pcode::VarNode,
dr0: pcode::VarNode,
dr1: pcode::VarNode,
dr2: pcode::VarNode,
dr3: pcode::VarNode,
dr4: pcode::VarNode,
dr5: pcode::VarNode,
dr6: pcode::VarNode,
dr7: pcode::VarNode,
fp0: pcode::VarNode,
fp1: pcode::VarNode,
fp2: pcode::VarNode,
fp3: pcode::VarNode,
fp4: pcode::VarNode,
fp5: pcode::VarNode,
fp6: pcode::VarNode,
fp7: pcode::VarNode,
/*k0: pcode::VarNode,
k1: pcode::VarNode,
k2: pcode::VarNode,
k3: pcode::VarNode,
k4: pcode::VarNode,
k5: pcode::VarNode,
k6: pcode::VarNode,
k7: pcode::VarNode,*/
mm0: pcode::VarNode,
mm1: pcode::VarNode,
mm2: pcode::VarNode,
mm3: pcode::VarNode,
mm4: pcode::VarNode,
mm5: pcode::VarNode,
mm6: pcode::VarNode,
mm7: pcode::VarNode,
st0: pcode::VarNode,
st1: pcode::VarNode,
st2: pcode::VarNode,
st3: pcode::VarNode,
st4: pcode::VarNode,
st5: pcode::VarNode,
st6: pcode::VarNode,
st7: pcode::VarNode,
xmm0: pcode::VarNode,
xmm1: pcode::VarNode,
xmm2: pcode::VarNode,
xmm3: pcode::VarNode,
xmm4: pcode::VarNode,
xmm5: pcode::VarNode,
xmm6: pcode::VarNode,
xmm7: pcode::VarNode,
xmm8: pcode::VarNode,
xmm9: pcode::VarNode,
xmm10: pcode::VarNode,
xmm11: pcode::VarNode,
xmm12: pcode::VarNode,
xmm13: pcode::VarNode,
xmm14: pcode::VarNode,
xmm15: pcode::VarNode,
/*xmm16: pcode::VarNode,
xmm17: pcode::VarNode,
xmm18: pcode::VarNode,
xmm19: pcode::VarNode,
xmm20: pcode::VarNode,
xmm21: pcode::VarNode,
xmm22: pcode::VarNode,
xmm23: pcode::VarNode,
xmm24: pcode::VarNode,
xmm25: pcode::VarNode,
xmm26: pcode::VarNode,
xmm27: pcode::VarNode,
xmm28: pcode::VarNode,
xmm29: pcode::VarNode,
xmm30: pcode::VarNode,
xmm31: pcode::VarNode,*/
ymm0: pcode::VarNode,
ymm1: pcode::VarNode,
ymm2: pcode::VarNode,
ymm3: pcode::VarNode,
ymm4: pcode::VarNode,
ymm5: pcode::VarNode,
ymm6: pcode::VarNode,
ymm7: pcode::VarNode,
ymm8: pcode::VarNode,
ymm9: pcode::VarNode,
ymm10: pcode::VarNode,
ymm11: pcode::VarNode,
ymm12: pcode::VarNode,
ymm13: pcode::VarNode,
ymm14: pcode::VarNode,
ymm15: pcode::VarNode,
/*ymm16: pcode::VarNode,
ymm17: pcode::VarNode,
ymm18: pcode::VarNode,
ymm19: pcode::VarNode,
ymm20: pcode::VarNode,
ymm21: pcode::VarNode,
ymm22: pcode::VarNode,
ymm23: pcode::VarNode,
ymm24: pcode::VarNode,
ymm25: pcode::VarNode,
ymm26: pcode::VarNode,
ymm27: pcode::VarNode,
ymm28: pcode::VarNode,
ymm29: pcode::VarNode,
ymm30: pcode::VarNode,
ymm31: pcode::VarNode,*/
/*zmm0: pcode::VarNode,
zmm1: pcode::VarNode,
zmm2: pcode::VarNode,
zmm3: pcode::VarNode,
zmm4: pcode::VarNode,
zmm5: pcode::VarNode,
zmm6: pcode::VarNode,
zmm7: pcode::VarNode,
zmm8: pcode::VarNode,
zmm9: pcode::VarNode,
zmm10: pcode::VarNode,
zmm11: pcode::VarNode,
zmm12: pcode::VarNode,
zmm13: pcode::VarNode,
zmm14: pcode::VarNode,
zmm15: pcode::VarNode,
zmm16: pcode::VarNode,
zmm17: pcode::VarNode,
zmm18: pcode::VarNode,
zmm19: pcode::VarNode,
zmm20: pcode::VarNode,
zmm21: pcode::VarNode,
zmm22: pcode::VarNode,
zmm23: pcode::VarNode,
zmm24: pcode::VarNode,
zmm25: pcode::VarNode,
zmm26: pcode::VarNode,
zmm27: pcode::VarNode,
zmm28: pcode::VarNode,
zmm29: pcode::VarNode,
zmm30: pcode::VarNode,
zmm31: pcode::VarNode,*/
r8b: pcode::VarNode,
r9b: pcode::VarNode,
r10b: pcode::VarNode,
r11b: pcode::VarNode,
r12b: pcode::VarNode,
r13b: pcode::VarNode,
r14b: pcode::VarNode,
r15b: pcode::VarNode,
r8d: pcode::VarNode,
r9d: pcode::VarNode,
r10d: pcode::VarNode,
r11d: pcode::VarNode,
r12d: pcode::VarNode,
r13d: pcode::VarNode,
r14d: pcode::VarNode,
r15d: pcode::VarNode,
r8w: pcode::VarNode,
r9w: pcode::VarNode,
r10w: pcode::VarNode,
r11w: pcode::VarNode,
r12w: pcode::VarNode,
r13w: pcode::VarNode,
r14w: pcode::VarNode,
r15w: pcode::VarNode,
fpcw: pcode::VarNode,
fptag: pcode::VarNode,
//msr: pcode::VarNode,
mxcsr: pcode::VarNode,
fs_base: pcode::VarNode,
gs_base: pcode::VarNode,
fip: pcode::VarNode,
fcs: pcode::VarNode,
fdp: pcode::VarNode,
fds: pcode::VarNode,
fop: pcode::VarNode,
flags: Vec<pcode::VarNode>,
}
impl X64RegisterNodes {
pub fn new(arch: &icicle_cpu::Arch) -> Self {
let r = |name: &str| arch.sleigh.get_reg(name).unwrap().var;
let nodes = [
"CF", "F1", "PF", "F3", "AF", "F5", "ZF", "SF", "TF", "IF", "DF", "OF", "IOPL", "NT",
"F15", "RF", "VM", "AC", "VIF", "VIP", "ID",
];
Self {
rax: r("RAX"),
rbx: r("RBX"),
rcx: r("RCX"),
rdx: r("RDX"),
rsi: r("RSI"),
rdi: r("RDI"),
rbp: r("RBP"),
rsp: r("RSP"),
r8: r("R8"),
r9: r("R9"),
r10: r("R10"),
r11: r("R11"),
r12: r("R12"),
r13: r("R13"),
r14: r("R14"),
r15: r("R15"),
rip: r("RIP"),
cs: r("CS"),
ds: r("DS"),
es: r("ES"),
fs: r("FS"),
gs: r("GS"),
ss: r("SS"),
ah: r("AH"),
al: r("AL"),
ax: r("AX"),
bh: r("BH"),
bl: r("BL"),
bpl: r("BPL"),
ch: r("CH"),
cl: r("CL"),
cx: r("CX"),
dh: r("DH"),
dil: r("DIL"),
dl: r("DL"),
dx: r("DX"),
eax: r("EAX"),
ebp: r("EBP"),
ebx: r("EBX"),
ecx: r("ECX"),
edi: r("EDI"),
edx: r("EDX"),
esi: r("ESI"),
esp: r("ESP"),
fpsw: r("FPUStatusWord"),
gdtr: r("GDTR"),
idtr: r("IDTR"),
ldtr: r("LDTR"),
tr: r("TR"),
cr0: r("CR0"),
cr1: r("CR1"),
cr2: r("CR2"),
cr3: r("CR3"),
cr4: r("CR4"),
cr8: r("CR8"),
dr0: r("DR0"),
dr1: r("DR1"),
dr2: r("DR2"),
dr3: r("DR3"),
dr4: r("DR4"),
dr5: r("DR5"),
dr6: r("DR6"),
dr7: r("DR7"),
fp0: r("ST0"), // ??
fp1: r("ST1"),
fp2: r("ST2"),
fp3: r("ST3"),
fp4: r("ST4"),
fp5: r("ST5"),
fp6: r("ST6"),
fp7: r("ST7"),
/*k0: r("K0"),
k1: r("K1"),
k2: r("K2"),
k3: r("K3"),
k4: r("K4"),
k5: r("K5"),
k6: r("K6"),
k7: r("K7"),*/
mm0: r("MM0"),
mm1: r("MM1"),
mm2: r("MM2"),
mm3: r("MM3"),
mm4: r("MM4"),
mm5: r("MM5"),
mm6: r("MM6"),
mm7: r("MM7"),
st0: r("ST0"),
st1: r("ST1"),
st2: r("ST2"),
st3: r("ST3"),
st4: r("ST4"),
st5: r("ST5"),
st6: r("ST6"),
st7: r("ST7"),
xmm0: r("XMM0"),
xmm1: r("XMM1"),
xmm2: r("XMM2"),
xmm3: r("XMM3"),
xmm4: r("XMM4"),
xmm5: r("XMM5"),
xmm6: r("XMM6"),
xmm7: r("XMM7"),
xmm8: r("XMM8"),
xmm9: r("XMM9"),
xmm10: r("XMM10"),
xmm11: r("XMM11"),
xmm12: r("XMM12"),
xmm13: r("XMM13"),
xmm14: r("XMM14"),
xmm15: r("XMM15"),
/*xmm16: r("XMM16"),
xmm17: r("XMM17"),
xmm18: r("XMM18"),
xmm19: r("XMM19"),
xmm20: r("XMM20"),
xmm21: r("XMM21"),
xmm22: r("XMM22"),
xmm23: r("XMM23"),
xmm24: r("XMM24"),
xmm25: r("XMM25"),
xmm26: r("XMM26"),
xmm27: r("XMM27"),
xmm28: r("XMM28"),
xmm29: r("XMM29"),
xmm30: r("XMM30"),
xmm31: r("XMM31"),*/
ymm0: r("YMM0"),
ymm1: r("YMM1"),
ymm2: r("YMM2"),
ymm3: r("YMM3"),
ymm4: r("YMM4"),
ymm5: r("YMM5"),
ymm6: r("YMM6"),
ymm7: r("YMM7"),
ymm8: r("YMM8"),
ymm9: r("YMM9"),
ymm10: r("YMM10"),
ymm11: r("YMM11"),
ymm12: r("YMM12"),
ymm13: r("YMM13"),
ymm14: r("YMM14"),
ymm15: r("YMM15"),
/*ymm16: r("YMM16"),
ymm17: r("YMM17"),
ymm18: r("YMM18"),
ymm19: r("YMM19"),
ymm20: r("YMM20"),
ymm21: r("YMM21"),
ymm22: r("YMM22"),
ymm23: r("YMM23"),
ymm24: r("YMM24"),
ymm25: r("YMM25"),
ymm26: r("YMM26"),
ymm27: r("YMM27"),
ymm28: r("YMM28"),
ymm29: r("YMM29"),
ymm30: r("YMM30"),
ymm31: r("YMM31"),*/
/*zmm0: r("ZMM0"),
zmm1: r("ZMM1"),
zmm2: r("ZMM2"),
zmm3: r("ZMM3"),
zmm4: r("ZMM4"),
zmm5: r("ZMM5"),
zmm6: r("ZMM6"),
zmm7: r("ZMM7"),
zmm8: r("ZMM8"),
zmm9: r("ZMM9"),
zmm10: r("ZMM10"),
zmm11: r("ZMM11"),
zmm12: r("ZMM12"),
zmm13: r("ZMM13"),
zmm14: r("ZMM14"),
zmm15: r("ZMM15"),
zmm16: r("ZMM16"),
zmm17: r("ZMM17"),
zmm18: r("ZMM18"),
zmm19: r("ZMM19"),
zmm20: r("ZMM20"),
zmm21: r("ZMM21"),
zmm22: r("ZMM22"),
zmm23: r("ZMM23"),
zmm24: r("ZMM24"),
zmm25: r("ZMM25"),
zmm26: r("ZMM26"),
zmm27: r("ZMM27"),
zmm28: r("ZMM28"),
zmm29: r("ZMM29"),
zmm30: r("ZMM30"),
zmm31: r("ZMM31"),*/
r8b: r("R8B"),
r9b: r("R9B"),
r10b: r("R10B"),
r11b: r("R11B"),
r12b: r("R12B"),
r13b: r("R13B"),
r14b: r("R14B"),
r15b: r("R15B"),
r8d: r("R8D"),
r9d: r("R9D"),
r10d: r("R10D"),
r11d: r("R11D"),
r12d: r("R12D"),
r13d: r("R13D"),
r14d: r("R14D"),
r15d: r("R15D"),
r8w: r("R8W"),
r9w: r("R9W"),
r10w: r("R10W"),
r11w: r("R11W"),
r12w: r("R12W"),
r13w: r("R13W"),
r14w: r("R14W"),
r15w: r("R15W"),
fpcw: r("FPUControlWord"),
fptag: r("FPUTagWord"),
mxcsr: r("MXCSR"),
fip: r("FPUInstructionPointer"),
fdp: r("FPUDataPointer"),
fop: r("FPULastInstructionOpcode"),
fds: r("DS"), // ?
fcs: r("CS"), // ?
//msr: r("MSR"),
fs_base: r("FS_OFFSET"),
gs_base: r("GS_OFFSET"),
flags: nodes.map(|name: &str| r(name)).to_vec(),
}
}
pub fn get_flags(&self, cpu: &mut icicle_cpu::Cpu) -> u64 {
let mut res: u64 = 0;
for (index, element) in self.flags.iter().enumerate() {
let flag = cpu.read_reg(*element);
res |= (flag & 1) << index;
}
res
}
pub fn set_flags(&self, cpu: &mut icicle_cpu::Cpu, value: u64) {
for (index, element) in self.flags.iter().enumerate() {
let flag = (value >> index) & 1;
cpu.write_reg(*element, flag);
}
}
pub fn get_node(&self, reg: X64Register) -> pcode::VarNode {
match reg {
X64Register::Rax => self.rax,
X64Register::Rbx => self.rbx,
X64Register::Rcx => self.rcx,
X64Register::Rdx => self.rdx,
X64Register::Rsi => self.rsi,
X64Register::Rdi => self.rdi,
X64Register::Rbp => self.rbp,
X64Register::Rsp => self.rsp,
X64Register::R8 => self.r8,
X64Register::R9 => self.r9,
X64Register::R10 => self.r10,
X64Register::R11 => self.r11,
X64Register::R12 => self.r12,
X64Register::R13 => self.r13,
X64Register::R14 => self.r14,
X64Register::R15 => self.r15,
X64Register::Rip => self.rip,
X64Register::Cs => self.cs,
X64Register::Ds => self.ds,
X64Register::Es => self.es,
X64Register::Fs => self.fs,
X64Register::Gs => self.gs,
X64Register::Ss => self.ss,
X64Register::Ah => self.ah,
X64Register::Al => self.al,
X64Register::Ax => self.ax,
X64Register::Bh => self.bh,
X64Register::Bl => self.bl,
X64Register::Bpl => self.bpl,
X64Register::Ch => self.ch,
X64Register::Cl => self.cl,
X64Register::Cx => self.cx,
X64Register::Dh => self.dh,
X64Register::Dil => self.dil,
X64Register::Dl => self.dl,
X64Register::Dx => self.dx,
X64Register::Eax => self.eax,
X64Register::Ebp => self.ebp,
X64Register::Ebx => self.ebx,
X64Register::Ecx => self.ecx,
X64Register::Edi => self.edi,
X64Register::Edx => self.edx,
X64Register::Esi => self.esi,
X64Register::Esp => self.esp,
X64Register::Fpsw => self.fpsw,
X64Register::Gdtr => self.gdtr,
X64Register::Idtr => self.idtr,
X64Register::Ldtr => self.ldtr,
X64Register::Tr => self.tr,
X64Register::Cr0 => self.cr0,
X64Register::Cr1 => self.cr1,
X64Register::Cr2 => self.cr2,
X64Register::Cr3 => self.cr3,
X64Register::Cr4 => self.cr4,
X64Register::Cr8 => self.cr8,
X64Register::Dr0 => self.dr0,
X64Register::Dr1 => self.dr1,
X64Register::Dr2 => self.dr2,
X64Register::Dr3 => self.dr3,
X64Register::Dr4 => self.dr4,
X64Register::Dr5 => self.dr5,
X64Register::Dr6 => self.dr6,
X64Register::Dr7 => self.dr7,
X64Register::Fp0 => self.fp0,
X64Register::Fp1 => self.fp1,
X64Register::Fp2 => self.fp2,
X64Register::Fp3 => self.fp3,
X64Register::Fp4 => self.fp4,
X64Register::Fp5 => self.fp5,
X64Register::Fp6 => self.fp6,
X64Register::Fp7 => self.fp7,
/*X64Register::K0 => self.k0,
X64Register::K1 => self.k1,
X64Register::K2 => self.k2,
X64Register::K3 => self.k3,
X64Register::K4 => self.k4,
X64Register::K5 => self.k5,
X64Register::K6 => self.k6,
X64Register::K7 => self.k7,*/
X64Register::Mm0 => self.mm0,
X64Register::Mm1 => self.mm1,
X64Register::Mm2 => self.mm2,
X64Register::Mm3 => self.mm3,
X64Register::Mm4 => self.mm4,
X64Register::Mm5 => self.mm5,
X64Register::Mm6 => self.mm6,
X64Register::Mm7 => self.mm7,
X64Register::St0 => self.st0,
X64Register::St1 => self.st1,
X64Register::St2 => self.st2,
X64Register::St3 => self.st3,
X64Register::St4 => self.st4,
X64Register::St5 => self.st5,
X64Register::St6 => self.st6,
X64Register::St7 => self.st7,
X64Register::Xmm0 => self.xmm0,
X64Register::Xmm1 => self.xmm1,
X64Register::Xmm2 => self.xmm2,
X64Register::Xmm3 => self.xmm3,
X64Register::Xmm4 => self.xmm4,
X64Register::Xmm5 => self.xmm5,
X64Register::Xmm6 => self.xmm6,
X64Register::Xmm7 => self.xmm7,
X64Register::Xmm8 => self.xmm8,
X64Register::Xmm9 => self.xmm9,
X64Register::Xmm10 => self.xmm10,
X64Register::Xmm11 => self.xmm11,
X64Register::Xmm12 => self.xmm12,
X64Register::Xmm13 => self.xmm13,
X64Register::Xmm14 => self.xmm14,
X64Register::Xmm15 => self.xmm15,
/*X64Register::Xmm16 => self.xmm16,
X64Register::Xmm17 => self.xmm17,
X64Register::Xmm18 => self.xmm18,
X64Register::Xmm19 => self.xmm19,
X64Register::Xmm20 => self.xmm20,
X64Register::Xmm21 => self.xmm21,
X64Register::Xmm22 => self.xmm22,
X64Register::Xmm23 => self.xmm23,
X64Register::Xmm24 => self.xmm24,
X64Register::Xmm25 => self.xmm25,
X64Register::Xmm26 => self.xmm26,
X64Register::Xmm27 => self.xmm27,
X64Register::Xmm28 => self.xmm28,
X64Register::Xmm29 => self.xmm29,
X64Register::Xmm30 => self.xmm30,
X64Register::Xmm31 => self.xmm31,*/
X64Register::Ymm0 => self.ymm0,
X64Register::Ymm1 => self.ymm1,
X64Register::Ymm2 => self.ymm2,
X64Register::Ymm3 => self.ymm3,
X64Register::Ymm4 => self.ymm4,
X64Register::Ymm5 => self.ymm5,
X64Register::Ymm6 => self.ymm6,
X64Register::Ymm7 => self.ymm7,
X64Register::Ymm8 => self.ymm8,
X64Register::Ymm9 => self.ymm9,
X64Register::Ymm10 => self.ymm10,
X64Register::Ymm11 => self.ymm11,
X64Register::Ymm12 => self.ymm12,
X64Register::Ymm13 => self.ymm13,
X64Register::Ymm14 => self.ymm14,
X64Register::Ymm15 => self.ymm15,
/*X64Register::Ymm16 => self.ymm16,
X64Register::Ymm17 => self.ymm17,
X64Register::Ymm18 => self.ymm18,
X64Register::Ymm19 => self.ymm19,
X64Register::Ymm20 => self.ymm20,
X64Register::Ymm21 => self.ymm21,
X64Register::Ymm22 => self.ymm22,
X64Register::Ymm23 => self.ymm23,
X64Register::Ymm24 => self.ymm24,
X64Register::Ymm25 => self.ymm25,
X64Register::Ymm26 => self.ymm26,
X64Register::Ymm27 => self.ymm27,
X64Register::Ymm28 => self.ymm28,
X64Register::Ymm29 => self.ymm29,
X64Register::Ymm30 => self.ymm30,
X64Register::Ymm31 => self.ymm31,*/
/*X64Register::Zmm0 => self.zmm0,
X64Register::Zmm1 => self.zmm1,
X64Register::Zmm2 => self.zmm2,
X64Register::Zmm3 => self.zmm3,
X64Register::Zmm4 => self.zmm4,
X64Register::Zmm5 => self.zmm5,
X64Register::Zmm6 => self.zmm6,
X64Register::Zmm7 => self.zmm7,
X64Register::Zmm8 => self.zmm8,
X64Register::Zmm9 => self.zmm9,
X64Register::Zmm10 => self.zmm10,
X64Register::Zmm11 => self.zmm11,
X64Register::Zmm12 => self.zmm12,
X64Register::Zmm13 => self.zmm13,
X64Register::Zmm14 => self.zmm14,
X64Register::Zmm15 => self.zmm15,
X64Register::Zmm16 => self.zmm16,
X64Register::Zmm17 => self.zmm17,
X64Register::Zmm18 => self.zmm18,
X64Register::Zmm19 => self.zmm19,
X64Register::Zmm20 => self.zmm20,
X64Register::Zmm21 => self.zmm21,
X64Register::Zmm22 => self.zmm22,
X64Register::Zmm23 => self.zmm23,
X64Register::Zmm24 => self.zmm24,
X64Register::Zmm25 => self.zmm25,
X64Register::Zmm26 => self.zmm26,
X64Register::Zmm27 => self.zmm27,
X64Register::Zmm28 => self.zmm28,
X64Register::Zmm29 => self.zmm29,
X64Register::Zmm30 => self.zmm30,
X64Register::Zmm31 => self.zmm31,*/
X64Register::R8b => self.r8b,
X64Register::R9b => self.r9b,
X64Register::R10b => self.r10b,
X64Register::R11b => self.r11b,
X64Register::R12b => self.r12b,
X64Register::R13b => self.r13b,
X64Register::R14b => self.r14b,
X64Register::R15b => self.r15b,
X64Register::R8d => self.r8d,
X64Register::R9d => self.r9d,
X64Register::R10d => self.r10d,
X64Register::R11d => self.r11d,
X64Register::R12d => self.r12d,
X64Register::R13d => self.r13d,
X64Register::R14d => self.r14d,
X64Register::R15d => self.r15d,
X64Register::R8w => self.r8w,
X64Register::R9w => self.r9w,
X64Register::R10w => self.r10w,
X64Register::R11w => self.r11w,
X64Register::R12w => self.r12w,
X64Register::R13w => self.r13w,
X64Register::R14w => self.r14w,
X64Register::R15w => self.r15w,
X64Register::Fpcw => self.fpcw,
X64Register::Fptag => self.fptag,
//X64Register::Msr => self.msr,
X64Register::Mxcsr => self.mxcsr,
X64Register::FsBase => self.fs_base,
X64Register::GsBase => self.gs_base,
X64Register::Fip => self.fip,
X64Register::Fcs => self.fcs,
X64Register::Fdp => self.fdp,
X64Register::Fds => self.fds,
X64Register::Fop => self.fop,
_ => panic!("Unsupported register"),
}
}
}

View File

@@ -0,0 +1,434 @@
#define ICICLE_EMULATOR_IMPL
#include "icicle_x64_emulator.hpp"
#include <utils/object.hpp>
using icicle_emulator = struct icicle_emulator_;
extern "C"
{
using icicle_mmio_read_func = void(void* user, uint64_t address, void* data, size_t length);
using icicle_mmio_write_func = void(void* user, uint64_t address, const void* data, size_t length);
using raw_func = void(void*);
using ptr_func = void(void*, uint64_t);
using interrupt_func = void(void*, int32_t);
using violation_func = int32_t(void*, uint64_t address, uint8_t operation, int32_t unmapped);
using data_accessor_func = void(void* user, const void* data, size_t length);
using memory_access_func = icicle_mmio_write_func;
icicle_emulator* icicle_create_emulator();
int32_t icicle_protect_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions);
int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions);
int32_t icicle_map_mmio(icicle_emulator*, uint64_t address, uint64_t length, icicle_mmio_read_func* read_callback,
void* read_data, icicle_mmio_write_func* write_callback, void* write_data);
int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length);
int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length);
int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length);
int32_t icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data);
int32_t icicle_restore_registers(icicle_emulator*, const void* data, size_t length);
uint32_t icicle_add_syscall_hook(icicle_emulator*, raw_func* callback, void* data);
uint32_t icicle_add_interrupt_hook(icicle_emulator*, interrupt_func* callback, void* data);
uint32_t icicle_add_execution_hook(icicle_emulator*, uint64_t address, ptr_func* callback, void* data);
uint32_t icicle_add_generic_execution_hook(icicle_emulator*, ptr_func* callback, void* data);
uint32_t icicle_add_violation_hook(icicle_emulator*, violation_func* callback, void* data);
uint32_t icicle_add_read_hook(icicle_emulator*, uint64_t start, uint64_t end, memory_access_func* cb, void* data);
uint32_t icicle_add_write_hook(icicle_emulator*, uint64_t start, uint64_t end, memory_access_func* cb, void* data);
void icicle_remove_hook(icicle_emulator*, uint32_t id);
size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length);
size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length);
void icicle_start(icicle_emulator*, size_t count);
void icicle_stop(icicle_emulator*);
void icicle_destroy_emulator(icicle_emulator*);
}
namespace icicle
{
namespace
{
void ice(const bool result, const std::string_view error)
{
if (!result)
{
throw std::runtime_error(std::string(error));
}
}
emulator_hook* wrap_hook(const uint32_t id)
{
return reinterpret_cast<emulator_hook*>(static_cast<size_t>(id));
}
template <typename T>
struct function_object : utils::object
{
std::function<T> func{};
function_object(std::function<T> f = {})
: func(std::move(f))
{
}
template <typename... Args>
auto operator()(Args&&... args) const
{
return this->func.operator()(std::forward<Args>(args)...);
}
~function_object() override = default;
};
template <typename T>
std::unique_ptr<function_object<T>> make_function_object(std::function<T> func)
{
return std::make_unique<function_object<T>>(std::move(func));
}
}
class icicle_x64_emulator : public x64_emulator
{
public:
icicle_x64_emulator()
: emu_(icicle_create_emulator())
{
if (!this->emu_)
{
throw std::runtime_error("Failed to create icicle emulator instance");
}
}
~icicle_x64_emulator() override
{
if (this->emu_)
{
icicle_destroy_emulator(this->emu_);
this->emu_ = nullptr;
}
}
void start(const size_t count) override
{
icicle_start(this->emu_, count);
}
void stop() override
{
icicle_stop(this->emu_);
}
void load_gdt(const pointer_type address, const uint32_t limit) override
{
struct gdtr
{
uint32_t padding{};
uint32_t limit{};
uint64_t address{};
};
const gdtr entry{.limit = limit, .address = address};
static_assert(sizeof(gdtr) - offsetof(gdtr, limit) == 12);
this->write_register(x64_register::gdtr, &entry.limit, 12);
}
void set_segment_base(const x64_register base, const pointer_type value) override
{
switch (base)
{
case x64_register::fs:
case x64_register::fs_base:
this->reg(x64_register::fs_base, value);
break;
case x64_register::gs:
case x64_register::gs_base:
this->reg(x64_register::gs_base, value);
break;
default:
break;
}
}
size_t write_raw_register(const int reg, const void* value, const size_t size) override
{
return icicle_write_register(this->emu_, reg, value, size);
}
size_t read_raw_register(const int reg, void* value, const size_t size) override
{
return icicle_read_register(this->emu_, reg, value, size);
}
void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,
mmio_write_callback write_cb) override
{
struct mmio_wrapper : utils::object
{
uint64_t base{};
mmio_read_callback read_cb{};
mmio_write_callback write_cb{};
};
auto wrapper = std::make_unique<mmio_wrapper>();
wrapper->base = address;
wrapper->read_cb = std::move(read_cb);
wrapper->write_cb = std::move(write_cb);
auto* ptr = wrapper.get();
this->storage_.push_back(std::move(wrapper));
auto* read_wrapper = +[](void* user, const uint64_t addr, void* data, const size_t length) {
const auto* w = static_cast<mmio_wrapper*>(user);
w->read_cb(addr - w->base, data, length);
};
auto* write_wrapper = +[](void* user, const uint64_t addr, const void* data, const size_t length) {
const auto* w = static_cast<mmio_wrapper*>(user);
w->write_cb(addr + w->base, data, length);
};
icicle_map_mmio(this->emu_, address, size, read_wrapper, ptr, write_wrapper, ptr);
}
void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override
{
const auto res = icicle_map_memory(this->emu_, address, size, static_cast<uint8_t>(permissions));
ice(res, "Failed to map memory");
}
void unmap_memory(const uint64_t address, const size_t size) override
{
const auto res = icicle_unmap_memory(this->emu_, address, size);
ice(res, "Failed to unmap memory");
}
bool try_read_memory(const uint64_t address, void* data, const size_t size) const override
{
return icicle_read_memory(this->emu_, address, data, size);
}
void read_memory(const uint64_t address, void* data, const size_t size) const override
{
const auto res = this->try_read_memory(address, data, size);
ice(res, "Failed to read memory");
}
void write_memory(const uint64_t address, const void* data, const size_t size) override
{
const auto res = icicle_write_memory(this->emu_, address, data, size);
ice(res, "Failed to write memory");
}
void apply_memory_protection(const uint64_t address, const size_t size, memory_permission permissions) override
{
const auto res = icicle_protect_memory(this->emu_, address, size, static_cast<uint8_t>(permissions));
ice(res, "Failed to apply permissions");
}
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override
{
if (static_cast<x64_hookable_instructions>(instruction_type) != x64_hookable_instructions::syscall)
{
// TODO
return nullptr;
}
auto obj = make_function_object(std::move(callback));
auto* ptr = obj.get();
const auto invoker = +[](void* cb) {
const auto& func = *static_cast<decltype(ptr)>(cb);
(void)func(); //
};
const auto id = icicle_add_syscall_hook(this->emu_, invoker, ptr);
this->hooks_[id] = std::move(obj);
return wrap_hook(id);
}
emulator_hook* hook_basic_block(basic_block_hook_callback callback) override
{
// TODO
(void)callback;
throw std::runtime_error("Not implemented");
}
emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override
{
// TODO
(void)callback;
throw std::runtime_error("Not implemented");
}
emulator_hook* hook_interrupt(interrupt_hook_callback callback) override
{
auto obj = make_function_object(std::move(callback));
auto* ptr = obj.get();
auto* wrapper = +[](void* user, const int32_t code) {
const auto& func = *static_cast<decltype(ptr)>(user);
func(code);
};
const auto id = icicle_add_interrupt_hook(this->emu_, wrapper, ptr);
this->hooks_[id] = std::move(obj);
return wrap_hook(id);
}
emulator_hook* hook_memory_violation(memory_violation_hook_callback callback) override
{
auto obj = make_function_object(std::move(callback));
auto* ptr = obj.get();
auto* wrapper =
+[](void* user, const uint64_t address, const uint8_t operation, const int32_t unmapped) -> int32_t {
const auto violation_type = unmapped //
? memory_violation_type::unmapped
: memory_violation_type::protection;
const auto& func = *static_cast<decltype(ptr)>(user);
const auto res = func(address, 1, static_cast<memory_operation>(operation), violation_type);
return res == memory_violation_continuation::resume ? 1 : 0;
};
const auto id = icicle_add_violation_hook(this->emu_, wrapper, ptr);
this->hooks_[id] = std::move(obj);
return wrap_hook(id);
}
emulator_hook* hook_memory_execution(const uint64_t address, memory_execution_hook_callback callback) override
{
auto object = make_function_object(std::move(callback));
auto* ptr = object.get();
auto* wrapper = +[](void* user, const uint64_t addr) {
const auto& func = *static_cast<decltype(ptr)>(user);
(func)(addr);
};
const auto id = icicle_add_execution_hook(this->emu_, address, wrapper, ptr);
this->hooks_[id] = std::move(object);
return wrap_hook(id);
}
emulator_hook* hook_memory_execution(memory_execution_hook_callback callback) override
{
auto object = make_function_object(std::move(callback));
auto* ptr = object.get();
auto* wrapper = +[](void* user, const uint64_t addr) {
const auto& func = *static_cast<decltype(ptr)>(user);
(func)(addr);
};
const auto id = icicle_add_generic_execution_hook(this->emu_, wrapper, ptr);
this->hooks_[id] = std::move(object);
return wrap_hook(id);
}
emulator_hook* hook_memory_read(const uint64_t address, const size_t size,
memory_access_hook_callback callback) override
{
auto obj = make_function_object(std::move(callback));
auto* ptr = obj.get();
auto* wrapper = +[](void* user, const uint64_t address, const void* data, size_t length) {
const auto& func = *static_cast<decltype(ptr)>(user);
func(address, data, length);
};
const auto id = icicle_add_read_hook(this->emu_, address, address + size, wrapper, ptr);
this->hooks_[id] = std::move(obj);
return wrap_hook(id);
}
emulator_hook* hook_memory_write(const uint64_t address, const size_t size,
memory_access_hook_callback callback) override
{
auto obj = make_function_object(std::move(callback));
auto* ptr = obj.get();
auto* wrapper = +[](void* user, const uint64_t address, const void* data, size_t length) {
const auto& func = *static_cast<decltype(ptr)>(user);
func(address, data, length);
};
const auto id = icicle_add_write_hook(this->emu_, address, address + size, wrapper, ptr);
this->hooks_[id] = std::move(obj);
return wrap_hook(id);
}
void delete_hook(emulator_hook* hook) override
{
const auto id = static_cast<uint32_t>(reinterpret_cast<size_t>(hook));
const auto entry = this->hooks_.find(id);
if (entry == this->hooks_.end())
{
return;
}
icicle_remove_hook(this->emu_, id);
this->hooks_.erase(entry);
}
void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override
{
if (is_snapshot)
{
throw std::runtime_error("Not implemented");
}
buffer.write_vector(this->save_registers());
}
void deserialize_state(utils::buffer_deserializer& buffer, const bool is_snapshot) override
{
if (is_snapshot)
{
throw std::runtime_error("Not implemented");
}
const auto data = buffer.read_vector<std::byte>();
this->restore_registers(data);
}
std::vector<std::byte> save_registers() const override
{
std::vector<std::byte> data{};
auto* accessor = +[](void* user, const void* data, const size_t length) {
auto& vec = *static_cast<std::vector<std::byte>*>(user);
vec.resize(length);
memcpy(vec.data(), data, length);
};
icicle_save_registers(this->emu_, accessor, &data);
return data;
}
void restore_registers(const std::vector<std::byte>& register_data) override
{
icicle_restore_registers(this->emu_, register_data.data(), register_data.size());
}
bool has_violation() const override
{
return false;
}
std::string get_name() const override
{
return "icicle-emu";
}
private:
std::list<std::unique_ptr<utils::object>> storage_{};
std::unordered_map<uint32_t, std::unique_ptr<utils::object>> hooks_{};
icicle_emulator* emu_{};
};
std::unique_ptr<x64_emulator> create_x64_emulator()
{
return std::make_unique<icicle_x64_emulator>();
}
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <memory>
#include <x64_emulator.hpp>
#include "platform/platform.hpp"
#ifdef ICICLE_EMULATOR_IMPL
#define ICICLE_EMULATOR_DLL_STORAGE EXPORT_SYMBOL
#else
#define ICICLE_EMULATOR_DLL_STORAGE IMPORT_SYMBOL
#endif
namespace icicle
{
#if !MOMO_BUILD_AS_LIBRARY
ICICLE_EMULATOR_DLL_STORAGE
#endif
std::unique_ptr<x64_emulator> create_x64_emulator();
}

View File

@@ -0,0 +1,20 @@
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS
*.cpp
*.hpp
*.rc
)
list(SORT SRC_FILES)
if(MOMO_BUILD_AS_LIBRARY)
add_library(unicorn-emulator STATIC ${SRC_FILES})
else()
add_library(unicorn-emulator SHARED ${SRC_FILES})
endif()
target_include_directories(unicorn-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}")
target_link_libraries(unicorn-emulator PUBLIC emulator)
target_link_libraries(unicorn-emulator PRIVATE unicorn emulator-common)
momo_strip_target(unicorn-emulator)

View File

@@ -0,0 +1,42 @@
#pragma once
#include <memory>
#include <functional>
#include <utils/object.hpp>
template <typename ReturnType, typename... Args>
class function_wrapper : public utils::object
{
public:
using user_data_pointer = void*;
using c_function_type = ReturnType(Args..., user_data_pointer);
using functor_type = std::function<ReturnType(Args...)>;
function_wrapper() = default;
function_wrapper(functor_type functor)
: functor_(std::make_unique<functor_type>(std::move(functor)))
{
}
c_function_type* get_c_function() const
{
return +[](Args... args, user_data_pointer user_data) -> ReturnType {
return (*static_cast<functor_type*>(user_data))(std::forward<Args>(args)...);
};
}
void* get_function() const
{
return reinterpret_cast<void*>(this->get_c_function());
}
user_data_pointer get_user_data() const
{
return this->functor_.get();
}
private:
std::unique_ptr<functor_type> functor_{};
};

View File

@@ -0,0 +1,51 @@
#pragma once
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4505)
#endif
#ifdef __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define NOMINMAX
#include <unicorn/unicorn.h>
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <stdexcept>
namespace unicorn
{
struct unicorn_error : std::runtime_error
{
unicorn_error(const uc_err error_code)
: std::runtime_error(uc_strerror(error_code)),
code(error_code)
{
}
uc_err code{};
};
inline void throw_if_unicorn_error(const uc_err error_code)
{
if (error_code != UC_ERR_OK)
{
throw unicorn_error(error_code);
}
}
inline void uce(const uc_err error_code)
{
throw_if_unicorn_error(error_code);
}
}

View File

@@ -0,0 +1,76 @@
#pragma once
#include "unicorn.hpp"
namespace unicorn
{
class unicorn_hook
{
public:
unicorn_hook() = default;
unicorn_hook(uc_engine* uc)
: unicorn_hook(uc, {})
{
}
unicorn_hook(uc_engine* uc, const uc_hook hook)
: uc_(uc),
hook_(hook)
{
}
~unicorn_hook()
{
release();
}
unicorn_hook(const unicorn_hook&) = delete;
unicorn_hook& operator=(const unicorn_hook&) = delete;
unicorn_hook(unicorn_hook&& obj) noexcept
{
this->operator=(std::move(obj));
}
uc_hook* make_reference()
{
if (!this->uc_)
{
throw std::runtime_error("Cannot make reference on default constructed hook");
}
this->release();
return &this->hook_;
}
unicorn_hook& operator=(unicorn_hook&& obj) noexcept
{
if (this != &obj)
{
this->release();
this->uc_ = obj.uc_;
this->hook_ = obj.hook_;
obj.hook_ = {};
obj.uc_ = {};
}
return *this;
}
void release()
{
if (this->hook_ && this->uc_)
{
uc_hook_del(this->uc_, this->hook_);
this->hook_ = {};
}
}
private:
uc_engine* uc_{};
uc_hook hook_{};
};
}

View File

@@ -0,0 +1,66 @@
#pragma once
#include <span>
#include "unicorn.hpp"
namespace unicorn
{
class unicorn_memory_regions
{
public:
unicorn_memory_regions(uc_engine* uc)
{
uce(uc_mem_regions(uc, &this->regions_, &this->count_));
}
~unicorn_memory_regions()
{
this->release();
}
unicorn_memory_regions(const unicorn_memory_regions&) = delete;
unicorn_memory_regions& operator=(const unicorn_memory_regions&) = delete;
unicorn_memory_regions(unicorn_memory_regions&& obj) noexcept
{
this->operator=(std::move(obj));
}
unicorn_memory_regions& operator=(unicorn_memory_regions&& obj) noexcept
{
if (this != &obj)
{
this->release();
this->count_ = obj.count_;
this->regions_ = obj.regions_;
obj.count_ = {};
obj.regions_ = nullptr;
}
return *this;
}
std::span<uc_mem_region> get_span() const
{
return {this->regions_, this->count_};
}
private:
uint32_t count_{};
uc_mem_region* regions_{};
void release()
{
if (this->regions_)
{
uc_free(regions_);
}
this->count_ = {};
this->regions_ = nullptr;
}
};
}

View File

@@ -0,0 +1,699 @@
#define UNICORN_EMULATOR_IMPL
#include "unicorn_x64_emulator.hpp"
#include <array>
#include "unicorn_memory_regions.hpp"
#include "unicorn_hook.hpp"
#include "function_wrapper.hpp"
#include <ranges>
namespace unicorn
{
namespace
{
static_assert(static_cast<uint32_t>(memory_permission::none) == UC_PROT_NONE);
static_assert(static_cast<uint32_t>(memory_permission::read) == UC_PROT_READ);
static_assert(static_cast<uint32_t>(memory_permission::exec) == UC_PROT_EXEC);
static_assert(static_cast<uint32_t>(memory_permission::all) == UC_PROT_ALL);
static_assert(static_cast<uint32_t>(x64_register::end) == UC_X86_REG_ENDING);
uc_x86_insn map_hookable_instruction(const x64_hookable_instructions instruction)
{
switch (instruction)
{
case x64_hookable_instructions::syscall:
return UC_X86_INS_SYSCALL;
case x64_hookable_instructions::cpuid:
return UC_X86_INS_CPUID;
case x64_hookable_instructions::rdtsc:
return UC_X86_INS_RDTSC;
case x64_hookable_instructions::rdtscp:
return UC_X86_INS_RDTSCP;
default:
throw std::runtime_error("Bad instruction for mapping");
}
}
memory_violation_type map_memory_violation_type(const uc_mem_type mem_type)
{
switch (mem_type)
{
case UC_MEM_READ_PROT:
case UC_MEM_WRITE_PROT:
case UC_MEM_FETCH_PROT:
return memory_violation_type::protection;
case UC_MEM_READ_UNMAPPED:
case UC_MEM_WRITE_UNMAPPED:
case UC_MEM_FETCH_UNMAPPED:
return memory_violation_type::unmapped;
default:
throw std::runtime_error("Memory type does not constitute a violation");
}
}
memory_operation map_memory_operation(const uc_mem_type mem_type)
{
switch (mem_type)
{
case UC_MEM_READ:
case UC_MEM_READ_PROT:
case UC_MEM_READ_AFTER:
case UC_MEM_READ_UNMAPPED:
return memory_operation::read;
case UC_MEM_WRITE:
case UC_MEM_WRITE_PROT:
case UC_MEM_WRITE_UNMAPPED:
return memory_operation::write;
case UC_MEM_FETCH:
case UC_MEM_FETCH_PROT:
case UC_MEM_FETCH_UNMAPPED:
return memory_operation::exec;
default:
return memory_operation::none;
}
}
struct hook_object : utils::object
{
emulator_hook* as_opaque_hook()
{
return reinterpret_cast<emulator_hook*>(this);
}
};
class hook_container : public hook_object
{
public:
template <typename T>
requires(std::is_base_of_v<utils::object, T> && std::is_move_constructible_v<T>)
void add(T data, unicorn_hook hook)
{
hook_entry entry{};
entry.data = std::make_unique<T>(std::move(data));
entry.hook = std::move(hook);
this->hooks_.emplace_back(std::move(entry));
}
private:
struct hook_entry
{
std::unique_ptr<utils::object> data{};
unicorn_hook hook{};
};
std::vector<hook_entry> hooks_;
};
struct mmio_callbacks
{
using read_wrapper = function_wrapper<uint64_t, uc_engine*, uint64_t, unsigned>;
using write_wrapper = function_wrapper<void, uc_engine*, uint64_t, unsigned, uint64_t>;
read_wrapper read{};
write_wrapper write{};
};
class uc_context_serializer
{
public:
uc_context_serializer(uc_engine* uc, const bool in_place)
: uc_(uc)
{
if (in_place)
{
// Unicorn stores pointers in the struct. The serialization here is broken
throw std::runtime_error("Memory saving not supported atm");
}
#ifndef OS_WINDOWS
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
uc_ctl_context_mode(uc, UC_CTL_CONTEXT_CPU | (in_place ? UC_CTL_CONTEXT_MEMORY : 0));
#ifndef OS_WINDOWS
#pragma GCC diagnostic pop
#endif
this->size_ = uc_context_size(uc);
uce(uc_context_alloc(uc, &this->context_));
}
~uc_context_serializer()
{
if (this->context_)
{
(void)uc_context_free(this->context_);
}
}
void serialize(utils::buffer_serializer& buffer) const
{
uce(uc_context_save(this->uc_, this->context_));
buffer.write(this->context_, this->size_);
}
void deserialize(utils::buffer_deserializer& buffer) const
{
buffer.read(this->context_, this->size_);
uce(uc_context_restore(this->uc_, this->context_));
}
uc_context_serializer(uc_context_serializer&&) = delete;
uc_context_serializer(const uc_context_serializer&) = delete;
uc_context_serializer& operator=(uc_context_serializer&&) = delete;
uc_context_serializer& operator=(const uc_context_serializer&) = delete;
private:
uc_engine* uc_{};
uc_context* context_{};
size_t size_{};
};
basic_block map_block(const uc_tb& translation_block)
{
basic_block block{};
block.address = translation_block.pc;
block.instruction_count = translation_block.icount;
block.size = translation_block.size;
return block;
}
void assert_64bit_limit(const size_t size)
{
if (size > sizeof(uint64_t))
{
throw std::runtime_error("Exceeded uint64_t size limit");
}
}
class unicorn_x64_emulator : public x64_emulator
{
public:
unicorn_x64_emulator()
{
uce(uc_open(UC_ARCH_X86, UC_MODE_64, &this->uc_));
uce(uc_ctl_set_cpu_model(this->uc_, UC_CPU_X86_EPYC_ROME));
#ifndef OS_WINDOWS
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
uce(uc_ctl_set_tcg_buffer_size(this->uc_, 2 << 30 /* 2 gb */));
#ifndef OS_WINDOWS
#pragma GCC diagnostic pop
#endif
}
~unicorn_x64_emulator() override
{
this->hooks_.clear();
uc_close(this->uc_);
}
void start(const size_t count) override
{
this->has_violation_ = false;
const auto start = this->read_instruction_pointer();
constexpr auto end = std::numeric_limits<uint64_t>::max();
const auto res = uc_emu_start(*this, start, end, 0, count);
if (res == UC_ERR_OK)
{
return;
}
const auto is_violation = //
res == UC_ERR_READ_UNMAPPED || //
res == UC_ERR_WRITE_UNMAPPED || //
res == UC_ERR_FETCH_UNMAPPED || //
res == UC_ERR_READ_PROT || //
res == UC_ERR_WRITE_PROT || //
res == UC_ERR_FETCH_PROT;
if (!is_violation || !this->has_violation_)
{
uce(res);
}
}
void stop() override
{
uce(uc_emu_stop(*this));
}
void load_gdt(const pointer_type address, const uint32_t limit) override
{
const std::array<uint64_t, 4> gdtr = {0, address, limit, 0};
this->write_register(x64_register::gdtr, gdtr.data(), gdtr.size() * sizeof(uint64_t));
}
void set_segment_base(const x64_register base, const pointer_type value) override
{
constexpr auto IA32_FS_BASE_MSR = 0xC0000100;
constexpr auto IA32_GS_BASE_MSR = 0xC0000101;
struct msr_value
{
uint32_t id;
uint64_t value;
};
msr_value msr_val{
.id = 0,
.value = value,
};
switch (base)
{
case x64_register::fs:
case x64_register::fs_base:
msr_val.id = IA32_FS_BASE_MSR;
break;
case x64_register::gs:
case x64_register::gs_base:
msr_val.id = IA32_GS_BASE_MSR;
break;
default:
return;
}
this->write_register(x64_register::msr, &msr_val, sizeof(msr_val));
}
size_t write_raw_register(const int reg, const void* value, const size_t size) override
{
auto result_size = size;
uce(uc_reg_write2(*this, reg, value, &result_size));
if (size < result_size)
{
throw std::runtime_error("Register size mismatch: " + std::to_string(size) +
" != " + std::to_string(result_size));
}
return result_size;
}
size_t read_raw_register(const int reg, void* value, const size_t size) override
{
size_t result_size = size;
memset(value, 0, size);
uce(uc_reg_read2(*this, reg, value, &result_size));
if (size < result_size)
{
throw std::runtime_error("Register size mismatch: " + std::to_string(size) +
" != " + std::to_string(result_size));
}
return result_size;
}
void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,
mmio_write_callback write_cb) override
{
auto read_wrapper = [c = std::move(read_cb)](uc_engine*, const uint64_t addr, const uint32_t s) {
assert_64bit_limit(s);
uint64_t value{};
c(addr, &value, s);
return value;
};
auto write_wrapper = [c = std::move(write_cb)](uc_engine*, const uint64_t addr, const uint32_t s,
const uint64_t value) {
assert_64bit_limit(s);
c(addr, &value, s);
};
mmio_callbacks cb{
.read = mmio_callbacks::read_wrapper(std::move(read_wrapper)),
.write = mmio_callbacks::write_wrapper(std::move(write_wrapper)),
};
uce(uc_mmio_map(*this, address, size, cb.read.get_c_function(), cb.read.get_user_data(),
cb.write.get_c_function(), cb.write.get_user_data()));
this->mmio_[address] = std::move(cb);
}
void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override
{
uce(uc_mem_map(*this, address, size, static_cast<uint32_t>(permissions)));
}
void unmap_memory(const uint64_t address, const size_t size) override
{
uce(uc_mem_unmap(*this, address, size));
const auto mmio_entry = this->mmio_.find(address);
if (mmio_entry != this->mmio_.end())
{
this->mmio_.erase(mmio_entry);
}
}
bool try_read_memory(const uint64_t address, void* data, const size_t size) const override
{
return uc_mem_read(*this, address, data, size) == UC_ERR_OK;
}
void read_memory(const uint64_t address, void* data, const size_t size) const override
{
uce(uc_mem_read(*this, address, data, size));
}
void write_memory(const uint64_t address, const void* data, const size_t size) override
{
uce(uc_mem_write(*this, address, data, size));
}
void apply_memory_protection(const uint64_t address, const size_t size,
memory_permission permissions) override
{
uce(uc_mem_protect(*this, address, size, static_cast<uint32_t>(permissions)));
}
emulator_hook* hook_instruction(const int instruction_type, instruction_hook_callback callback) override
{
function_wrapper<int, uc_engine*> wrapper([c = std::move(callback)](uc_engine*) {
return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0;
});
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
const auto inst_type = static_cast<x64_hookable_instructions>(instruction_type);
if (inst_type == x64_hookable_instructions::invalid)
{
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN_INVALID, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
}
else
{
const auto uc_instruction = map_hookable_instruction(inst_type);
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max(),
uc_instruction));
}
container->add(std::move(wrapper), std::move(hook));
auto* result = container->as_opaque_hook();
this->hooks_.push_back(std::move(container));
return result;
}
emulator_hook* hook_basic_block(basic_block_hook_callback callback) override
{
function_wrapper<void, uc_engine*, uint64_t, size_t> wrapper(
[c = std::move(callback)](uc_engine*, const uint64_t address, const size_t size) {
basic_block block{};
block.address = address;
block.size = size;
c(block);
});
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_BLOCK, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
auto* result = container->as_opaque_hook();
this->hooks_.push_back(std::move(container));
return result;
}
emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override
{
function_wrapper<void, uc_engine*, uc_tb*, uc_tb*> wrapper(
[c = std::move(callback)](uc_engine*, const uc_tb* cur_tb, const uc_tb* prev_tb) {
const auto current_block = map_block(*cur_tb);
const auto previous_block = map_block(*prev_tb);
c(current_block, previous_block);
});
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_EDGE_GENERATED, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
auto* result = container->as_opaque_hook();
this->hooks_.push_back(std::move(container));
return result;
}
emulator_hook* hook_interrupt(interrupt_hook_callback callback) override
{
function_wrapper<void, uc_engine*, int> wrapper(
[c = std::move(callback)](uc_engine*, const int interrupt_type) { c(interrupt_type); });
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INTR, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
container->add(std::move(wrapper), std::move(hook));
auto* result = container->as_opaque_hook();
this->hooks_.push_back(std::move(container));
return result;
}
emulator_hook* hook_memory_violation(memory_violation_hook_callback callback) override
{
function_wrapper<bool, uc_engine*, uc_mem_type, uint64_t, int, int64_t> wrapper(
[c = std::move(callback), this](uc_engine*, const uc_mem_type type, const uint64_t address,
const int size, const int64_t) {
const auto ip = this->read_instruction_pointer();
assert(size >= 0);
const auto operation = map_memory_operation(type);
const auto violation = map_memory_violation_type(type);
const auto resume = c(address, static_cast<uint64_t>(size), operation, violation) ==
memory_violation_continuation::resume;
const auto has_ip_changed = ip != this->read_instruction_pointer();
if (!resume)
{
return false;
}
this->has_violation_ = resume && has_ip_changed;
if (has_ip_changed)
{
return false;
}
return true;
});
unicorn_hook hook{*this};
auto container = std::make_unique<hook_container>();
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_MEM_INVALID, wrapper.get_function(),
wrapper.get_user_data(), 0, std::numeric_limits<uint64_t>::max()));
container->add(std::move(wrapper), std::move(hook));
auto* result = container->as_opaque_hook();
this->hooks_.push_back(std::move(container));
return result;
}
emulator_hook* hook_memory_execution(const uint64_t address, const uint64_t size,
memory_execution_hook_callback callback)
{
auto exec_wrapper = [c = std::move(callback)](uc_engine*, const uint64_t address,
const uint32_t /*size*/) {
c(address); //
};
function_wrapper<void, uc_engine*, uint64_t, uint32_t> wrapper(std::move(exec_wrapper));
unicorn_hook hook{*this};
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_CODE, wrapper.get_function(),
wrapper.get_user_data(), address, address + size));
auto* container = this->create_hook_container();
container->add(std::move(wrapper), std::move(hook));
return container->as_opaque_hook();
}
emulator_hook* hook_memory_execution(memory_execution_hook_callback callback) override
{
return this->hook_memory_execution(0, std::numeric_limits<uint64_t>::max(), std::move(callback));
}
emulator_hook* hook_memory_execution(const uint64_t address,
memory_execution_hook_callback callback) override
{
return this->hook_memory_execution(address, 1, std::move(callback));
}
emulator_hook* hook_memory_read(const uint64_t address, const size_t size,
memory_access_hook_callback callback) override
{
auto read_wrapper = [c = std::move(callback)](uc_engine*, const uc_mem_type type,
const uint64_t address, const int size,
const uint64_t value) {
const auto operation = map_memory_operation(type);
if (operation == memory_operation::read && size > 0)
{
c(address, &value, std::min(static_cast<size_t>(size), sizeof(value)));
}
};
function_wrapper<void, uc_engine*, uc_mem_type, uint64_t, int, int64_t> wrapper(
std::move(read_wrapper));
unicorn_hook hook{*this};
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_MEM_READ_AFTER, wrapper.get_function(),
wrapper.get_user_data(), address, address + size));
auto* container = this->create_hook_container();
container->add(std::move(wrapper), std::move(hook));
return container->as_opaque_hook();
}
emulator_hook* hook_memory_write(const uint64_t address, const size_t size,
memory_access_hook_callback callback) override
{
auto write_wrapper = [c = std::move(callback)](uc_engine*, const uc_mem_type type, const uint64_t addr,
const int length, const uint64_t value) {
const auto operation = map_memory_operation(type);
if (operation == memory_operation::write && length > 0)
{
c(addr, &value, std::min(static_cast<size_t>(length), sizeof(value)));
}
};
function_wrapper<void, uc_engine*, uc_mem_type, uint64_t, int, int64_t> wrapper(
std::move(write_wrapper));
unicorn_hook hook{*this};
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_MEM_WRITE, wrapper.get_function(),
wrapper.get_user_data(), address, address + size));
auto* container = this->create_hook_container();
container->add(std::move(wrapper), std::move(hook));
return container->as_opaque_hook();
}
hook_container* create_hook_container()
{
auto container = std::make_unique<hook_container>();
auto* ptr = container.get();
this->hooks_.push_back(std::move(container));
return ptr;
}
void delete_hook(emulator_hook* hook) override
{
const auto entry =
std::ranges::find_if(this->hooks_, [&](const std::unique_ptr<hook_object>& hook_ptr) {
return hook_ptr->as_opaque_hook() == hook;
});
if (entry != this->hooks_.end())
{
this->hooks_.erase(entry);
}
}
operator uc_engine*() const
{
return this->uc_;
}
void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override
{
if (this->has_snapshots_ && !is_snapshot)
{
// TODO: Investigate if this is really necessary
throw std::runtime_error("Unable to serialize after snapshot was taken!");
}
this->has_snapshots_ |= is_snapshot;
const uc_context_serializer serializer(this->uc_, is_snapshot);
serializer.serialize(buffer);
}
void deserialize_state(utils::buffer_deserializer& buffer, const bool is_snapshot) override
{
if (this->has_snapshots_ && !is_snapshot)
{
// TODO: Investigate if this is really necessary
throw std::runtime_error("Unable to deserialize after snapshot was taken!");
}
const uc_context_serializer serializer(this->uc_, is_snapshot);
serializer.deserialize(buffer);
}
std::vector<std::byte> save_registers() const override
{
utils::buffer_serializer buffer{};
const uc_context_serializer serializer(this->uc_, false);
serializer.serialize(buffer);
return buffer.move_buffer();
}
void restore_registers(const std::vector<std::byte>& register_data) override
{
utils::buffer_deserializer buffer{register_data};
const uc_context_serializer serializer(this->uc_, false);
serializer.deserialize(buffer);
}
bool has_violation() const override
{
return this->has_violation_;
}
std::string get_name() const override
{
return "Unicorn Engine";
}
private:
mutable bool has_snapshots_{false};
uc_engine* uc_{};
bool has_violation_{false};
std::vector<std::unique_ptr<hook_object>> hooks_{};
std::unordered_map<uint64_t, mmio_callbacks> mmio_{};
};
}
std::unique_ptr<x64_emulator> create_x64_emulator()
{
return std::make_unique<unicorn_x64_emulator>();
}
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <memory>
#include <x64_emulator.hpp>
#include "platform/platform.hpp"
#ifdef UNICORN_EMULATOR_IMPL
#define UNICORN_EMULATOR_DLL_STORAGE EXPORT_SYMBOL
#else
#define UNICORN_EMULATOR_DLL_STORAGE IMPORT_SYMBOL
#endif
namespace unicorn
{
#if !MOMO_BUILD_AS_LIBRARY
UNICORN_EMULATOR_DLL_STORAGE
#endif
std::unique_ptr<x64_emulator> create_x64_emulator();
}