mirror of
https://github.com/open-goal/jak-project
synced 2026-08-18 13:53:01 -04:00
goalc: replicate tests for the majority of ARM64 non-simd cases (#4377)
- Adds `capstone` as a disassembling library that could eventually replace Zydis (for now left that alone) - Replicates all of the existing x86 tests to ARM64, fixed a bunch of underlying issues along the way - There are a very small handful of tests remaining that need to be enabled / fixed
This commit is contained in:
+24
-1
@@ -192,13 +192,17 @@ endif()
|
||||
|
||||
function(build_third_party_lib dir_name target_name)
|
||||
add_subdirectory(third-party/${dir_name} EXCLUDE_FROM_ALL)
|
||||
# Convert all public include dirs to SYSTEM
|
||||
# Treat third-party headers as system headers.
|
||||
get_target_property(INCLUDES ${target_name} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if(INCLUDES)
|
||||
set_target_properties(${target_name} PROPERTIES
|
||||
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${INCLUDES}"
|
||||
)
|
||||
endif()
|
||||
# Suppress all warnings while compiling the third-party library itself.
|
||||
target_compile_options(${target_name} PRIVATE
|
||||
-w
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Dependencies and Libraries
|
||||
@@ -349,6 +353,25 @@ endif()
|
||||
|
||||
build_third_party_lib(zydis Zydis)
|
||||
|
||||
# Capstone (zydis replacement eventually)
|
||||
option(CAPSTONE_ARCHITECTURE_DEFAULT "Capstone: Disable all by default" OFF)
|
||||
option(CAPSTONE_X86_SUPPORT "Capstone: x86 support" ON)
|
||||
option(CAPSTONE_ARM_SUPPORT "Capstone: ARM support" ON)
|
||||
option(CAPSTONE_AARCH64_SUPPORT "Capstone: ARM64 support" ON)
|
||||
|
||||
if(STATICALLY_LINK)
|
||||
message(STATUS "Statically linking capstone")
|
||||
option(CAPSTONE_BUILD_SHARED_LIBS "Capstone: Build shared library" OFF)
|
||||
option(CAPSTONE_BUILD_STATIC_LIBS "Capstone: Build static library" ON)
|
||||
else()
|
||||
message(STATUS "dynamically linking capstone")
|
||||
option(CAPSTONE_BUILD_SHARED_LIBS "Capstone: Build shared library" ON)
|
||||
option(CAPSTONE_BUILD_STATIC_LIBS "Capstone: Build static library" OFF)
|
||||
endif()
|
||||
|
||||
include_directories(third-party/capstone/include)
|
||||
build_third_party_lib(capstone capstone)
|
||||
|
||||
# windows memory management lib
|
||||
if(WIN32)
|
||||
build_third_party_lib(mman mman)
|
||||
|
||||
+138
-44
@@ -1,5 +1,7 @@
|
||||
#include "os.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/string_util.h"
|
||||
@@ -46,17 +48,133 @@ void __cpuidex(int result[4], int eax, int ecx) {
|
||||
: "=a"(result[0]), "=b"(result[1]), "=c"(result[2]), "=d"(result[3])
|
||||
: "0"(eax), "2"(ecx));
|
||||
}
|
||||
#else
|
||||
// TODO ARM - implement ARM64 detection, check for NEON instead of AVX
|
||||
// for now, just return 0's.
|
||||
void __cpuidex(int result[4], int eax, int ecx) {
|
||||
lg::warn("cpuid not implemented on this platform");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
result[i] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void setup_cpu_info_windows(CpuInfo& info) {
|
||||
#if defined(_M_X64) || defined(_M_IX86)
|
||||
// Brand string
|
||||
{
|
||||
int result[4];
|
||||
__cpuidex(result, 0, 0);
|
||||
|
||||
for (int r : {1, 3, 2}) {
|
||||
int reg = result[r];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
info.brand.push_back(reg & 0xff);
|
||||
reg >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Model string
|
||||
for (int leaf = 0x80000002; leaf <= 0x80000004; leaf++) {
|
||||
int result[4];
|
||||
__cpuidex(result, leaf, 0);
|
||||
|
||||
for (int reg : result) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
info.model.push_back(reg & 0xff);
|
||||
reg >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
int result[4];
|
||||
__cpuidex(result, 1, 0);
|
||||
info.has_avx = result[2] & (1 << 28);
|
||||
}
|
||||
{
|
||||
int result[4];
|
||||
__cpuidex(result, 7, 0);
|
||||
info.has_avx2 = result[1] & (1 << 5);
|
||||
}
|
||||
#elif defined(_M_ARM64)
|
||||
info.brand = "ARM";
|
||||
HKEY key;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
|
||||
KEY_READ, &key) == ERROR_SUCCESS) {
|
||||
char buf[256];
|
||||
DWORD size = sizeof(buf);
|
||||
if (RegQueryValueExA(key, "ProcessorNameString", nullptr, nullptr, reinterpret_cast<BYTE*>(buf),
|
||||
&size) == ERROR_SUCCESS) {
|
||||
info.model = buf;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
info.has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup_cpu_info_linux(CpuInfo& info) {
|
||||
std::ifstream cpuinfo("/proc/cpuinfo");
|
||||
std::string line;
|
||||
while (std::getline(cpuinfo, line)) {
|
||||
auto colon = line.find(':');
|
||||
if (colon == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
std::string key = line.substr(0, colon);
|
||||
std::string value = line.substr(colon + 1);
|
||||
while (!value.empty() && value.front() == ' ') {
|
||||
value.erase(value.begin());
|
||||
}
|
||||
if (info.brand.empty() && key == "vendor_id") {
|
||||
info.brand = value;
|
||||
}
|
||||
if (info.model.empty() && (key == "model name" || key == "Processor")) {
|
||||
info.model = value;
|
||||
}
|
||||
}
|
||||
#if defined(__aarch64__)
|
||||
info.brand = "ARM";
|
||||
#ifdef HWCAP_ASIMD
|
||||
info.has_neon = getauxval(AT_HWCAP) & HWCAP_ASIMD;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
int result[4];
|
||||
__cpuidex(result, 1, 0);
|
||||
info.has_avx = result[2] & (1 << 28);
|
||||
__cpuidex(result, 7, 0);
|
||||
info.has_avx2 = result[1] & (1 << 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup_cpu_info_macos(CpuInfo& info) {
|
||||
#if defined(__x86_64__)
|
||||
int result[4];
|
||||
__cpuidex(result, 0, 0);
|
||||
for (int r : {1, 3, 2}) {
|
||||
int reg = result[r];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
info.brand.push_back(reg & 0xff);
|
||||
reg >>= 8;
|
||||
}
|
||||
}
|
||||
for (int leaf = 0x80000002; leaf <= 0x80000004; leaf++) {
|
||||
__cpuidex(result, leaf, 0);
|
||||
for (int reg : result) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
info.model.push_back(reg & 0xff);
|
||||
reg >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
__cpuidex(result, 1, 0);
|
||||
info.has_avx = result[2] & (1 << 28);
|
||||
__cpuidex(result, 7, 0);
|
||||
info.has_avx2 = result[1] & (1 << 5);
|
||||
#elif defined(__aarch64__) || defined(__arm64__)
|
||||
info.brand = "Apple";
|
||||
char buf[128];
|
||||
size_t len = sizeof(buf);
|
||||
if (sysctlbyname("hw.model", buf, &len, nullptr, 0) == 0) {
|
||||
info.model = buf;
|
||||
}
|
||||
info.has_neon = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
CpuInfo gCpuInfo;
|
||||
|
||||
void setup_cpu_info() {
|
||||
@@ -64,47 +182,23 @@ void setup_cpu_info() {
|
||||
return;
|
||||
}
|
||||
|
||||
// as a test, get the brand and model
|
||||
for (u32 i = 0x80000002; i <= 0x80000004; i++) {
|
||||
int result[4];
|
||||
__cpuidex(result, i, 0);
|
||||
for (auto reg : result) {
|
||||
for (int c = 0; c < 4; c++) {
|
||||
gCpuInfo.model.push_back(reg);
|
||||
reg >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int result[4];
|
||||
__cpuidex(result, 0, 0);
|
||||
for (auto r : {1, 3, 2}) {
|
||||
for (int c = 0; c < 4; c++) {
|
||||
gCpuInfo.brand.push_back(result[r]);
|
||||
result[r] >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for AVX2
|
||||
{
|
||||
int result[4];
|
||||
__cpuidex(result, 7, 0);
|
||||
gCpuInfo.has_avx2 = result[1] & (1 << 5);
|
||||
}
|
||||
|
||||
{
|
||||
int result[4];
|
||||
__cpuidex(result, 1, 0);
|
||||
gCpuInfo.has_avx = result[2] & (1 << 28);
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
setup_cpu_info_windows(gCpuInfo);
|
||||
#elif defined(__APPLE__)
|
||||
setup_cpu_info_macos(gCpuInfo);
|
||||
#elif defined(__linux__)
|
||||
setup_cpu_info_linux(gCpuInfo);
|
||||
#else
|
||||
gCpuInfo.brand = "Unknown Brand";
|
||||
gCpuInfo.model = "Unknown Model";
|
||||
#endif
|
||||
|
||||
printf("-------- CPU Information --------\n");
|
||||
printf(" Brand: %s\n", gCpuInfo.brand.c_str());
|
||||
printf(" Model: %s\n", gCpuInfo.model.c_str());
|
||||
printf(" AVX : %s\n", gCpuInfo.has_avx ? "true" : "false");
|
||||
printf(" AVX2 : %s\n", gCpuInfo.has_avx2 ? "true" : "false");
|
||||
printf(" NEON : %s\n", gCpuInfo.has_neon ? "true" : "false");
|
||||
fflush(stdout);
|
||||
|
||||
gCpuInfo.initialized = true;
|
||||
|
||||
@@ -11,6 +11,7 @@ struct CpuInfo {
|
||||
bool initialized = false;
|
||||
bool has_avx = false;
|
||||
bool has_avx2 = false;
|
||||
bool has_neon = false;
|
||||
|
||||
std::string brand;
|
||||
std::string model;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; name: nav-graph-h.gc
|
||||
;; name in dgo: nav-graph-h
|
||||
|
||||
;; Omitted from jakx, but the types are still used!
|
||||
@@ -85,7 +85,7 @@ add_library(compiler
|
||||
regalloc/Allocator_v2.cpp
|
||||
compiler/docs/DocTypes.cpp)
|
||||
|
||||
target_link_libraries(compiler common Zydis tiny_gltf decomp)
|
||||
target_link_libraries(compiler common Zydis capstone tiny_gltf decomp)
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(compiler mman)
|
||||
@@ -97,7 +97,7 @@ add_executable(goalc-simple simple_main.cpp)
|
||||
add_executable(build_level build_level/main.cpp)
|
||||
add_executable(build_actor build_actor/main.cpp)
|
||||
|
||||
target_link_libraries(goalc common Zydis compiler)
|
||||
target_link_libraries(goalc-simple common Zydis compiler)
|
||||
target_link_libraries(build_level common Zydis compiler)
|
||||
target_link_libraries(build_actor common Zydis compiler)
|
||||
target_link_libraries(goalc common Zydis capstone compiler)
|
||||
target_link_libraries(goalc-simple common Zydis capstone compiler)
|
||||
target_link_libraries(build_level common Zydis capstone compiler)
|
||||
target_link_libraries(build_actor common Zydis capstone compiler)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "CodeTester.h"
|
||||
#include "IGen.h"
|
||||
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
namespace emitter {
|
||||
|
||||
CodeTester::CodeTester() : m_info(RegisterInfo::make_register_info()), m_gen(GameVersion::Jak1) {}
|
||||
@@ -54,6 +56,181 @@ std::string CodeTester::dump_to_hex_string(bool nospace) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void CodeTester::print_hex_dump() {
|
||||
printf("%s\n", dump_to_hex_string(true).data());
|
||||
}
|
||||
void CodeTester::print_asm_dump() {
|
||||
printf("%s\n", dump_to_asm_string().data());
|
||||
}
|
||||
|
||||
static constexpr int first_saved_gpr = 1;
|
||||
static constexpr int first_saved_simd = 0;
|
||||
|
||||
static std::optional<size_t> match_push_gprs(const std::vector<CodeTester::DisasmLine>& lines,
|
||||
int last_gpr,
|
||||
size_t start) {
|
||||
const int count = last_gpr - first_saved_gpr + 1;
|
||||
|
||||
if (start + count > lines.size()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int reg = first_saved_gpr + i;
|
||||
|
||||
std::string expected = "str\tx" + std::to_string(reg) + ", [sp, #-0x10]!";
|
||||
|
||||
if (lines[start + i].text != expected) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<size_t>(count);
|
||||
}
|
||||
|
||||
static std::optional<size_t> match_pop_gprs(const std::vector<CodeTester::DisasmLine>& lines,
|
||||
int last_gpr,
|
||||
size_t start) {
|
||||
const int count = last_gpr - first_saved_gpr + 1;
|
||||
|
||||
if (start + count > lines.size()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int reg = last_gpr - i;
|
||||
|
||||
std::string expected = "ldr\tx" + std::to_string(reg) + ", [sp], #0x10";
|
||||
|
||||
if (lines[start + i].text != expected) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<size_t>(count);
|
||||
}
|
||||
|
||||
static std::optional<size_t> match_push_simd(const std::vector<CodeTester::DisasmLine>& lines,
|
||||
int last_simd,
|
||||
size_t start) {
|
||||
const int count = last_simd - first_saved_simd + 1;
|
||||
const size_t line_count = static_cast<size_t>(count) * 2;
|
||||
|
||||
if (start + line_count > lines.size()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int reg = first_saved_simd + i;
|
||||
|
||||
std::string expected_sub = "sub\tsp, sp, #0x10";
|
||||
std::string expected_str = "str\tq" + std::to_string(reg) + ", [sp]";
|
||||
|
||||
if (lines[start + i * 2].text != expected_sub ||
|
||||
lines[start + i * 2 + 1].text != expected_str) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return line_count;
|
||||
}
|
||||
|
||||
static std::optional<size_t> match_pop_simd(const std::vector<CodeTester::DisasmLine>& lines,
|
||||
int last_simd,
|
||||
size_t start) {
|
||||
const int count = last_simd - first_saved_simd + 1;
|
||||
const size_t line_count = static_cast<size_t>(count) * 2;
|
||||
|
||||
if (start + line_count > lines.size()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int reg = last_simd - i;
|
||||
|
||||
std::string expected_ldr = "ldr\tq" + std::to_string(reg) + ", [sp]";
|
||||
std::string expected_add = "add\tsp, sp, #0x10";
|
||||
|
||||
if (lines[start + i * 2].text != expected_ldr ||
|
||||
lines[start + i * 2 + 1].text != expected_add) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return line_count;
|
||||
}
|
||||
|
||||
std::vector<CodeTester::DisasmLine> CodeTester::disassemble() {
|
||||
std::vector<DisasmLine> result;
|
||||
|
||||
csh handle;
|
||||
if (cs_open(CS_ARCH_AARCH64, CS_MODE_ARM, &handle) != CS_ERR_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
cs_insn* insn = nullptr;
|
||||
size_t count = cs_disasm(handle, code_buffer, code_buffer_size, 0, 0, &insn);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
DisasmLine line;
|
||||
line.address = insn[i].address;
|
||||
|
||||
// Keep only the mnemonic + operands for pattern matching
|
||||
line.text = std::string(insn[i].mnemonic) + "\t" + insn[i].op_str;
|
||||
|
||||
result.push_back(std::move(line));
|
||||
}
|
||||
|
||||
cs_free(insn, count);
|
||||
cs_close(&handle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CodeTester::dump_to_asm_string() {
|
||||
auto lines = disassemble();
|
||||
|
||||
// x31 is SP/ZR, not a GPR. The last real GPR is one before it.
|
||||
const int last_gpr = get_reg_count() - 1;
|
||||
|
||||
// SIMD registers are V0-V31.
|
||||
const int last_simd = get_simd_reg_count() - 1;
|
||||
|
||||
std::string result;
|
||||
for (size_t i = 0; i < lines.size();) {
|
||||
if (auto count = match_push_gprs(lines, last_gpr, i)) {
|
||||
result += "\033[2m<push all GPRs>\033[0m\n";
|
||||
i += *count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto count = match_pop_gprs(lines, last_gpr, i)) {
|
||||
result += "\033[2m<pop all GPRs>\033[0m\n";
|
||||
i += *count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto count = match_push_simd(lines, last_simd, i)) {
|
||||
result += "\033[2m<push all SIMDs>\033[0m\n";
|
||||
i += *count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto count = match_pop_simd(lines, last_simd, i)) {
|
||||
result += "\033[2m<pop all SIMDs>\033[0m\n";
|
||||
i += *count;
|
||||
continue;
|
||||
}
|
||||
|
||||
char buff[128];
|
||||
snprintf(buff, sizeof(buff), "%08llx:\t%s\n", lines[i].address, lines[i].text.c_str());
|
||||
result += buff;
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add an instruction to the buffer.
|
||||
*/
|
||||
@@ -124,6 +301,7 @@ void CodeTester::emit_push_all_simd() {
|
||||
emit(IGen::store128_gpr64_simd128(m_gen, RSP, XMM0 + i));
|
||||
}
|
||||
} else if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
// TODO - 16 or 32 simd regs available?
|
||||
for (int i = 0; i < 16; i++) {
|
||||
emit(IGen::sub_gpr64_imm8s(m_gen, SP, 16));
|
||||
emit(IGen::store128_gpr64_simd128(m_gen, SP, V0 + i));
|
||||
@@ -138,13 +316,13 @@ void CodeTester::emit_push_all_simd() {
|
||||
*/
|
||||
void CodeTester::emit_pop_all_simd() {
|
||||
if (m_gen.instr_set() == InstructionSet::X86) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
emit(IGen::load128_simd128_gpr64(m_gen, XMM0 + i, RSP));
|
||||
emit(IGen::add_gpr64_imm8s(m_gen, RSP, 16));
|
||||
}
|
||||
emit(IGen::add_gpr64_imm8s(m_gen, RSP, 8));
|
||||
} else if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
emit(IGen::load128_simd128_gpr64(m_gen, V0 + i, SP));
|
||||
emit(IGen::add_gpr64_imm8s(m_gen, SP, 16));
|
||||
}
|
||||
|
||||
@@ -35,13 +35,22 @@ class CodeTester {
|
||||
ObjectGenerator m_gen;
|
||||
|
||||
public:
|
||||
struct DisasmLine {
|
||||
uint64_t address;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
CodeTester();
|
||||
CodeTester(InstructionSet instruction_set);
|
||||
std::string dump_to_hex_string(bool nospace = false);
|
||||
std::vector<DisasmLine> disassemble();
|
||||
std::string dump_to_asm_string();
|
||||
void print_hex_dump();
|
||||
void print_asm_dump();
|
||||
ObjectGenerator generator() const { return m_gen; }
|
||||
void init_code_buffer(int capacity);
|
||||
void emit_push_all_gprs(bool exclude_rax = false);
|
||||
void emit_pop_all_gprs(bool exclude_rax = false);
|
||||
void emit_push_all_gprs(bool exclude_return_register = false);
|
||||
void emit_pop_all_gprs(bool exclude_return_register = false);
|
||||
void emit_push_all_simd();
|
||||
void emit_pop_all_simd();
|
||||
void emit_return();
|
||||
@@ -91,10 +100,64 @@ class CodeTester {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_reg_count() {
|
||||
if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
return 31; // 32 = XZR which is a special case / zero register
|
||||
} else {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
int get_simd_reg_count() {
|
||||
if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
return 16; // TODO - check if platform has 16 or 32
|
||||
} else {
|
||||
return -1; // TODO
|
||||
}
|
||||
}
|
||||
|
||||
Register get_stack_reg() {
|
||||
if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
return SP;
|
||||
} else {
|
||||
return RSP;
|
||||
}
|
||||
}
|
||||
|
||||
Register get_return_reg() {
|
||||
if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
return X0;
|
||||
} else {
|
||||
return RAX;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Should allow emitter tests which run code to do the right thing on windows.
|
||||
*/
|
||||
Register get_c_abi_arg_reg(int i) {
|
||||
if (m_gen.instr_set() == InstructionSet::ARM64) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return X0;
|
||||
case 1:
|
||||
return X1;
|
||||
case 2:
|
||||
return X2;
|
||||
case 3:
|
||||
return X3;
|
||||
case 4:
|
||||
return X4;
|
||||
case 5:
|
||||
return X5;
|
||||
case 6:
|
||||
return X6;
|
||||
case 7:
|
||||
return X7;
|
||||
default:
|
||||
throw std::runtime_error("Invalid ARM64 arg register index");
|
||||
}
|
||||
}
|
||||
// TODO ARM64 - x86 specific
|
||||
#ifdef _WIN32
|
||||
switch (i) {
|
||||
@@ -136,6 +199,8 @@ class CodeTester {
|
||||
int size() const { return code_buffer_size; }
|
||||
const u8* data() const { return code_buffer; }
|
||||
|
||||
uintptr_t code_address() const { return reinterpret_cast<uintptr_t>(code_buffer); }
|
||||
|
||||
/*!
|
||||
* Write over existing data at the given offset.
|
||||
*/
|
||||
|
||||
+129
-98
@@ -3,9 +3,13 @@
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#include "goalc/emitter/IGen.h"
|
||||
#include "goalc/emitter/Instruction.h"
|
||||
#include "goalc/emitter/InstructionSet.h"
|
||||
#include "goalc/emitter/Register.h"
|
||||
#include <fmt/base.h>
|
||||
|
||||
// https://armconverter.com/?code=ret
|
||||
// https://developer.arm.com/documentation/ddi0487/latest
|
||||
@@ -39,6 +43,26 @@ std::tuple<bool, u16, bool> can_encode_single_imm12(u64 imm) {
|
||||
return {false, 0, false};
|
||||
}
|
||||
|
||||
// TODO - imm12 decomposition produces way too many chunks for what will be common operations,
|
||||
// update the instructions that we can to instead use the movz/movk pattern
|
||||
//
|
||||
// Decompose a 64-bit immediate into 16-bit chunks suitable for movz/movk.
|
||||
// Returns {chunk, shift} pairs where shift is one of 0,16,32,48.
|
||||
std::vector<std::tuple<u16, u8>> decompose_into_imm16_chunks(u64 imm) {
|
||||
std::vector<std::tuple<u16, u8>> result;
|
||||
if (imm == 0) {
|
||||
result.emplace_back(0, 0);
|
||||
return result;
|
||||
}
|
||||
for (u8 shift = 0; shift <= 48; shift += 16) {
|
||||
u16 chunk = static_cast<u16>((imm >> shift) & 0xFFFF);
|
||||
if (chunk != 0 || result.empty()) {
|
||||
result.emplace_back(chunk, shift / 16);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Given a larger than u12 immediate, decompose it into multiple (shifted or not)
|
||||
// immediates that can be used to emit multiple instructions to produce the desired outcome
|
||||
std::vector<std::tuple<u16, bool>> decompose_into_imm12_chunks(u64 imm) {
|
||||
@@ -94,31 +118,28 @@ InstructionARM64 mov_gpr64_gpr64(Register dst, Register src) {
|
||||
Imm6(0));
|
||||
}
|
||||
|
||||
InstructionARM64 mov_gpr64_u64(Register dst, uint64_t val) {
|
||||
std::vector<InstructionARM64> mov_gpr64_u64_instrs(Register dst, uint64_t val) {
|
||||
// Cannot be done in a single instruction, must combine multiple MOVZ/MOVKs
|
||||
std::vector<InstructionARM64> instrs;
|
||||
bool emitted_movz = false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
u16 chunk = (val >> (i * 16)) & 0xFFFF;
|
||||
if (!emitted_movz && chunk != 0) {
|
||||
auto imm_chunks = decompose_into_imm16_chunks(val);
|
||||
for (const auto& [imm_chunk, shift] : imm_chunks) {
|
||||
if (shift == 0) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/movz.html
|
||||
// MOVZ <Xd>, #<imm>{, LSL #<shift>/16}
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b110100101, 9), Hw(i), Imm16(chunk), Rd(dst.id())));
|
||||
emitted_movz = true;
|
||||
} else if (emitted_movz && chunk != 0) {
|
||||
InstructionARM64(Base(0b110100101, 9), Hw(shift), Imm16(imm_chunk), Rd(dst.id())));
|
||||
} else {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/movk.html
|
||||
// MOVK <Xd>, #<imm>{, LSL #<shift>/16}
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b111100101, 9), Hw(i), Imm16(chunk), Rd(dst.id())));
|
||||
InstructionARM64(Base(0b111100101, 9), Hw(shift), Imm16(imm_chunk), Rd(dst.id())));
|
||||
}
|
||||
}
|
||||
if (!emitted_movz) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/movz.html
|
||||
// MOVZ <Xd>, #<imm>{, LSL #0}
|
||||
instrs.emplace_back(InstructionARM64(Base(0b110100101, 9), Hw(0), Imm16(0), Rd(dst.id())));
|
||||
}
|
||||
return InstructionARM64(instrs);
|
||||
return instrs;
|
||||
}
|
||||
|
||||
InstructionARM64 mov_gpr64_u64(Register dst, uint64_t val) {
|
||||
return InstructionARM64(mov_gpr64_u64_instrs(dst, val));
|
||||
}
|
||||
|
||||
InstructionARM64 mov_gpr64_u32(Register dst, uint64_t val) {
|
||||
@@ -379,6 +400,7 @@ InstructionARM64 load8u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
|
||||
// ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
InstructionARM64(Base(0b10001011000, 11), Rd(X16), Imm6(0), Rn(addr1.id()), Rm(addr2.id())),
|
||||
};
|
||||
// TODO - movk instead eventually
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
@@ -391,8 +413,7 @@ InstructionARM64 load8u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
|
||||
// finally do the load
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldrb_imm.html
|
||||
// LDRB <Xt>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b0011100101, 10), Imm12(offset), Rt(dst.id()), Rn(X16)));
|
||||
instrs.emplace_back(InstructionARM64(Base(0b0011100101, 10), Imm12(0), Rt(dst.id()), Rn(X16)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -418,7 +439,7 @@ InstructionARM64 store16_gpr64_gpr64_plus_gpr64(Register addr1, Register addr2,
|
||||
ASSERT(addr1 != addr2);
|
||||
ASSERT(addr1 != SP);
|
||||
ASSERT(addr2 != SP);
|
||||
return InstructionARM64(Base(0b0111100000100000000010, 22), Rt(value.id()), Rn(addr1.id()),
|
||||
return InstructionARM64(Base(0b0111100000100000111010, 22), Rt(value.id()), Rn(addr1.id()),
|
||||
Rm(addr2.id()));
|
||||
}
|
||||
|
||||
@@ -607,8 +628,7 @@ InstructionARM64 load16u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
|
||||
// finally do the load
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldrh_imm.html
|
||||
// LDRH <Wt>, [<Xn|SP>{, #<pimm>}]
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b0111100101, 10), Imm12(offset), Rt(dst.id()), Rn(X16)));
|
||||
instrs.emplace_back(InstructionARM64(Base(0b0111100101, 10), Imm12(0), Rt(dst.id()), Rn(X16)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -758,7 +778,7 @@ InstructionARM64 store32_gpr64_gpr64_plus_gpr64_plus_s32(Register addr1,
|
||||
|
||||
InstructionARM64 load32u_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_reg_gen.html
|
||||
// 32-bit variant
|
||||
// 32-bit variant, SXTX
|
||||
// LDR <Wt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]
|
||||
ASSERT(dst.is_gpr(instr_set));
|
||||
ASSERT(addr1.is_gpr(instr_set));
|
||||
@@ -766,7 +786,7 @@ InstructionARM64 load32u_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Re
|
||||
ASSERT(addr1 != addr2);
|
||||
ASSERT(addr1 != SP);
|
||||
ASSERT(addr2 != SP);
|
||||
return InstructionARM64(Base(0b1011100001100000000010, 22), Rt(dst.id()), Rn(addr1.id()),
|
||||
return InstructionARM64(Base(0b1011100001100000111010, 22), Rt(dst.id()), Rn(addr1.id()),
|
||||
Rm(addr2.id()));
|
||||
}
|
||||
|
||||
@@ -829,7 +849,7 @@ InstructionARM64 load32u_gpr64_gpr64_plus_gpr64_plus_s32(Register dst,
|
||||
|
||||
InstructionARM64 load64_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Register addr2) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_reg_gen.html
|
||||
// 64 bit mode
|
||||
// 64 bit mode, SXTX
|
||||
// LDR <Xt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]
|
||||
ASSERT(dst.is_gpr(instr_set));
|
||||
ASSERT(addr1.is_gpr(instr_set));
|
||||
@@ -837,7 +857,7 @@ InstructionARM64 load64_gpr64_gpr64_plus_gpr64(Register dst, Register addr1, Reg
|
||||
ASSERT(addr1 != addr2);
|
||||
ASSERT(addr1 != SP);
|
||||
ASSERT(addr2 != SP);
|
||||
return InstructionARM64(Base(0b1111100001100000000010, 22), Rt(dst.id()), Rn(addr1.id()),
|
||||
return InstructionARM64(Base(0b1111100001100000111010, 22), Rt(dst.id()), Rn(addr1.id()),
|
||||
Rm(addr2.id()));
|
||||
}
|
||||
|
||||
@@ -1263,8 +1283,8 @@ InstructionARM64 store32_xmm32_gpr64_plus_gpr64(Register addr1,
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_reg_fpsimd.html
|
||||
// 32-bit variant
|
||||
// STR <St>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]
|
||||
return InstructionARM64(Base(0b1011110000100000000010, 22), Rt(xmm_value.id()), Rm(addr1.id()),
|
||||
Rn(addr2.id()));
|
||||
return InstructionARM64(Base(0b1011110000100000110010, 22), Rt(xmm_value.id()), Rm(addr2.id()),
|
||||
Rn(addr1.id()));
|
||||
}
|
||||
|
||||
InstructionARM64 load32_xmm32_gpr64_plus_gpr64(Register simd_dest, Register addr1, Register addr2) {
|
||||
@@ -1292,20 +1312,21 @@ InstructionARM64 store32_xmm32_gpr64_plus_gpr64_plus_s8(Register addr1,
|
||||
// ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
InstructionARM64(Base(0b10001011000, 11), Rd(X16), Imm6(0), Rn(addr1.id()), Rm(addr2.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
// STR <St>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b1011110100000000000001, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
InstructionARM64(Base(0b1011110100000000000000, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -1323,14 +1344,15 @@ InstructionARM64 load32_xmm32_gpr64_plus_gpr64_plus_s8(Register simd_dest,
|
||||
// ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
InstructionARM64(Base(0b10001011000, 11), Rd(X16), Imm6(0), Rn(addr1.id()), Rm(addr2.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
@@ -1354,20 +1376,21 @@ InstructionARM64 store32_xmm32_gpr64_plus_gpr64_plus_s32(Register addr1,
|
||||
// ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
InstructionARM64(Base(0b10001011000, 11), Rd(X16), Imm6(0), Rn(addr1.id()), Rm(addr2.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
// STR <St>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b1011110100000000000001, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
InstructionARM64(Base(0b1011110100000000000000, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -1381,20 +1404,21 @@ InstructionARM64 store32_xmm32_gpr64_plus_s32(Register base, Register xmm_value,
|
||||
// ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}
|
||||
InstructionARM64(Base(0b100100010, 9), Sh(0), Imm12(0), Rd(X16), Rn(base.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
// STR <St>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b1011110100000000000001, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
InstructionARM64(Base(0b1011110100000000000000, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -1408,20 +1432,21 @@ InstructionARM64 store32_xmm32_gpr64_plus_s8(Register base, Register xmm_value,
|
||||
// ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}
|
||||
InstructionARM64(Base(0b100100010, 9), Sh(0), Imm12(0), Rd(X16), Rn(base.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||
// 32-bit variant, unsigned
|
||||
// STR <St>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b1011110100000000000001, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
InstructionARM64(Base(0b1011110100000000000000, 22), Imm12(0), Rt(xmm_value.id()), Rn(X16)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -1439,14 +1464,15 @@ InstructionARM64 load32_xmm32_gpr64_plus_gpr64_plus_s32(Register simd_dest,
|
||||
// ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
InstructionARM64(Base(0b10001011000, 11), Rd(X16), Imm6(0), Rn(addr1.id()), Rm(addr2.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
@@ -1466,14 +1492,15 @@ InstructionARM64 load32_xmm32_gpr64_plus_s32(Register simd_dest, Register base,
|
||||
// ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}
|
||||
InstructionARM64(Base(0b100100010, 9), Sh(0), Imm12(0), Rd(X16), Rn(base.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
@@ -1493,14 +1520,15 @@ InstructionARM64 load32_xmm32_gpr64_plus_s8(Register simd_dest, Register base, s
|
||||
// ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}
|
||||
InstructionARM64(Base(0b100100010, 9), Sh(0), Imm12(0), Rd(X16), Rn(base.id())),
|
||||
};
|
||||
// TODO - optimization, if its less than imm12 we can just do an add/sub
|
||||
auto mov_instrs = mov_gpr64_u64_instrs(X17, std::abs(offset));
|
||||
for (const auto& instr : mov_instrs) {
|
||||
instrs.push_back(InstructionARM64(instr));
|
||||
}
|
||||
if (offset < 0) {
|
||||
// we'll subtract instead
|
||||
offset = std::abs(offset);
|
||||
const auto sub_instrs = construct_multiple_imm12_subs(offset, X16);
|
||||
instrs.insert(instrs.end(), sub_instrs.begin(), sub_instrs.end());
|
||||
instrs.push_back(sub_gpr64_gpr64(X16, X17));
|
||||
} else {
|
||||
const auto add_instrs = construct_multiple_imm12_adds(offset, X16);
|
||||
instrs.insert(instrs.end(), add_instrs.begin(), add_instrs.end());
|
||||
instrs.push_back(add_gpr64_gpr64(X16, X17));
|
||||
}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
|
||||
// 32-bit variant
|
||||
@@ -1943,13 +1971,18 @@ InstructionARM64 static_addr(Register dest, s64 offset) {
|
||||
ASSERT(dest.is_gpr(instr_set));
|
||||
ASSERT_MSG(offset != 0,
|
||||
"PC Relative offset isn't 0 at encoding time, actually encode it properly!");
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_lit_gen.html
|
||||
// LDR <Xt>, <label>
|
||||
return InstructionARM64(Base(0b01011000, 8), Imm19(offset / 4), Rt(dest.id()));
|
||||
ASSERT(offset >= -(1 << 20));
|
||||
ASSERT(offset < (1 << 20));
|
||||
u32 immlo = offset & 0x3;
|
||||
u32 immhi = (offset >> 2) & 0x7ffff;
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/adr.html
|
||||
// ADR <Xd>, <label>
|
||||
return InstructionARM64(Base(0b00010000, 8), Rd(dest.id()), Immlo(immlo), Immhi(immhi));
|
||||
}
|
||||
|
||||
InstructionARM64 static_load_f32(Register simd_dest, s64 offset) {
|
||||
ASSERT(simd_dest.is_128bit_simd(instr_set));
|
||||
ASSERT_MSG(std::abs(offset) < 1000000, "LDR offset is greater than 1MB");
|
||||
ASSERT_MSG(offset != 0,
|
||||
"PC Relative offset isn't 0 at encoding time, actually encode it properly!");
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/ldr_lit_fpsimd.html
|
||||
@@ -2042,7 +2075,7 @@ InstructionARM64 add_gpr64_imm(Register reg, int64_t imm) {
|
||||
if (imm < 0) {
|
||||
return sub_gpr64_imm(reg, std::abs(imm));
|
||||
}
|
||||
// Check to see if we can represent this subtraction in a single instruction
|
||||
// Check to see if we can represent this addition in a single instruction
|
||||
// if not, then we need to emit multiple partial instructions
|
||||
const auto [is_single_instr, imm12, needs_shift] = can_encode_single_imm12(imm);
|
||||
if (is_single_instr) {
|
||||
@@ -2051,8 +2084,7 @@ InstructionARM64 add_gpr64_imm(Register reg, int64_t imm) {
|
||||
return InstructionARM64(Base(0b100100010, 9), Sh(needs_shift ? 1 : 0), Imm12(imm12),
|
||||
Rd(reg.id()), Rn(reg.id()));
|
||||
} else {
|
||||
std::vector<InstructionARM64> instrs = construct_multiple_imm12_adds(imm, reg.id());
|
||||
return InstructionARM64(instrs);
|
||||
return InstructionARM64(mov_gpr64_u64(X16, imm), add_gpr64_gpr64(reg, X16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2070,8 +2102,7 @@ InstructionARM64 sub_gpr64_imm(Register reg, int64_t imm) {
|
||||
return InstructionARM64(Base(0b110100010, 9), Sh(needs_shift ? 1 : 0), Imm12(imm12),
|
||||
Rd(reg.id()), Rn(reg.id()));
|
||||
} else {
|
||||
std::vector<InstructionARM64> instrs = construct_multiple_imm12_subs(imm, reg.id());
|
||||
return InstructionARM64(instrs);
|
||||
return InstructionARM64(mov_gpr64_u64(X16, imm), sub_gpr64_gpr64(reg, X16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2152,11 +2183,11 @@ InstructionARM64 or_gpr64_gpr64(Register dst, Register src) {
|
||||
}
|
||||
|
||||
InstructionARM64 and_gpr64_gpr64(Register dst, Register src) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/add_addsub_shift.html
|
||||
// ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/and_log_shift.html
|
||||
// AND <Xd>, <Xn>, <Xm>{, <shift> #<amount>}
|
||||
ASSERT(dst.is_gpr(instr_set));
|
||||
ASSERT(src.is_gpr(instr_set));
|
||||
return InstructionARM64(Base(0b10001011000, 11), Rd(dst.id()), Rn(dst.id()), Rm(src.id()));
|
||||
return InstructionARM64(Base(0b10001010000, 11), Rd(dst.id()), Rn(dst.id()), Rm(src.id()));
|
||||
}
|
||||
|
||||
InstructionARM64 xor_gpr64_gpr64(Register dst, Register src) {
|
||||
@@ -2210,7 +2241,7 @@ InstructionARM64 sar_gpr64_reg(Register reg, Register shift_reg) {
|
||||
InstructionARM64 shl_gpr64_u8(Register reg, uint8_t sa) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/lsl_ubfm.html
|
||||
// LSL <Xd>, <Xn>, #<shift>
|
||||
ASSERT(sa < 63);
|
||||
sa &= 63;
|
||||
ASSERT(reg.is_gpr(instr_set));
|
||||
return InstructionARM64(Base(0b1101001101, 10), Rd(reg.id()), Rn(reg.id()), Immr((64 - sa) & 63),
|
||||
Imms(63 - sa));
|
||||
@@ -2220,7 +2251,7 @@ InstructionARM64 shr_gpr64_u8(Register reg, uint8_t sa) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/lsr_ubfm.html
|
||||
// LSR <Xd>, <Xn>, #<shift>
|
||||
// sf 1 0 1 0 0 1 1 0 N
|
||||
ASSERT(sa < 63);
|
||||
sa &= 63;
|
||||
ASSERT(reg.is_gpr(instr_set));
|
||||
return InstructionARM64(Base(0b1101001101000000111111, 22), Rd(reg.id()), Rn(reg.id()), Immr(sa));
|
||||
}
|
||||
@@ -2228,7 +2259,7 @@ InstructionARM64 shr_gpr64_u8(Register reg, uint8_t sa) {
|
||||
InstructionARM64 sar_gpr64_u8(Register reg, uint8_t sa) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/asr_sbfm.html
|
||||
// ASR <Xd>, <Xn>, #<shift>
|
||||
ASSERT(sa < 63);
|
||||
sa &= 63;
|
||||
ASSERT(reg.is_gpr(instr_set));
|
||||
return InstructionARM64(Base(0b1001001101000000111111, 22), Rd(reg.id()), Rn(reg.id()), Immr(sa));
|
||||
}
|
||||
@@ -2403,7 +2434,7 @@ InstructionARM64 max_f32_f32(Register dst, Register src) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/fmax_float.html
|
||||
// Single-precision (ftype == 00)
|
||||
// FMAX <Sd>, <Sn>, <Sm>
|
||||
return InstructionARM64(Base(0b0001111000100000010010, 22), Rd(dst.id()), Rn(dst.id()),
|
||||
return InstructionARM64(Base(0b0001111000100000010010, 22), Rd(dst.id()), Rn(src.id()),
|
||||
Rm(src.id()));
|
||||
}
|
||||
|
||||
@@ -2411,14 +2442,14 @@ InstructionARM64 int32_to_f32(Register dst, Register src) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/scvtf_float_int.html
|
||||
// 32-bit to single-precision (sf == 0 && ftype == 00)
|
||||
// SCVTF <Sd>, <Wn>
|
||||
return InstructionARM64(Base(0b0001111000100010000000, 22), Rd(dst.id()), Rn(dst.id()));
|
||||
return InstructionARM64(Base(0b0001111000100010000000, 22), Rd(dst.id()), Rn(src.id()));
|
||||
}
|
||||
|
||||
InstructionARM64 f32_to_int32(Register dst, Register src) {
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/fcvtzs_float_int.html
|
||||
// 32-bit to single-precision (sf == 0 && ftype == 00)
|
||||
// FCVTZS <Wd>, <Sn>
|
||||
return InstructionARM64(Base(0b0001111000111000000000, 22), Rd(dst.id()), Rn(dst.id()));
|
||||
return InstructionARM64(Base(0b0001111000111000000000, 22), Rd(dst.id()), Rn(src.id()));
|
||||
}
|
||||
|
||||
InstructionARM64 nop() {
|
||||
@@ -2537,7 +2568,7 @@ InstructionARM64 storevf_gpr64_plus_gpr64(Register value, Register addr1, Regist
|
||||
ASSERT(addr2 != SP);
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_reg_fpsimd.html
|
||||
// STR <Qt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]
|
||||
return InstructionARM64(Base(0b0011110010100000000010, 22), Rt(value.id()), Rn(addr1.id()),
|
||||
return InstructionARM64(Base(0b0011110010100000011010, 22), Rt(value.id()), Rn(addr1.id()),
|
||||
Rm(addr2.id()));
|
||||
}
|
||||
|
||||
@@ -2570,7 +2601,7 @@ InstructionARM64 storevf_gpr64_plus_gpr64_plus_s8(Register value,
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||
// STR <Qt>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b0011110010000000000001, 22), Rt(value.id()), Rn(X16), Imm9s(0)));
|
||||
InstructionARM64(Base(0b0011110010000000000000, 22), Rt(value.id()), Rn(X16), Imm9s(0)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
@@ -2603,7 +2634,7 @@ InstructionARM64 storevf_gpr64_plus_gpr64_plus_s32(Register value,
|
||||
// https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
|
||||
// STR <Qt>, [<Xn|SP>], #<simm>
|
||||
instrs.emplace_back(
|
||||
InstructionARM64(Base(0b0011110010000000000001, 22), Rt(value.id()), Rn(X16), Imm9s(0)));
|
||||
InstructionARM64(Base(0b0011110010000000000000, 22), Rt(value.id()), Rn(X16), Imm9s(0)));
|
||||
return InstructionARM64(instrs);
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -48,7 +48,6 @@ constexpr u32 Base(u32 value, u32 width) {
|
||||
// TODO - consider passing in the instruction name to make debugging easier when an assertion is
|
||||
// hit
|
||||
|
||||
// TODO NOW - fix below
|
||||
constexpr u64 pow2(u64 n) {
|
||||
return 1ull << n;
|
||||
}
|
||||
@@ -59,7 +58,7 @@ constexpr s64 pow2s(u64 n) {
|
||||
|
||||
constexpr Field Hw(u32 x) {
|
||||
ASSERT(x >= 0 && x <= (4 - 1));
|
||||
return Field{(x & 4) << 21};
|
||||
return Field{x << 21};
|
||||
}
|
||||
|
||||
constexpr Field Sh(u32 x) {
|
||||
@@ -93,12 +92,12 @@ constexpr Field Rm(u32 x) {
|
||||
}
|
||||
|
||||
constexpr Field Imm4(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 4) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(4) - 1));
|
||||
return Field{(x & 0b111111) << 11};
|
||||
}
|
||||
|
||||
constexpr Field Imm6(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 6)));
|
||||
ASSERT(x >= 0 && x <= (pow2(6) - 1));
|
||||
return Field{(x & 0b111111) << 10};
|
||||
}
|
||||
|
||||
@@ -114,7 +113,7 @@ constexpr Field Imm12(u32 x) {
|
||||
|
||||
constexpr Field Imm16(u32 x) {
|
||||
ASSERT(x >= 0 && x <= (pow2(16) - 1));
|
||||
return Field{static_cast<u32>((x & (pow2(16) - 1)) << 16)};
|
||||
return Field{static_cast<u32>((x & (pow2(16) - 1)) << 5)};
|
||||
}
|
||||
|
||||
constexpr Field Imm26(u32 x) {
|
||||
@@ -123,7 +122,7 @@ constexpr Field Imm26(u32 x) {
|
||||
}
|
||||
|
||||
constexpr Field Imm19(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 19) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(19) - 1));
|
||||
return Field{(static_cast<uint32_t>(x) & 0b1111111111111111111) << 5};
|
||||
}
|
||||
|
||||
@@ -138,27 +137,27 @@ constexpr Field Immhi(u32 x) {
|
||||
}
|
||||
|
||||
constexpr Field Imms(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 6) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(6) - 1));
|
||||
return Field{(static_cast<uint32_t>(x) & 0b111111) << 10};
|
||||
}
|
||||
|
||||
constexpr Field Immr(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 6) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(6) - 1));
|
||||
return Field{(static_cast<uint32_t>(x) & 0b111111) << 16};
|
||||
}
|
||||
|
||||
constexpr Field Immh(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 4) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(4) - 1));
|
||||
return Field{(static_cast<uint32_t>(x) & 0b111111) << 19};
|
||||
}
|
||||
|
||||
constexpr Field Immb(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 3) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(3) - 1));
|
||||
return Field{(static_cast<uint32_t>(x) & 0b111111) << 16};
|
||||
}
|
||||
|
||||
constexpr Field Cond(u32 x) {
|
||||
ASSERT(x >= 0 && x <= ((2 ^ 4) - 1));
|
||||
ASSERT(x >= 0 && x <= (pow2(4) - 1));
|
||||
return Field{(static_cast<uint32_t>(x) & 0b1111) << 0};
|
||||
}
|
||||
} // namespace ARM64
|
||||
@@ -173,9 +172,9 @@ struct InstructionARM64 : InstructionImpl<InstructionARM64> {
|
||||
//
|
||||
// To do so, the instruction can optionally include multiple encodings
|
||||
// all of which are emitted at once.
|
||||
static constexpr int kMaxInstrs = 64;
|
||||
static constexpr int max_instrs = 64;
|
||||
|
||||
u32 encodings[kMaxInstrs]{};
|
||||
u32 encodings[max_instrs]{};
|
||||
u8 count = 0;
|
||||
|
||||
InstructionARM64() = delete;
|
||||
@@ -195,6 +194,7 @@ struct InstructionARM64 : InstructionImpl<InstructionARM64> {
|
||||
{
|
||||
u8 idx = 0;
|
||||
auto append = [&](const InstructionARM64& i) {
|
||||
ASSERT_MSG(idx + i.count <= max_instrs, "Too many instructions in a multi-ARM64-instruction");
|
||||
for (uint8_t j = 0; j < i.count; ++j) {
|
||||
encodings[idx++] = i.encodings[j];
|
||||
}
|
||||
@@ -206,6 +206,7 @@ struct InstructionARM64 : InstructionImpl<InstructionARM64> {
|
||||
InstructionARM64(std::span<const InstructionARM64> instrs) {
|
||||
u8 idx = 0;
|
||||
for (const auto& i : instrs) {
|
||||
ASSERT_MSG(idx + i.count <= max_instrs, "Too many instructions in a multi-ARM64-instruction");
|
||||
for (uint8_t j = 0; j < i.count; ++j) {
|
||||
encodings[idx++] = i.encodings[j];
|
||||
}
|
||||
@@ -213,7 +214,7 @@ struct InstructionARM64 : InstructionImpl<InstructionARM64> {
|
||||
count = idx;
|
||||
}
|
||||
|
||||
uint8_t emit(uint8_t* buffer) const {
|
||||
uint32_t emit(uint8_t* buffer) const {
|
||||
if (count == 1 && encodings[0] == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1153,7 +1154,7 @@ struct InstructionX86 : InstructionImpl<InstructionX86> {
|
||||
return offset;
|
||||
}
|
||||
|
||||
uint8_t emit(uint8_t* buffer) const {
|
||||
uint32_t emit(uint8_t* buffer) const {
|
||||
if (m_flags & kIsNull)
|
||||
return 0;
|
||||
uint8_t count = 0;
|
||||
@@ -1253,7 +1254,7 @@ class Instruction {
|
||||
template <typename T>
|
||||
Instruction(T v) : instr(std::move(v)) {}
|
||||
|
||||
u8 emit(u8* buffer) const {
|
||||
u32 emit(u8* buffer) const {
|
||||
return std::visit([&](auto const& i) { return i.emit(buffer); }, instr);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,8 +84,8 @@ enum ARM64_REG : s8 {
|
||||
// temp, not-saved - Conventionally used for linker/veneer/temporary values (we will reserve this
|
||||
// one atleast)
|
||||
X16,
|
||||
// temp, not-saved - Conventionally used for linker/veneer/temporary values
|
||||
X17,
|
||||
// TODO - ARM, save
|
||||
X17, // TODO ARM - reserve
|
||||
X18, // temp, not-saved
|
||||
|
||||
X19, // saved TODO purpose?, R12
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# Directory of this script
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
"$DIR/build/goalc-test" --gtest_color=yes "$@" --gtest_filter="-*MANUAL_TEST*"
|
||||
"$DIR/build/goalc-test" --gtest_color=yes "$@" --gtest_filter="-*MANUAL_TEST*" # --gtest_filter="*ARM64Emitter*:*NEONEmitter*" -v
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ add_executable(goalc-test
|
||||
${GOALC_TEST_CASES}
|
||||
)
|
||||
|
||||
target_link_libraries(goalc-test common runtime compiler gtest decomp Zydis libzstd_static tree-sitter)
|
||||
target_link_libraries(goalc-test common runtime compiler gtest decomp Zydis capstone libzstd_static tree-sitter)
|
||||
|
||||
add_executable(test_image_resize ${CMAKE_CURRENT_LIST_DIR}/common/test_image_resize.cpp)
|
||||
target_link_libraries(test_image_resize common)
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
#include "emitter_util.h"
|
||||
|
||||
template <typename T>
|
||||
bool execute_ret_equals(emitter::CodeTester& tester, u64 val, T expected, T& actual) {
|
||||
if (tester.generator().instr_set() == emitter::InstructionSet::ARM64) {
|
||||
#ifdef __aarch64__
|
||||
actual = tester.execute_ret<T>(val, 0, 0, 0);
|
||||
return actual == expected;
|
||||
#endif
|
||||
} else if (tester.generator().instr_set() == emitter::InstructionSet::X86) {
|
||||
#ifndef __aarch64__
|
||||
actual = tester.execute_ret<T>(val, 0, 0, 0);
|
||||
return actual == expected;
|
||||
#endif
|
||||
}
|
||||
return true; // not testing this architecture
|
||||
}
|
||||
|
||||
bool execute_equals(emitter::CodeTester& tester, u64 expected, u64& actual) {
|
||||
if (tester.generator().instr_set() == emitter::InstructionSet::ARM64) {
|
||||
#ifdef __aarch64__
|
||||
actual = tester.execute();
|
||||
return actual == expected;
|
||||
#endif
|
||||
} else if (tester.generator().instr_set() == emitter::InstructionSet::X86) {
|
||||
#ifndef __aarch64__
|
||||
actual = tester.execute();
|
||||
return actual == expected;
|
||||
#endif
|
||||
}
|
||||
return true; // not testing this architecture
|
||||
}
|
||||
|
||||
bool execute_equals_4arg(emitter::CodeTester& tester,
|
||||
u64 in0,
|
||||
u64 in1,
|
||||
u64 in2,
|
||||
u64 in3,
|
||||
u64 expected,
|
||||
u64& actual) {
|
||||
if (tester.generator().instr_set() == emitter::InstructionSet::ARM64) {
|
||||
#ifdef __aarch64__
|
||||
actual = tester.execute(in0, in1, in2, in3);
|
||||
return actual == expected;
|
||||
#endif
|
||||
} else if (tester.generator().instr_set() == emitter::InstructionSet::X86) {
|
||||
#ifndef __aarch64__
|
||||
actual = tester.execute(in0, in1, in2, in3);
|
||||
return actual == expected;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool execute_equals_4args_no_cmp(emitter::CodeTester& tester, u64 in0, u64 in1, u64 in2, u64 in3) {
|
||||
if (tester.generator().instr_set() == emitter::InstructionSet::ARM64) {
|
||||
#ifdef __aarch64__
|
||||
tester.execute(in0, in1, in2, in3);
|
||||
return true;
|
||||
#endif
|
||||
} else if (tester.generator().instr_set() == emitter::InstructionSet::X86) {
|
||||
#ifndef __aarch64__
|
||||
tester.execute(in0, in1, in2, in3);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return true; // not testing this architecture
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool execute_ret_equals_4arg(emitter::CodeTester& tester,
|
||||
u64 in0,
|
||||
u64 in1,
|
||||
u64 in2,
|
||||
u64 in3,
|
||||
T expected,
|
||||
T& actual) {
|
||||
if (tester.generator().instr_set() == emitter::InstructionSet::ARM64) {
|
||||
#ifdef __aarch64__
|
||||
actual = tester.execute_ret<T>(in0, in1, in2, in3);
|
||||
return actual == expected;
|
||||
#endif
|
||||
} else if (tester.generator().instr_set() == emitter::InstructionSet::X86) {
|
||||
#ifndef __aarch64__
|
||||
actual = tester.execute_ret<T>(in0, in1, in2, in3);
|
||||
return actual == expected;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool execute_ret_float_equals_4arg(emitter::CodeTester& tester,
|
||||
u64 in0,
|
||||
u64 in1,
|
||||
u64 in2,
|
||||
u64 in3,
|
||||
T expected,
|
||||
T& actual) {
|
||||
if (tester.generator().instr_set() == emitter::InstructionSet::ARM64) {
|
||||
#ifdef __aarch64__
|
||||
actual = tester.execute_ret<float>(in0, in1, in2, in3);
|
||||
return actual == expected;
|
||||
#endif
|
||||
} else if (tester.generator().instr_set() == emitter::InstructionSet::X86) {
|
||||
#ifndef __aarch64__
|
||||
actual = tester.execute_ret<float>(in0, in1, in2, in3);
|
||||
return actual == expected;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#define EXPECT_EXECUTE_RET_EQ(tester, val, expected) \
|
||||
EXPECT_EXECUTE_RET_EQ_IMPL(tester, val, expected, "")
|
||||
|
||||
#define EXPECT_EXECUTE_RET_EQ_MSG(tester, val, expected, msg) \
|
||||
EXPECT_EXECUTE_RET_EQ_IMPL(tester, val, expected, msg)
|
||||
|
||||
#define EXPECT_EXECUTE_RET_EQ_IMPL(tester, val, expected, msg) \
|
||||
do { \
|
||||
decltype(expected) actual{}; \
|
||||
if (!execute_ret_equals(tester, val, expected, actual)) { \
|
||||
FAIL() \
|
||||
<< "\033[1;31mExecute mismatch\033[0m" \
|
||||
<< "\n \033[33minput: \033[0m" << val \
|
||||
<< "\n \033[32mexpected: \033[0m" << expected \
|
||||
<< "\n \033[31mactual: \033[0m" << actual \
|
||||
<< "\n \033[36mcontext: \033[0m" << msg \
|
||||
<< "\n\033[1;36mGenerated code:\033[0m\n" \
|
||||
<< tester.dump_to_asm_string() \
|
||||
<< "\n\033[1;36mInstruction encoding:\033[0m\n" \
|
||||
<< tester.dump_to_hex_string(true) << "\n"; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_EXECUTE_EQ(tester, expected) \
|
||||
EXPECT_EXECUTE_EQ_IMPL(tester, expected, "")
|
||||
|
||||
#define EXPECT_EXECUTE_EQ_MSG(tester, expected, msg) \
|
||||
EXPECT_EXECUTE_EQ_IMPL(tester, expected, msg)
|
||||
|
||||
#define EXPECT_EXECUTE_EQ_IMPL(tester, expected, msg) \
|
||||
do { \
|
||||
decltype(expected) actual{}; \
|
||||
if (!execute_equals(tester, expected, actual)) { \
|
||||
FAIL() \
|
||||
<< "\033[1;31mExecute mismatch\033[0m" \
|
||||
<< "\n \033[32mexpected: \033[0m" << expected \
|
||||
<< "\n \033[31mactual: \033[0m" << actual \
|
||||
<< "\n \033[36mcontext: \033[0m" << msg \
|
||||
<< "\n\033[1;36mGenerated code:\033[0m\n" \
|
||||
<< tester.dump_to_asm_string() \
|
||||
<< "\n\033[1;36mInstruction encoding:\033[0m\n" \
|
||||
<< tester.dump_to_hex_string(true) << "\n"; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_EXECUTE_4ARG_NO_CMP(tester, val1, val2, val3, val4) \
|
||||
EXPECT_EXECUTE_4ARG_NO_CMP_IMPL(tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, "")
|
||||
|
||||
#define EXPECT_EXECUTE_4ARG_NO_CMP_MSG(tester, val1, val2, val3, val4, msg) \
|
||||
EXPECT_EXECUTE_4ARG_NO_CMP_IMPL(tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, msg)
|
||||
|
||||
#define EXPECT_EXECUTE_4ARG_NO_CMP_IMPL(tester, val1, val2, val3, val4, msg) \
|
||||
do { \
|
||||
if (!execute_equals_4args_no_cmp(tester, val1, val2, val3, val4)) { \
|
||||
FAIL() \
|
||||
<< "\033[1;31mExecute mismatch\033[0m" \
|
||||
<< "\n \033[33minput: \033[0m" << val1 << ", " << val2 << ", " << val3 << ", " << val4 \
|
||||
<< "\n \033[36mcontext: \033[0m" << msg \
|
||||
<< "\n\033[1;36mGenerated code:\033[0m\n" \
|
||||
<< tester.dump_to_asm_string() \
|
||||
<< "\n\033[1;36mInstruction encoding:\033[0m\n" \
|
||||
<< tester.dump_to_hex_string(true) << "\n"; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_EXECUTE_4ARG_EQ(tester, val1, val2, val3, val4,expected) \
|
||||
EXPECT_EXECUTE_4ARG_EQ_IMPL(tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, (u64)expected, "")
|
||||
|
||||
#define EXPECT_EXECUTE_4ARG_EQ_MSG(tester, val1, val2, val3, val4,expected, msg) \
|
||||
EXPECT_EXECUTE_4ARG_EQ_IMPL(tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, (u64)expected, msg)
|
||||
|
||||
#define EXPECT_EXECUTE_4ARG_EQ_IMPL(tester, val1, val2, val3, val4, expected, msg) \
|
||||
do { \
|
||||
decltype(expected) actual{}; \
|
||||
if (!execute_equals_4arg(tester, val1, val2, val3, val4, expected, actual)) { \
|
||||
FAIL() \
|
||||
<< "\033[1;31mExecute mismatch\033[0m" \
|
||||
<< "\n \033[33minput: \033[0m" << val1 << ", " << val2 << ", " << val3 << ", " << val4 \
|
||||
<< "\n \033[32mexpected: \033[0m" << expected \
|
||||
<< "\n \033[31mactual: \033[0m" << actual \
|
||||
<< "\n \033[36mcontext: \033[0m" << msg \
|
||||
<< "\n\033[1;36mGenerated code:\033[0m\n" \
|
||||
<< tester.dump_to_asm_string() \
|
||||
<< "\n\033[1;36mInstruction encoding:\033[0m\n" \
|
||||
<< tester.dump_to_hex_string(true) << "\n"; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_EXECUTE_RET_4ARG_EQ(tester, val1, val2, val3, val4, expected) \
|
||||
EXPECT_EXECUTE_RET_4ARG_EQ_IMPL( \
|
||||
tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, expected, "")
|
||||
|
||||
#define EXPECT_EXECUTE_RET_4ARG_EQ_MSG(tester, val1, val2, val3, val4, expected, msg) \
|
||||
EXPECT_EXECUTE_RET_4ARG_EQ_IMPL( \
|
||||
tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, expected, msg)
|
||||
|
||||
#define EXPECT_EXECUTE_RET_4ARG_EQ_IMPL(tester, val1, val2, val3, val4, expected, msg) \
|
||||
do { \
|
||||
decltype(expected) actual{}; \
|
||||
if (!execute_ret_equals_4arg( \
|
||||
tester, val1, val2, val3, val4, expected, actual)) { \
|
||||
FAIL() \
|
||||
<< "\033[1;31mExecute mismatch\033[0m" \
|
||||
<< "\n \033[33minput: \033[0m" << val1 << ", " << val2 << ", " \
|
||||
<< val3 << ", " << val4 \
|
||||
<< "\n \033[32mexpected: \033[0m" << expected \
|
||||
<< "\n \033[31mactual: \033[0m" << actual \
|
||||
<< "\n \033[36mcontext: \033[0m" << msg \
|
||||
<< "\n\033[1;36mGenerated code:\033[0m\n" \
|
||||
<< tester.dump_to_asm_string() \
|
||||
<< "\n\033[1;36mInstruction encoding:\033[0m\n" \
|
||||
<< tester.dump_to_hex_string(true) << "\n"; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT_EXECUTE_RET_4ARG_FLOAT_EQ(tester, val1, val2, val3, val4, expected) \
|
||||
EXPECT_EXECUTE_RET_4ARG_FLOAT_EQ_IMPL( \
|
||||
tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, expected, "")
|
||||
|
||||
#define EXPECT_EXECUTE_RET_4ARG_FLOAT_EQ_MSG( \
|
||||
tester, val1, val2, val3, val4, expected, msg) \
|
||||
EXPECT_EXECUTE_RET_4ARG_FLOAT_EQ_IMPL( \
|
||||
tester, (u64)val1, (u64)val2, (u64)val3, (u64)val4, expected, msg)
|
||||
|
||||
#define EXPECT_EXECUTE_RET_4ARG_FLOAT_EQ_IMPL( \
|
||||
tester, val1, val2, val3, val4, expected, msg) \
|
||||
do { \
|
||||
float actual{}; \
|
||||
if (!execute_ret_float_equals_4arg( \
|
||||
tester, val1, val2, val3, val4, expected, actual)) { \
|
||||
FAIL() \
|
||||
<< "\033[1;31mExecute mismatch\033[0m" \
|
||||
<< "\n \033[33minput: \033[0m" << val1 << ", " << val2 << ", " \
|
||||
<< val3 << ", " << val4 \
|
||||
<< "\n \033[32mexpected: \033[0m" << expected \
|
||||
<< "\n \033[31mactual: \033[0m" << actual \
|
||||
<< "\n \033[36mcontext: \033[0m" << msg \
|
||||
<< "\n\033[1;36mGenerated code:\033[0m\n" \
|
||||
<< tester.dump_to_asm_string() \
|
||||
<< "\n\033[1;36mInstruction encoding:\033[0m\n" \
|
||||
<< tester.dump_to_hex_string(true) << "\n"; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define EXPECT_EXECUTE_IF_NATIVE_ARM64(body) body
|
||||
#else
|
||||
#define EXPECT_EXECUTE_IF_NATIVE_ARM64(body)
|
||||
#endif
|
||||
|
||||
#ifndef __aarch64__
|
||||
#define EXPECT_EXECUTE_IF_NATIVE_X86(body) body
|
||||
#else
|
||||
#define EXPECT_EXECUTE_IF_NATIVE_X86(body)
|
||||
#endif
|
||||
|
||||
#define EXPECT_EXECUTE_IF_NATIVE(tester, body) \
|
||||
do { \
|
||||
if ((tester).generator().instr_set() == \
|
||||
emitter::InstructionSet::ARM64) { \
|
||||
EXPECT_EXECUTE_IF_NATIVE_ARM64(body) \
|
||||
} else if ((tester).generator().instr_set() == \
|
||||
emitter::InstructionSet::X86) { \
|
||||
EXPECT_EXECUTE_IF_NATIVE_X86(body) \
|
||||
} \
|
||||
} while (false)
|
||||
// clang-format on
|
||||
@@ -225,18 +225,14 @@ TEST(CodeTester, execute_push_pop_simd_x86) {
|
||||
tester.emit_pop_all_simd();
|
||||
tester.emit_return();
|
||||
EXPECT_EQ(
|
||||
tester.dump_to_hex_string(),
|
||||
"48 83 ec 08 48 83 ec 10 66 0f 7f 04 24 48 83 ec 10 66 0f 7f 0c 24 48 83 ec 10 66 0f 7f 14 "
|
||||
"24 48 83 ec 10 66 0f 7f 1c 24 48 83 ec 10 66 0f 7f 24 24 48 83 ec 10 66 0f 7f 2c 24 48 83 "
|
||||
"ec 10 66 0f 7f 34 24 48 83 ec 10 66 0f 7f 3c 24 48 83 ec 10 66 44 0f 7f 04 24 48 83 ec 10 "
|
||||
"66 44 0f 7f 0c 24 48 83 ec 10 66 44 0f 7f 14 24 48 83 ec 10 66 44 0f 7f 1c 24 48 83 ec 10 "
|
||||
"66 44 0f 7f 24 24 48 83 ec 10 66 44 0f 7f 2c 24 48 83 ec 10 66 44 0f 7f 34 24 48 83 ec 10 "
|
||||
"66 44 0f 7f 3c 24 66 0f 6f 04 24 48 83 c4 10 66 0f 6f 0c 24 48 83 c4 10 66 0f 6f 14 24 48 "
|
||||
"83 c4 10 66 0f 6f 1c 24 48 83 c4 10 66 0f 6f 24 24 48 83 c4 10 66 0f 6f 2c 24 48 83 c4 10 "
|
||||
"66 0f 6f 34 24 48 83 c4 10 66 0f 6f 3c 24 48 83 c4 10 66 44 0f 6f 04 24 48 83 c4 10 66 44 "
|
||||
"0f 6f 0c 24 48 83 c4 10 66 44 0f 6f 14 24 48 83 c4 10 66 44 0f 6f 1c 24 48 83 c4 10 66 44 "
|
||||
"0f 6f 24 24 48 83 c4 10 66 44 0f 6f 2c 24 48 83 c4 10 66 44 0f 6f 34 24 48 83 c4 10 66 44 "
|
||||
"0f 6f 3c 24 48 83 c4 10 48 83 c4 08 c3");
|
||||
tester.dump_to_hex_string(true),
|
||||
"4883EC084883EC10660F7F04244883EC10660F7F0C244883EC10660F7F14244883EC10660F7F1C244883EC10660F"
|
||||
"7F24244883EC10660F7F2C244883EC10660F7F34244883EC10660F7F3C244883EC1066440F7F04244883EC106644"
|
||||
"0F7F0C244883EC1066440F7F14244883EC1066440F7F1C244883EC1066440F7F24244883EC1066440F7F2C244883"
|
||||
"EC1066440F7F34244883EC1066440F7F3C2466440F6F3C244883C41066440F6F34244883C41066440F6F2C244883"
|
||||
"C41066440F6F24244883C41066440F6F1C244883C41066440F6F14244883C41066440F6F0C244883C41066440F6F"
|
||||
"04244883C410660F6F3C244883C410660F6F34244883C410660F6F2C244883C410660F6F24244883C410660F6F1C"
|
||||
"244883C410660F6F14244883C410660F6F0C244883C410660F6F04244883C4104883C408C3");
|
||||
execute_tester(tester);
|
||||
}
|
||||
|
||||
@@ -247,16 +243,13 @@ TEST(CodeTester, execute_push_pop_simd_arm64) {
|
||||
tester.emit_pop_all_simd();
|
||||
tester.emit_return();
|
||||
EXPECT_EQ(
|
||||
tester.dump_to_hex_string(),
|
||||
"ff 43 00 d1 e0 03 80 3d ff 43 00 d1 e1 03 80 3d ff 43 00 d1 e2 03 80 3d ff 43 00 d1 e3 03 "
|
||||
"80 3d ff 43 00 d1 e4 03 80 3d ff 43 00 d1 e5 03 80 3d ff 43 00 d1 e6 03 80 3d ff 43 00 d1 "
|
||||
"e7 03 80 3d ff 43 00 d1 e8 03 80 3d ff 43 00 d1 e9 03 80 3d ff 43 00 d1 ea 03 80 3d ff 43 "
|
||||
"00 d1 eb 03 80 3d ff 43 00 d1 ec 03 80 3d ff 43 00 d1 ed 03 80 3d ff 43 00 d1 ee 03 80 3d "
|
||||
"ff 43 00 d1 ef 03 80 3d e0 03 c0 3d ff 43 00 91 e1 03 c0 3d ff 43 00 91 e2 03 c0 3d ff 43 "
|
||||
"00 91 e3 03 c0 3d ff 43 00 91 e4 03 c0 3d ff 43 00 91 e5 03 c0 3d ff 43 00 91 e6 03 c0 3d "
|
||||
"ff 43 00 91 e7 03 c0 3d ff 43 00 91 e8 03 c0 3d ff 43 00 91 e9 03 c0 3d ff 43 00 91 ea 03 "
|
||||
"c0 3d ff 43 00 91 eb 03 c0 3d ff 43 00 91 ec 03 c0 3d ff 43 00 91 ed 03 c0 3d ff 43 00 91 "
|
||||
"ee 03 c0 3d ff 43 00 91 ef 03 c0 3d ff 43 00 91 c0 03 5f d6");
|
||||
tester.dump_to_hex_string(true),
|
||||
"FF4300D1E003803DFF4300D1E103803DFF4300D1E203803DFF4300D1E303803DFF4300D1E403803DFF4300D1E503"
|
||||
"803DFF4300D1E603803DFF4300D1E703803DFF4300D1E803803DFF4300D1E903803DFF4300D1EA03803DFF4300D1"
|
||||
"EB03803DFF4300D1EC03803DFF4300D1ED03803DFF4300D1EE03803DFF4300D1EF03803DEF03C03DFF430091EE03"
|
||||
"C03DFF430091ED03C03DFF430091EC03C03DFF430091EB03C03DFF430091EA03C03DFF430091E903C03DFF430091"
|
||||
"E803C03DFF430091E703C03DFF430091E603C03DFF430091E503C03DFF430091E403C03DFF430091E303C03DFF43"
|
||||
"0091E203C03DFF430091E103C03DFF430091E003C03DFF430091C0035FD6");
|
||||
execute_tester(tester);
|
||||
}
|
||||
|
||||
@@ -270,20 +263,16 @@ TEST(CodeTester, execute_push_pop_all_the_things_x86) {
|
||||
tester.emit_pop_all_gprs();
|
||||
tester.emit_pop_all_simd();
|
||||
tester.emit_return();
|
||||
EXPECT_EQ(tester.dump_to_hex_string(),
|
||||
"48 83 ec 08 48 83 ec 10 66 0f 7f 04 24 48 83 ec 10 66 0f 7f 0c 24 48 83 ec 10 66 0f "
|
||||
"7f 14 24 48 83 ec 10 66 0f 7f 1c 24 48 83 ec 10 66 0f 7f 24 24 48 83 ec 10 66 0f 7f "
|
||||
"2c 24 48 83 ec 10 66 0f 7f 34 24 48 83 ec 10 66 0f 7f 3c 24 48 83 ec 10 66 44 0f 7f "
|
||||
"04 24 48 83 ec 10 66 44 0f 7f 0c 24 48 83 ec 10 66 44 0f 7f 14 24 48 83 ec 10 66 44 "
|
||||
"0f 7f 1c 24 48 83 ec 10 66 44 0f 7f 24 24 48 83 ec 10 66 44 0f 7f 2c 24 48 83 ec 10 "
|
||||
"66 44 0f 7f 34 24 48 83 ec 10 66 44 0f 7f 3c 24 50 51 52 53 54 55 56 57 41 50 41 51 "
|
||||
"41 52 41 53 41 54 41 55 41 56 41 57 41 5f 41 5e 41 5d 41 5c 41 5b 41 5a 41 59 41 58 "
|
||||
"5f 5e 5d 5c 5b 5a 59 58 66 0f 6f 04 24 48 83 c4 10 66 0f 6f 0c 24 48 83 c4 10 66 0f "
|
||||
"6f 14 24 48 83 c4 10 66 0f 6f 1c 24 48 83 c4 10 66 0f 6f 24 24 48 83 c4 10 66 0f 6f "
|
||||
"2c 24 48 83 c4 10 66 0f 6f 34 24 48 83 c4 10 66 0f 6f 3c 24 48 83 c4 10 66 44 0f 6f "
|
||||
"04 24 48 83 c4 10 66 44 0f 6f 0c 24 48 83 c4 10 66 44 0f 6f 14 24 48 83 c4 10 66 44 "
|
||||
"0f 6f 1c 24 48 83 c4 10 66 44 0f 6f 24 24 48 83 c4 10 66 44 0f 6f 2c 24 48 83 c4 10 "
|
||||
"66 44 0f 6f 34 24 48 83 c4 10 66 44 0f 6f 3c 24 48 83 c4 10 48 83 c4 08 c3");
|
||||
EXPECT_EQ(
|
||||
tester.dump_to_hex_string(true),
|
||||
"4883EC084883EC10660F7F04244883EC10660F7F0C244883EC10660F7F14244883EC10660F7F1C244883EC10660F"
|
||||
"7F24244883EC10660F7F2C244883EC10660F7F34244883EC10660F7F3C244883EC1066440F7F04244883EC106644"
|
||||
"0F7F0C244883EC1066440F7F14244883EC1066440F7F1C244883EC1066440F7F24244883EC1066440F7F2C244883"
|
||||
"EC1066440F7F34244883EC1066440F7F3C24505152535455565741504151415241534154415541564157415F415E"
|
||||
"415D415C415B415A415941585F5E5D5C5B5A595866440F6F3C244883C41066440F6F34244883C41066440F6F2C24"
|
||||
"4883C41066440F6F24244883C41066440F6F1C244883C41066440F6F14244883C41066440F6F0C244883C4106644"
|
||||
"0F6F04244883C410660F6F3C244883C410660F6F34244883C410660F6F2C244883C410660F6F24244883C410660F"
|
||||
"6F1C244883C410660F6F14244883C410660F6F0C244883C410660F6F04244883C4104883C408C3");
|
||||
execute_tester(tester);
|
||||
}
|
||||
|
||||
@@ -297,25 +286,19 @@ TEST(CodeTester, execute_push_pop_all_the_things_arm64) {
|
||||
tester.emit_pop_all_gprs();
|
||||
tester.emit_pop_all_simd();
|
||||
tester.emit_return();
|
||||
EXPECT_EQ(
|
||||
tester.dump_to_hex_string(),
|
||||
"ff 43 00 d1 e0 03 80 3d ff 43 00 d1 e1 03 80 3d ff 43 00 d1 e2 03 80 3d ff 43 00 d1 e3 03 "
|
||||
"80 3d ff 43 00 d1 e4 03 80 3d ff 43 00 d1 e5 03 80 3d ff 43 00 d1 e6 03 80 3d ff 43 00 d1 "
|
||||
"e7 03 80 3d ff 43 00 d1 e8 03 80 3d ff 43 00 d1 e9 03 80 3d ff 43 00 d1 ea 03 80 3d ff 43 "
|
||||
"00 d1 eb 03 80 3d ff 43 00 d1 ec 03 80 3d ff 43 00 d1 ed 03 80 3d ff 43 00 d1 ee 03 80 3d "
|
||||
"ff 43 00 d1 ef 03 80 3d e0 0f 1f f8 e1 0f 1f f8 e2 0f 1f f8 e3 0f 1f f8 e4 0f 1f f8 e5 0f "
|
||||
"1f f8 e6 0f 1f f8 e7 0f 1f f8 e8 0f 1f f8 e9 0f 1f f8 ea 0f 1f f8 eb 0f 1f f8 ec 0f 1f f8 "
|
||||
"ed 0f 1f f8 ee 0f 1f f8 ef 0f 1f f8 f0 0f 1f f8 f1 0f 1f f8 f2 0f 1f f8 f3 0f 1f f8 f4 0f "
|
||||
"1f f8 f5 0f 1f f8 f6 0f 1f f8 f7 0f 1f f8 f8 0f 1f f8 f9 0f 1f f8 fa 0f 1f f8 fb 0f 1f f8 "
|
||||
"fc 0f 1f f8 fd 0f 1f f8 fe 0f 1f f8 fe 07 41 f8 fd 07 41 f8 fc 07 41 f8 fb 07 41 f8 fa 07 "
|
||||
"41 f8 f9 07 41 f8 f8 07 41 f8 f7 07 41 f8 f6 07 41 f8 f5 07 41 f8 f4 07 41 f8 f3 07 41 f8 "
|
||||
"f2 07 41 f8 f1 07 41 f8 f0 07 41 f8 ef 07 41 f8 ee 07 41 f8 ed 07 41 f8 ec 07 41 f8 eb 07 "
|
||||
"41 f8 ea 07 41 f8 e9 07 41 f8 e8 07 41 f8 e7 07 41 f8 e6 07 41 f8 e5 07 41 f8 e4 07 41 f8 "
|
||||
"e3 07 41 f8 e2 07 41 f8 e1 07 41 f8 e0 07 41 f8 e0 03 c0 3d ff 43 00 91 e1 03 c0 3d ff 43 "
|
||||
"00 91 e2 03 c0 3d ff 43 00 91 e3 03 c0 3d ff 43 00 91 e4 03 c0 3d ff 43 00 91 e5 03 c0 3d "
|
||||
"ff 43 00 91 e6 03 c0 3d ff 43 00 91 e7 03 c0 3d ff 43 00 91 e8 03 c0 3d ff 43 00 91 e9 03 "
|
||||
"c0 3d ff 43 00 91 ea 03 c0 3d ff 43 00 91 eb 03 c0 3d ff 43 00 91 ec 03 c0 3d ff 43 00 91 "
|
||||
"ed 03 c0 3d ff 43 00 91 ee 03 c0 3d ff 43 00 91 ef 03 c0 3d ff 43 00 91 c0 03 5f d6");
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true),
|
||||
"FF4300D1E003803DFF4300D1E103803DFF4300D1E203803DFF4300D1E303803DFF4300D1E403803DFF4300"
|
||||
"D1E503803DFF4300D1E603803DFF4300D1E703803DFF4300D1E803803DFF4300D1E903803DFF4300D1EA03"
|
||||
"803DFF4300D1EB03803DFF4300D1EC03803DFF4300D1ED03803DFF4300D1EE03803DFF4300D1EF03803DE0"
|
||||
"0F1FF8E10F1FF8E20F1FF8E30F1FF8E40F1FF8E50F1FF8E60F1FF8E70F1FF8E80F1FF8E90F1FF8EA0F1FF8"
|
||||
"EB0F1FF8EC0F1FF8ED0F1FF8EE0F1FF8EF0F1FF8F00F1FF8F10F1FF8F20F1FF8F30F1FF8F40F1FF8F50F1F"
|
||||
"F8F60F1FF8F70F1FF8F80F1FF8F90F1FF8FA0F1FF8FB0F1FF8FC0F1FF8FD0F1FF8FE0F1FF8FE0741F8FD07"
|
||||
"41F8FC0741F8FB0741F8FA0741F8F90741F8F80741F8F70741F8F60741F8F50741F8F40741F8F30741F8F2"
|
||||
"0741F8F10741F8F00741F8EF0741F8EE0741F8ED0741F8EC0741F8EB0741F8EA0741F8E90741F8E80741F8"
|
||||
"E70741F8E60741F8E50741F8E40741F8E30741F8E20741F8E10741F8E00741F8EF03C03DFF430091EE03C0"
|
||||
"3DFF430091ED03C03DFF430091EC03C03DFF430091EB03C03DFF430091EA03C03DFF430091E903C03DFF43"
|
||||
"0091E803C03DFF430091E703C03DFF430091E603C03DFF430091E503C03DFF430091E403C03DFF430091E3"
|
||||
"03C03DFF430091E203C03DFF430091E103C03DFF430091E003C03DFF430091C0035FD6");
|
||||
execute_tester(tester);
|
||||
}
|
||||
|
||||
|
||||
+3173
-10
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,6 @@
|
||||
|
||||
using namespace emitter;
|
||||
|
||||
// TODO - do an ARM64 version of this
|
||||
|
||||
TEST(EmitterAVX, VF_NOP) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(1024);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "goalc/emitter/CodeTester.h"
|
||||
#include "goalc/emitter/IGen.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace emitter;
|
||||
|
||||
namespace {
|
||||
const auto instr_set = InstructionSet::ARM64;
|
||||
|
||||
CodeTester create_tester(int code_capacity = 1024) {
|
||||
CodeTester tester(instr_set);
|
||||
tester.init_code_buffer(code_capacity);
|
||||
return tester;
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
TEST(NEONEmitter, VF_NOP) {
|
||||
CodeTester tester = create_tester();
|
||||
tester.emit(IGen::nop_vf(tester.generator()));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "1F2003D5");
|
||||
}
|
||||
|
||||
TEST(NEONEmitter, WAIT_VF) {
|
||||
CodeTester tester = create_tester();
|
||||
tester.emit(IGen::wait_vf(tester.generator()));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "1F2003D5");
|
||||
}
|
||||
@@ -473,7 +473,7 @@ TEST(X86EmitterIntegerMath, sar_gpr64_cl) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(X86EmitterIntegerMath, shl_gpr64_u8_new) {
|
||||
TEST(X86EmitterIntegerMath, shl_gpr64_u8) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(256);
|
||||
std::vector<s64> vals = {0, 1, -2, INT32_MIN, INT32_MAX, INT64_MIN,
|
||||
|
||||
-1579
File diff suppressed because it is too large
Load Diff
+147
@@ -0,0 +1,147 @@
|
||||
# Building Capstone
|
||||
|
||||
This guide describes how to build Capstone with `CMake`.
|
||||
|
||||
## Build commands
|
||||
|
||||
**Unix**
|
||||
|
||||
```bash
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release # For debug build change "Release" to "Debug"
|
||||
cmake --build build
|
||||
cmake --install build --prefix "<install-prefix>"
|
||||
```
|
||||
|
||||
To create rpm, debian and OSX packages, run the following
|
||||
```bash
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCAPSTONE_BUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake --build build
|
||||
cd build
|
||||
cpack -G DEB
|
||||
cpack -G RPM
|
||||
cpack -G DragNDrop
|
||||
```
|
||||
|
||||
**Windows**
|
||||
|
||||
```bash
|
||||
cmake.exe -B build
|
||||
cmake.exe --build build --config Release # For debug build change "Release" to "Debug"
|
||||
cmake.exe --install build
|
||||
```
|
||||
|
||||
## Tailor Capstone to your needs.
|
||||
|
||||
Enable and disable options in the "configure" step (first `cmake` command from above).
|
||||
Options are added with `-D<OPTION>=ON/OFF` or `-D<OPTION>=1/0`
|
||||
|
||||
### Exclude architecture modules
|
||||
|
||||
You can build Capstone with only the architectures you need.
|
||||
By default all are enabled.
|
||||
|
||||
- `CAPSTONE_ARCHITECTURE_DEFAULT`: Whether all architectures are enabled by default.
|
||||
- `CAPSTONE_ARM_SUPPORT`: Support ARM.
|
||||
- `CAPSTONE_AARCH64_SUPPORT`: Support AARCH64.
|
||||
- `CAPSTONE_ALPHA_SUPPORT`: Support Alpha.
|
||||
- `CAPSTONE_ARC_SUPPORT`: Support ARC.
|
||||
- `CAPSTONE_HPPA_SUPPORT`: Support HPPA.
|
||||
- `CAPSTONE_LOONGARCH_SUPPORT`: Support LoongArch.
|
||||
- `CAPSTONE_M680X_SUPPORT`: Support M680X.
|
||||
- `CAPSTONE_M68K_SUPPORT`: Support M68K.
|
||||
- `CAPSTONE_MIPS_SUPPORT`: Support Mips.
|
||||
- `CAPSTONE_MOS65XX_SUPPORT`: Support MOS65XX.
|
||||
- `CAPSTONE_PPC_SUPPORT`: Support PPC.
|
||||
- `CAPSTONE_SPARC_SUPPORT`: Support Sparc.
|
||||
- `CAPSTONE_SYSTEMZ_SUPPORT`: Support SystemZ.
|
||||
- `CAPSTONE_XCORE_SUPPORT`: Support XCore.
|
||||
- `CAPSTONE_TRICORE_SUPPORT`: Support TriCore.
|
||||
- `CAPSTONE_X86_SUPPORT`: Support X86.
|
||||
- `CAPSTONE_TMS320C64X_SUPPORT`: Support TMS320C64X.
|
||||
- `CAPSTONE_EVM_SUPPORT`: Support EVM.
|
||||
- `CAPSTONE_WASM_SUPPORT`: Support Web Assembly.
|
||||
- `CAPSTONE_BPF_SUPPORT`: Support BPF.
|
||||
- `CAPSTONE_RISCV_SUPPORT`: Support RISCV.
|
||||
|
||||
### Module registration
|
||||
|
||||
If you're building a static library that you intend to link into multiple consumers,
|
||||
and they have differing architecture requirements, you may want `-DCAPSTONE_USE_ARCH_REGISTRATION=1`.
|
||||
|
||||
In your consumer code you can call `cs_arch_register_*()` to register the specific module for initialization.
|
||||
|
||||
In this way you only pay footprint size for the architectures you're actually using in each consumer,
|
||||
without having to compile Capstone multiple times.
|
||||
|
||||
### Additional options
|
||||
|
||||
Capstone allows some more customization via the following options:
|
||||
|
||||
- `CAPSTONE_BUILD_SHARED_LIBS`: Build shared libraries.
|
||||
- `CAPSTONE_BUILD_STATIC_LIBS`: Build static libraries (`ON` by default).
|
||||
- `CAPSTONE_BUILD_STATIC_MSVC_RUNTIME`: (Windows only) - Build with static MSVC runtime. Always set if `CAPSTONE_BUILD_SHARED_LIBS=ON`.
|
||||
- `CAPSTONE_BUILD_CSTOOL`: Enable/disable build of `cstool`. Default is enabled if build runs from the repository root.
|
||||
- `CAPSTONE_USE_SYS_DYN_MEM`: change this to OFF to use your own dynamic memory management.
|
||||
- `CAPSTONE_BUILD_MACOS_THIN`: MacOS only. Disables universal2 build. So you only get the binary for you processor architecture.
|
||||
- `CAPSTONE_BUILD_DIET`: change this to ON to make the binaries more compact.
|
||||
- `CAPSTONE_X86_REDUCE`: change this to ON to make X86 binary smaller.
|
||||
- `CAPSTONE_X86_ATT_DISABLE`: change this to ON to disable AT&T syntax on x86.
|
||||
|
||||
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE
|
||||
modes are disabled. To use your own memory allocations, turn ON both DIET &
|
||||
X86_REDUCE, run "cmake" with: `-DCAPSTONE_USE_SYS_DYN_MEM=0`, `-DCAPSTONE_BUILD_DIET=1`, `-DCAPSTONE_X86_REDUCE=1`
|
||||
|
||||
### Cross compilation
|
||||
|
||||
We have some example configurations for cross builds in [cross_configs](cross_configs/).
|
||||
Build them with the following command (static build is of course optional):
|
||||
|
||||
```bash
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=cross_configs/<cross_build_config>.cmake -DCAPSTONE_BUILD_STATIC_LIBS=ON -S . -B build
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
See the cmake cross compilation [documentation](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html)
|
||||
for more details.
|
||||
|
||||
**Android**
|
||||
|
||||
The [Android SDK provides](https://developer.android.com/ndk/guides/cmake) a toolchain file for CMake.
|
||||
It is the most reliable way to build Capstone for Android.
|
||||
|
||||
_Example:_
|
||||
|
||||
```bash
|
||||
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$NDK_PATH/build/cmake/android.toolchain.cmake -DANDROID_NDK=$NDK_PATH -DANDROID_ABI=arm64-v8a
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
#### Test cross build with QEMU
|
||||
|
||||
Running the binaries with QEMU (here an example for s390x on Fedora 40)
|
||||
is usually done with a command like this:
|
||||
|
||||
```bash
|
||||
QEMU_LD_PREFIX=/usr/s390x-redhat-linux/sys-root/fc40/usr/ qemu-s390x-static ./build/cstool -d aarch64 01421bd501423bd5
|
||||
```
|
||||
|
||||
### Developer specific options
|
||||
|
||||
- `CAPSTONE_DEBUG`: Change this to ON to enable extra debug assertions. Automatically enabled with `Debug` build.
|
||||
- `CAPSTONE_BUILD_CSTEST`: Build `cstest` in `suite/cstest/`. **Note:** `cstest` requires `libyaml` on your system. It attempts to build it from source otherwise.
|
||||
- `CMAKE_EXPORT_COMPILE_COMMANDS`: To export `compile_commands.json` for `clangd` and other language servers.
|
||||
- `ENABLE_ASAN`: Compiles Capstone with the address sanitizer.
|
||||
- `ENABLE_COVERAGE`: Generate coverage files.
|
||||
- `CAPSTONE_BUILD_LEGACY_TESTS`: Build some legacy integration tests.
|
||||
|
||||
## Building cstest
|
||||
|
||||
`cstest` is build together with Capstone by adding the flag `-DCAPSTONE_BUILD_CSTEST`.
|
||||
|
||||
The build requires `libyaml`. It is a fairly common package and should be provided by your package manager.
|
||||
If not present it will attempt to build it from source.
|
||||
|
||||
_Note:_ Currently `cstest` is only tested on Linux.
|
||||
|
||||
If you run another operation system, please install `cstest_py`.
|
||||
See `bindings/python/BUILDING.md` for instructions.
|
||||
+1102
File diff suppressed because it is too large
Load Diff
+175
@@ -0,0 +1,175 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "locations-base",
|
||||
"hidden": true,
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}"
|
||||
},
|
||||
{
|
||||
"name": "warnings-base",
|
||||
"hidden": true,
|
||||
"warnings": {
|
||||
"dev": true,
|
||||
"deprecated": true,
|
||||
"systemVars": true
|
||||
},
|
||||
"errors": {
|
||||
"dev": true,
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ninja",
|
||||
"hidden": true,
|
||||
"displayName": "Ninja",
|
||||
"generator": "Ninja Multi-Config",
|
||||
"cacheVariables": {
|
||||
"CMAKE_DEFAULT_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64",
|
||||
"hidden": true,
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "diet",
|
||||
"hidden": true,
|
||||
"displayName": "DIET",
|
||||
"generator": "DIET build",
|
||||
"cacheVariables": {
|
||||
"CAPSTONE_BUILD_DIET": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-x64",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "macos-x64",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "windows-x64",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "windows-x64-diet",
|
||||
"inherits": [ "ninja", "x64", "locations-base", "warnings-base", "diet" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "build-linux",
|
||||
"configurePreset": "linux-x64",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "build-macos",
|
||||
"configurePreset": "macos-x64",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "build-windows",
|
||||
"configurePreset": "windows-x64",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "build-windows-diet",
|
||||
"configurePreset": "windows-x64-diet",
|
||||
"nativeToolOptions": [ "-v" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "build-linux-release",
|
||||
"inherits": "build-linux",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "build-macos-release",
|
||||
"inherits": "build-macos",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "build-windows-release",
|
||||
"inherits": "build-windows",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "build-windows-diet-release",
|
||||
"inherits": "build-windows-diet",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "install-linux",
|
||||
"configurePreset": "linux-x64",
|
||||
"inherits": "build-linux",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "install-macos",
|
||||
"configurePreset": "macos-x64",
|
||||
"inherits": "build-macos",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "install-windows",
|
||||
"configurePreset": "windows-x64",
|
||||
"inherits": "build-windows",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "install-windows-diet",
|
||||
"configurePreset": "windows-x64-diet",
|
||||
"inherits": "build-windows-diet",
|
||||
"targets": [ "install" ],
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "install-linux-release",
|
||||
"inherits": "install-linux",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Linux"}
|
||||
},
|
||||
{
|
||||
"name": "install-macos-release",
|
||||
"inherits": "install-macos",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Darwin"}
|
||||
},
|
||||
{
|
||||
"name": "install-windows-release",
|
||||
"inherits": "install-windows",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
},
|
||||
{
|
||||
"name": "install-windows-diet-release",
|
||||
"inherits": "install-windows-diet",
|
||||
"configuration": "Release",
|
||||
"condition": {"type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows"}
|
||||
}
|
||||
]
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
|
||||
# NOTICE
|
||||
|
||||
> Please be aware that the Makefile build is deprecated.
|
||||
> Use cmake instead.
|
||||
|
||||
<hr>
|
||||
|
||||
This documentation explains how to compile, install & run Capstone on MacOSX,
|
||||
Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows.
|
||||
|
||||
To natively compile for Windows using Microsoft Visual Studio, see BUILDING.md.
|
||||
|
||||
To compile using CMake, see BUILDING.md.
|
||||
|
||||
To compile using XCode on MacOSX, see xcode/README.md.
|
||||
|
||||
To compile for Windows CE (a.k.a, Windows Embedded Compact), see windowsce/COMPILE.md.
|
||||
|
||||
*-*-*-*-*-*
|
||||
|
||||
Capstone requires no prerequisite packages, so it is easy to compile & install.
|
||||
|
||||
|
||||
|
||||
(0) Tailor Capstone to your need.
|
||||
|
||||
Out of all architectures supported by Capstone, if you just need several
|
||||
selected archs, choose the ones you want to compile in by editing "config.mk"
|
||||
before going to next steps.
|
||||
|
||||
By default, all architectures are compiled.
|
||||
|
||||
The other way of customize Capstone without having to edit config.mk is to
|
||||
pass the desired options on the commandline to ./make.sh. Currently,
|
||||
Capstone supports 8 options, as followings.
|
||||
|
||||
- CAPSTONE_ARCHS: specify list of architectures to compiled in.
|
||||
- CAPSTONE_USE_SYS_DYN_MEM: change this if you have your own dynamic memory management.
|
||||
- CAPSTONE_DIET: use this to make the output binaries more compact.
|
||||
- CAPSTONE_X86_REDUCE: another option to make X86 binary smaller.
|
||||
- CAPSTONE_X86_ATT_DISABLE: disables AT&T syntax on x86.
|
||||
- CAPSTONE_STATIC: build static library.
|
||||
- CAPSTONE_SHARED: build dynamic (shared) library.
|
||||
- CAPSTONE_DEBUG: enable debug build supporting assert().
|
||||
|
||||
By default, Capstone uses system dynamic memory management, both DIET and X86_REDUCE
|
||||
modes are disable, and builds all the static & shared libraries.
|
||||
|
||||
To avoid editing config.mk for these customization, we can pass their values to
|
||||
make.sh, as followings.
|
||||
|
||||
$ CAPSTONE_ARCHS="arm aarch64 x86" CAPSTONE_USE_SYS_DYN_MEM=no CAPSTONE_DIET=yes CAPSTONE_X86_REDUCE=yes ./make.sh
|
||||
|
||||
NOTE: on commandline, put these values in front of ./make.sh, not after it.
|
||||
|
||||
For each option, refer to docs/README for more details.
|
||||
|
||||
|
||||
|
||||
(1) Compile from source
|
||||
|
||||
On *nix (such as MacOSX, Linux, *BSD, Solaris):
|
||||
|
||||
- To compile for current platform, run:
|
||||
|
||||
$ ./make.sh
|
||||
|
||||
- On 64-bit OS, run the command below to cross-compile Capstone for 32-bit binary:
|
||||
|
||||
$ ./make.sh nix32
|
||||
|
||||
|
||||
|
||||
(2) Install Capstone on *nix
|
||||
|
||||
To install Capstone, run:
|
||||
|
||||
$ sudo ./make.sh install
|
||||
|
||||
For FreeBSD/OpenBSD, where sudo is unavailable, run:
|
||||
|
||||
$ su; ./make.sh install
|
||||
|
||||
Users are then required to enter root password to copy Capstone into machine
|
||||
system directories.
|
||||
|
||||
Afterwards, run ./tests/test* to see the tests disassembling sample code.
|
||||
|
||||
|
||||
NOTE: The core framework installed by "./make.sh install" consist of
|
||||
following files:
|
||||
|
||||
/usr/include/capstone/arm.h
|
||||
/usr/include/capstone/arm64.h
|
||||
/usr/include/capstone/alpha.h
|
||||
/usr/include/capstone/arc.h
|
||||
/usr/include/capstone/bpf.h
|
||||
/usr/include/capstone/capstone.h
|
||||
/usr/include/capstone/evm.h
|
||||
/usr/include/capstone/hppa.h
|
||||
/usr/include/capstone/loongarch.h
|
||||
/usr/include/capstone/m680x.h
|
||||
/usr/include/capstone/m68k.h
|
||||
/usr/include/capstone/mips.h
|
||||
/usr/include/capstone/mos65xx.h
|
||||
/usr/include/capstone/platform.h
|
||||
/usr/include/capstone/ppc.h
|
||||
/usr/include/capstone/sparc.h
|
||||
/usr/include/capstone/systemz.h
|
||||
/usr/include/capstone/tms320c64x.h
|
||||
/usr/include/capstone/wasm.h
|
||||
/usr/include/capstone/x86.h
|
||||
/usr/include/capstone/xcore.h
|
||||
/usr/include/capstone/tricore.h
|
||||
/usr/lib/libcapstone.a
|
||||
/usr/lib/libcapstone.so (for Linux/*nix), or /usr/lib/libcapstone.dylib (OSX)
|
||||
|
||||
|
||||
|
||||
(3) Cross-compile for Windows from *nix
|
||||
|
||||
To cross-compile for Windows, Linux & gcc-mingw-w64-i686 (and also gcc-mingw-w64-x86-64
|
||||
for 64-bit binaries) are required.
|
||||
|
||||
- To cross-compile Windows 32-bit binary, simply run:
|
||||
|
||||
$ ./make.sh cross-win32
|
||||
|
||||
- To cross-compile Windows 64-bit binary, run:
|
||||
|
||||
$ ./make.sh cross-win64
|
||||
|
||||
Resulted files libcapstone.dll, libcapstone.dll.a & tests/test*.exe can then
|
||||
be used on Windows machine.
|
||||
|
||||
|
||||
|
||||
(4) Cross-compile for iOS from Mac OSX.
|
||||
|
||||
To cross-compile for iOS (iPhone/iPad/iPod), Mac OSX with XCode installed is required.
|
||||
|
||||
- To cross-compile for ArmV7 (iPod 4, iPad 1/2/3, iPhone4, iPhone4S), run:
|
||||
$ ./make.sh ios_armv7
|
||||
|
||||
- To cross-compile for ArmV7s (iPad 4, iPhone 5C, iPad mini), run:
|
||||
$ ./make.sh ios_armv7s
|
||||
|
||||
- To cross-compile for Arm64 (iPhone 5S, iPad mini Retina, iPad Air), run:
|
||||
$ ./make.sh ios_arm64
|
||||
|
||||
- To cross-compile for all iDevices (armv7 + armv7s + arm64), run:
|
||||
$ ./make.sh ios
|
||||
|
||||
Resulted files libcapstone.dylib, libcapstone.a & tests/test* can then
|
||||
be used on iOS devices.
|
||||
|
||||
|
||||
|
||||
(5) Cross-compile for Android
|
||||
|
||||
To cross-compile for Android (smartphone/tablet), Android NDK is required.
|
||||
NOTE: Only ARM and AARCH64 are currently supported.
|
||||
|
||||
$ NDK=/android/android-ndk-r10e ./make.sh cross-android arm
|
||||
or
|
||||
$ NDK=/android/android-ndk-r10e ./make.sh cross-android arm64
|
||||
|
||||
Resulted files libcapstone.so, libcapstone.a & tests/test* can then
|
||||
be used on Android devices.
|
||||
|
||||
|
||||
|
||||
(6) Compile on Windows with Cygwin
|
||||
|
||||
To compile under Cygwin gcc-mingw-w64-i686 or x86_64-w64-mingw32 run:
|
||||
|
||||
- To compile Windows 32-bit binary under Cygwin, run:
|
||||
|
||||
$ ./make.sh cygwin-mingw32
|
||||
|
||||
- To compile Windows 64-bit binary under Cygwin, run:
|
||||
|
||||
$ ./make.sh cygwin-mingw64
|
||||
|
||||
Resulted files libcapstone.dll, libcapstone.dll.a & tests/test*.exe can then
|
||||
be used on Windows machine.
|
||||
|
||||
|
||||
|
||||
(7) By default, "cc" (default C compiler on the system) is used as compiler.
|
||||
|
||||
- To use "clang" compiler instead, run the command below:
|
||||
|
||||
$ ./make.sh clang
|
||||
|
||||
- To use "gcc" compiler instead, run:
|
||||
|
||||
$ ./make.sh gcc
|
||||
|
||||
|
||||
|
||||
(8) To uninstall Capstone, run the command below:
|
||||
|
||||
$ sudo ./make.sh uninstall
|
||||
|
||||
|
||||
|
||||
(9) Language bindings
|
||||
|
||||
So far, Python, Ocaml & Java are supported by bindings in the main code.
|
||||
Look for the bindings under directory bindings/, and refer to README file
|
||||
of corresponding languages.
|
||||
|
||||
Community also provide bindings for C#, Go, Ruby, NodeJS, C++ & Vala. Links to
|
||||
these can be found at address http://capstone-engine.org/download.html
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
Code structure
|
||||
--------------
|
||||
|
||||
Capstone source is organized as followings.
|
||||
|
||||
```
|
||||
. <- core engine + README.md + BUILDING.md etc
|
||||
├── arch <- code handling disasm engine for each arch
|
||||
│ ├── AArch64 <- AArch64 engine
|
||||
│ ├── Alpha <- Alpha engine
|
||||
│ ├── ARC <- ARC engine
|
||||
│ ├── ARM <- ARM engine
|
||||
│ ├── BPF <- Berkeley Packet Filter engine
|
||||
│ ├── EVM <- Ethereum engine
|
||||
│ ├── HPPA <- HPPA engine
|
||||
│ ├── LoongArch <- LoongArch engine
|
||||
│ ├── M680X <- M680X engine
|
||||
│ ├── M68K <- M68K engine
|
||||
│ ├── Mips <- Mips engine
|
||||
│ ├── MOS65XX <- MOS65XX engine
|
||||
│ ├── PowerPC <- PowerPC engine
|
||||
│ ├── RISCV <- RISCV engine
|
||||
│ ├── SH <- SH engine
|
||||
│ ├── Sparc <- Sparc engine
|
||||
│ ├── SystemZ <- SystemZ engine
|
||||
│ ├── TMS320C64x <- TMS320C64x engine
|
||||
│ ├── TriCore <- TriCore engine
|
||||
│ ├── WASM <- WASM engine
|
||||
│ ├── X86 <- x86 engine
|
||||
│ ├── XCore <- XCore engine
|
||||
│ └── Xtensa <- Xtensa engine
|
||||
├── bindings <- all bindings are under this dir
|
||||
│ ├── java <- Java bindings
|
||||
│ ├── ocaml <- Ocaml bindings
|
||||
│ └── python <- Python bindings
|
||||
│ └── cstest <- Testing tool for the Python bindings.
|
||||
├── suite <- Several tools used for development
|
||||
│ ├── cstest <- Testing tool to consume and check the test `yaml` files in `tests`
|
||||
│ ├── fuzz <- Fuzzer
|
||||
│ └── auto-sync <- The updater for Capstone modules
|
||||
├── contrib <- Code contributed by community to help Capstone integration
|
||||
├── cstool <- Cstool
|
||||
├── docs <- Documentation
|
||||
├── include <- API headers in C language (*.h)
|
||||
├── packages <- Packages for Linux/OSX/BSD.
|
||||
├── windows <- Windows support (for Windows kernel driver compile)
|
||||
├── tests <- Unit and itegration tests
|
||||
└── xcode <- Xcode support (for MacOSX compile)
|
||||
```
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
Follow the instructions in [BUILDING.md](BUILDING.md) for how to compile and run test code.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
General testing docs are at [tests/README.md](tests/README.md).
|
||||
|
||||
You can test single instructions easily with the `cstool`.
|
||||
For example:
|
||||
|
||||
```bash
|
||||
$ cstool x32 "90 91"
|
||||
```
|
||||
|
||||
Using `cstool` is also the prefered way for debugging a single instruction.
|
||||
|
||||
**Bindings**
|
||||
|
||||
Bindings currently have not equivalent to a `cstool`.
|
||||
|
||||
The Python bindings have `cstool` implemented.
|
||||
|
||||
Other bindings are out-of-date for a while because of missing maintainers.
|
||||
They only have legacy integration tests.
|
||||
|
||||
Please check the issues or open a new one if you intent to work on them or need them.
|
||||
|
||||
Coding style
|
||||
------------
|
||||
- We provide a `.clang-format` for C code.
|
||||
- Python files should be formatted with `black`.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
**Please always open an issue or leave a comment in one, before starting work on an architecture! We can give support and save you a lot of time.**
|
||||
|
||||
Updating an Architecture
|
||||
------------------------
|
||||
|
||||
The update tool for Capstone is called `Auto-Sync` and can be found in `suite/auto-sync`.
|
||||
|
||||
Not all architectures are supported yet.
|
||||
Run `suite/auto-sync/Updater/ASUpdater.py -h` to get a list of currently supported architectures.
|
||||
|
||||
The documentation how to update with `Auto-Sync` or refactor an architecture module
|
||||
can be found in [suite/auto-sync/README.md](suite/auto-sync/README.md).
|
||||
|
||||
If a module does not support `Auto-Sync` yet, it is highly recommended to refactor it
|
||||
instead of attempting to update it manually.
|
||||
Refactoring will take less time and updates it during the procedure.
|
||||
|
||||
The one exception is `x86`. In LLVM we use several emitter backends to generate C code.
|
||||
One of those LLVM backends (the `DecoderEmitter`) has two versions.
|
||||
One for `x86` and another for all the other architectures.
|
||||
Until now it was not worth it to refactoring this unique `x86` backend. So `x86` is not
|
||||
supported currently.
|
||||
|
||||
Adding an Architecture
|
||||
----------------------
|
||||
|
||||
If your architecture is supported in LLVM or one of its forks, you can use `Auto-Sync` to
|
||||
add the new module.
|
||||
Checkout [suite/auto-sync/RefactorGuide.md](suite/auto-sync/RefactorGuide.md).
|
||||
|
||||
Otherwise, you need to implement the disassembler on your own and make it work with the Capstone API.
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Used to dynamically set the package file name based on the generator
|
||||
foreach(generator ${CPACK_GENERATOR})
|
||||
if("${generator}" STREQUAL "DEB")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_DEBIAN_PACKAGE_FILE_NAME})
|
||||
elseif("${generator}" STREQUAL "RPM")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_RPM_PACKAGE_FILE_NAME})
|
||||
elseif("${generator}" STREQUAL "NSIS")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_NSIS_PACKAGE_FILE_NAME})
|
||||
elseif("${generator}" STREQUAL "DragNDrop")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_DMG_PACKAGE_FILE_NAME})
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-unknown")
|
||||
endif()
|
||||
message(STATUS "Generating package for ${generator} with file name ${CPACK_PACKAGE_FILE_NAME}")
|
||||
endforeach()
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
# Copyright © 2024 Andrew Quijano <andrewquijano92@gmail.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Set general CPack values
|
||||
set(CPACK_PACKAGE_NAME "capstone")
|
||||
set(CPACK_PACKAGE_VENDOR "Rot127")
|
||||
set(CPACK_PACKAGE_CONTACT "Rot127 <unisono@quyllur.org>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Capstone is a lightweight multi-platform, multi-architecture disassembly framework. These are the development headers and libraries.\n Features:\n - Support hardware architectures: AArch64, ARM, Alpha, BPF, EVM, HPPA, LongArch, M680X, M68K, MOS65XX, Mips, PowerPC, RISCV, SH, Sparc, SystemZ, TMS320C64x, TriCore, WASM, x86, XCore, Xtensa.\n - Clean/simple/lightweight/intuitive architecture-neutral API.\n - Provide details on disassembled instructions (called \\\"decomposer\\\" by some others).\n - Provide some semantics of the disassembled instruction, such as list of implicit registers read & written.\n - Thread-safe by design.\n - Special support for embedding into firmware or OS kernel.\n - Distributed under the open source BSD license.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Lightweight multi-architecture disassembly framework - devel files")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL "https://www.capstone-engine.org/")
|
||||
set(CPACK_STRIP_FILES false)
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSES/LICENSE.TXT")
|
||||
|
||||
# Set Debian-specific package variables
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "libcapstone-dev")
|
||||
set(CPACK_DEBIAN_PACKAGE_SOURCE "capstone")
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
set(CPACK_DEBIAN_PACKAGE_ORIGINAL_MAINTAINER "Debian Security Tools <team+pkg-security@tracker.debian.org>")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.2.5)")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "libdevel")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_PACKAGE_MULTIARCH "same")
|
||||
|
||||
# Determine architecture for Debian package
|
||||
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
||||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i386" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i686")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
|
||||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm")
|
||||
if(CMAKE_SIZE_OF_VOID_P EQUAL 4)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
endif()
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
# Include additional file to run 'ldconfig' after install
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${PROJECT_SOURCE_DIR}/packages/deb/triggers")
|
||||
|
||||
# RPM package settings
|
||||
set(CPACK_RPM_PACKAGE_NAME "capstone-devel")
|
||||
set(CPACK_RPM_PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "glibc >= 2.2.5")
|
||||
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/packages/rpm/postinstall.sh")
|
||||
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/packages/rpm/postinstall.sh")
|
||||
set(CPACK_RPM_CHANGELOG_FILE "${PROJECT_SOURCE_DIR}/ChangeLog")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "BSD3, LLVM")
|
||||
set(CPACK_RPM_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")
|
||||
|
||||
# Windows package settings
|
||||
if(WIN32)
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "capstone")
|
||||
set(CPACK_SYSTEM_NAME "Windows-x64")
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
set(CPACK_NSIS_PACKAGE_NAME "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}")
|
||||
endif()
|
||||
|
||||
# Set package file name based on the generator
|
||||
set(CPACK_DEBIAN_PACKAGE_FILE_NAME "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
set(CPACK_RPM_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_DMG_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_NSIS_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}")
|
||||
|
||||
include(CPack)
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
This file credits all the contributors of the Capstone engine project.
|
||||
|
||||
Key developers
|
||||
==============
|
||||
Nguyen Anh Quynh <aquynh -at- gmail.com>
|
||||
Chenxu Wu (kabeor) kabeor@qiling.io
|
||||
|
||||
|
||||
Past key developers
|
||||
===================
|
||||
Tan Sheng Di <shengdi -at- coseinc.com>
|
||||
- Bindings: Ruby
|
||||
|
||||
Ben Nagy <ben -at- coseinc.com>
|
||||
- Bindings: Ruby, Go
|
||||
|
||||
Dang Hoang Vu <dang.hvu -at- gmail.com>
|
||||
- Bindings: Java
|
||||
|
||||
|
||||
Beta testers (in random order)
|
||||
==============================
|
||||
Pancake
|
||||
Van Hauser
|
||||
FX of Phenoelit
|
||||
The Grugq, The Grugq <-- our hero for submitting the first ever patch!
|
||||
Isaac Dawson, Veracode Inc
|
||||
Patroklos Argyroudis, Census Inc. (http://census-labs.com)
|
||||
Attila Suszter
|
||||
Le Dinh Long
|
||||
Nicolas Ruff
|
||||
Gunther
|
||||
Alex Ionescu, Winsider Seminars & Solutions Inc.
|
||||
Snare
|
||||
Daniel Godas-Lopez
|
||||
Joshua J. Drake
|
||||
Edgar Barbosa
|
||||
Ralf-Philipp Weinmann
|
||||
Hugo Fortier
|
||||
Joxean Koret
|
||||
Bruce Dang
|
||||
Andrew Dunham
|
||||
|
||||
|
||||
Contributors (in no particular order)
|
||||
=====================================
|
||||
(Please let us know if you want to have your name here)
|
||||
|
||||
Ole André Vadla Ravnås (author of the 100th Pull-Request in our Github repo, thanks!)
|
||||
Axel "0vercl0k" Souchet (@0vercl0k) & Alex Ionescu: port to MSVC.
|
||||
Daniel Pistelli: Cmake support.
|
||||
Peter Hlavaty: integrate Capstone for Windows kernel drivers.
|
||||
Guillaume Jeanne: Ocaml binding.
|
||||
Martin Tofall, Obsidium Software: Optimize X86 performance & size + x86 encoding features.
|
||||
David Martínez Moreno & Hilko Bengen: Debian package.
|
||||
Félix Cloutier: Xcode project.
|
||||
Benoit Lecocq: OpenBSD package.
|
||||
Christophe Avoinne (Hlide): Improve memory management for better performance.
|
||||
Michael Cohen & Nguyen Tan Cong: Python module installer.
|
||||
Adel Gadllah, Francisco Alonso & Stefan Cornelius: RPM package.
|
||||
Felix Gröbert (Google): fuzz testing harness.
|
||||
Xipiter LLC: Capstone logo redesigned.
|
||||
Satoshi Tanda: Support Windows kernel driver.
|
||||
Tang Yuhang: cstool.
|
||||
Andrew Dutcher: better Python setup.
|
||||
Ruben Boonen: PowerShell binding.
|
||||
David Zimmer: VB6 binding.
|
||||
Philippe Antoine: Integration with oss-fuzz and various fixes.
|
||||
Bui Dinh Cuong: Explicit registers accessed for Arm64.
|
||||
Vincent Bénony: Explicit registers accessed for X86.
|
||||
Adel Gadllah, Francisco Alonso & Stefan Cornelius: RPM package.
|
||||
Felix Gröbert (Google): fuzz testing harness.
|
||||
Daniel Collin & Nicolas Planel: M68K architecture.
|
||||
Pranith Kumar: Explicit registers accessed for Arm64.
|
||||
Xipiter LLC: Capstone logo redesigned.
|
||||
Satoshi Tanda: Support Windows kernel driver.
|
||||
Koutheir Attouchi: Support for Windows CE.
|
||||
Fotis Loukos: TMS320C64x architecture.
|
||||
Wolfgang Schwotzer: M680X architecture.
|
||||
Philippe Antoine: Integration with oss-fuzz and various fixes.
|
||||
Stephen Eckels (stevemk14ebr): x86 encoding features
|
||||
Tong Yu(Spike) & Kai Jern, Lau (xwings): WASM architecture.
|
||||
Sebastian Macke: MOS65XX architecture
|
||||
Ilya Leoshkevich: SystemZ architecture improvements.
|
||||
Do Minh Tuan: Regression testing tool (cstest)
|
||||
david942j: BPF (both classic and extended) architecture.
|
||||
fanfuqiang & citypw & porto703 : RISCV architecture.
|
||||
Josh "blacktop" Maine: Arm64 architecture improvements.
|
||||
Finn Wilkinson: AArch64 update to Armv9.2-a (SME + SVE2 support)
|
||||
Billow & Sidneyp: TriCore architecture.
|
||||
Dmitry Sibirtsev: Alpha, HPPA, ARC architecture.
|
||||
Jiajie Chen & Yanglin Xun: LoongArch architecture.
|
||||
Billow: Xtensa architecture.
|
||||
+1652
File diff suppressed because it is too large
Load Diff
+38
@@ -0,0 +1,38 @@
|
||||
//===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares some utility functions for encoding SLEB128 and
|
||||
// ULEB128 values.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_SUPPORT_LEB128_H
|
||||
#define CS_LLVM_SUPPORT_LEB128_H
|
||||
|
||||
#include "include/capstone/capstone.h"
|
||||
|
||||
/// Utility function to decode a ULEB128 value.
|
||||
static inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n)
|
||||
{
|
||||
const uint8_t *orig_p = p;
|
||||
uint64_t Value = 0;
|
||||
unsigned Shift = 0;
|
||||
do {
|
||||
Value += (uint64_t)(*p & 0x7f) << Shift;
|
||||
Shift += 7;
|
||||
} while (*p++ >= 128);
|
||||
if (n)
|
||||
*n = (unsigned)(p - orig_p);
|
||||
return Value;
|
||||
}
|
||||
|
||||
#endif // LLVM_SYSTEM_LEB128_H
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
This is the software license for Capstone disassembly framework.
|
||||
Capstone has been designed & implemented by Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
|
||||
See http://www.capstone-engine.org for further information.
|
||||
|
||||
Copyright (c) 2013, COSEINC.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the developer(s) nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Copyright (c) <year> <owner>.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
==============================================================================
|
||||
LLVM Release License
|
||||
==============================================================================
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2003-2013 University of Illinois at Urbana-Champaign.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
Copyrights and Licenses for Third Party Software Distributed with LLVM:
|
||||
==============================================================================
|
||||
The LLVM software contains code written by third parties. Such software will
|
||||
have its own individual LICENSE.TXT file in the directory in which it appears.
|
||||
This file will describe the copyrights, license, and restrictions which apply
|
||||
to that code.
|
||||
|
||||
The disclaimer of warranty in the University of Illinois Open Source License
|
||||
applies to all code in the LLVM Distribution, and nothing in any of the
|
||||
other licenses gives permission to use the names of the LLVM Team or the
|
||||
University of Illinois to endorse or promote products derived from this
|
||||
Software.
|
||||
|
||||
The following pieces of software have additional or alternate copyrights,
|
||||
licenses, and/or restrictions:
|
||||
|
||||
Program Directory
|
||||
------- ---------
|
||||
Autoconf llvm/autoconf
|
||||
llvm/projects/ModuleMaker/autoconf
|
||||
llvm/projects/sample/autoconf
|
||||
Google Test llvm/utils/unittest/googletest
|
||||
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
|
||||
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
|
||||
ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
|
||||
md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright © 2024 Rot127 <unisono@quyllur.org>
|
||||
// SPDX-License-Identifier: BSD-3
|
||||
|
||||
/// The equivalent of the MCAsmInfo class in LLVM.
|
||||
/// We save only some flags of the original class here.
|
||||
|
||||
#ifndef CS_MCASMINFO_H
|
||||
#define CS_MCASMINFO_H
|
||||
|
||||
typedef enum {
|
||||
SYSTEMZASMDIALECT_AD_ATT = 0,
|
||||
SYSTEMZASMDIALECT_AD_HLASM = 1,
|
||||
} MCAsmInfoAssemblerDialect;
|
||||
|
||||
typedef struct {
|
||||
MCAsmInfoAssemblerDialect assemblerDialect;
|
||||
} MCAsmInfo;
|
||||
|
||||
#endif // CS_MCASMINFO_H
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_MCDISASSEMBLER_H
|
||||
#define CS_MCDISASSEMBLER_H
|
||||
|
||||
typedef enum DecodeStatus {
|
||||
MCDisassembler_Fail = 0,
|
||||
MCDisassembler_SoftFail = 1,
|
||||
MCDisassembler_Success = 3,
|
||||
} DecodeStatus;
|
||||
|
||||
#endif
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
//===-- llvm/MC/MCFixedLenDisassembler.h - Decoder driver -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Fixed length disassembler decoder state machine driver.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_MC_MCFIXEDLENDISASSEMBLER_H
|
||||
#define CS_LLVM_MC_MCFIXEDLENDISASSEMBLER_H
|
||||
|
||||
// Disassembler state machine opcodes.
|
||||
enum DecoderOps {
|
||||
MCD_OPC_ExtractField =
|
||||
1, // OPC_ExtractField(uint8_t Start, uint8_t Len)
|
||||
MCD_OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip)
|
||||
MCD_OPC_CheckField, // OPC_CheckField(uint8_t Start, uint8_t Len,
|
||||
// uleb128 Val, uint16_t NumToSkip)
|
||||
MCD_OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip)
|
||||
MCD_OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
|
||||
MCD_OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx,
|
||||
// uint16_t NumToSkip)
|
||||
MCD_OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
|
||||
MCD_OPC_Fail // OPC_Fail()
|
||||
};
|
||||
|
||||
#endif
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
||||
#include <Availability.h>
|
||||
#include <libkern/libkern.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "MCInstrDesc.h"
|
||||
#include "MCInst.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1)
|
||||
|
||||
void MCInst_Init(MCInst *inst, cs_arch arch)
|
||||
{
|
||||
memset(inst, 0, sizeof(MCInst));
|
||||
// unnecessary to initialize in loop . its expensive and inst->size should be honored
|
||||
inst->Operands[0].Kind = kInvalid;
|
||||
inst->Operands[0].ImmVal = 0;
|
||||
|
||||
inst->Opcode = 0;
|
||||
inst->OpcodePub = 0;
|
||||
inst->size = 0;
|
||||
inst->has_imm = false;
|
||||
inst->op1_size = 0;
|
||||
inst->ac_idx = 0;
|
||||
inst->popcode_adjust = 0;
|
||||
inst->assembly[0] = '\0';
|
||||
inst->wasm_data.type = WASM_OP_INVALID;
|
||||
inst->xAcquireRelease = 0;
|
||||
for (int i = 0; i < MAX_MC_OPS; ++i)
|
||||
inst->tied_op_idx[i] = -1;
|
||||
inst->isAliasInstr = false;
|
||||
inst->fillDetailOps = false;
|
||||
memset(&inst->hppa_ext, 0, sizeof(inst->hppa_ext));
|
||||
|
||||
// Set default assembly dialect.
|
||||
switch (arch) {
|
||||
default:
|
||||
break;
|
||||
case CS_ARCH_SYSTEMZ:
|
||||
inst->MAI.assemblerDialect = SYSTEMZASMDIALECT_AD_HLASM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MCInst_clear(MCInst *inst)
|
||||
{
|
||||
inst->size = 0;
|
||||
}
|
||||
|
||||
// does not free @Op
|
||||
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op)
|
||||
{
|
||||
CS_ASSERT_RET(index < MAX_MC_OPS && inst->size < MAX_MC_OPS);
|
||||
int i;
|
||||
|
||||
for (i = inst->size; i > index; i--)
|
||||
//memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand));
|
||||
inst->Operands[i] = inst->Operands[i - 1];
|
||||
|
||||
inst->Operands[index] = *Op;
|
||||
inst->size++;
|
||||
}
|
||||
|
||||
void MCInst_setOpcode(MCInst *inst, unsigned Op)
|
||||
{
|
||||
inst->Opcode = Op;
|
||||
}
|
||||
|
||||
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
|
||||
{
|
||||
inst->OpcodePub = Op;
|
||||
}
|
||||
|
||||
unsigned MCInst_getOpcode(const MCInst *inst)
|
||||
{
|
||||
return inst->Opcode;
|
||||
}
|
||||
|
||||
unsigned MCInst_getOpcodePub(const MCInst *inst)
|
||||
{
|
||||
return inst->OpcodePub;
|
||||
}
|
||||
|
||||
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
|
||||
{
|
||||
assert(i < MAX_MC_OPS);
|
||||
return &inst->Operands[i];
|
||||
}
|
||||
|
||||
unsigned MCInst_getNumOperands(const MCInst *inst)
|
||||
{
|
||||
return inst->size;
|
||||
}
|
||||
|
||||
// This addOperand2 function doesn't free Op
|
||||
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
|
||||
{
|
||||
CS_ASSERT_RET(inst->size < MAX_MC_OPS);
|
||||
inst->Operands[inst->size] = *Op;
|
||||
|
||||
inst->size++;
|
||||
}
|
||||
|
||||
bool MCOperand_isValid(const MCOperand *op)
|
||||
{
|
||||
return op->Kind != kInvalid;
|
||||
}
|
||||
|
||||
bool MCOperand_isReg(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kRegister || op->MachineOperandType == kRegister;
|
||||
}
|
||||
|
||||
bool MCOperand_isImm(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kImmediate || op->MachineOperandType == kImmediate;
|
||||
}
|
||||
|
||||
bool MCOperand_isFPImm(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kFPImmediate;
|
||||
}
|
||||
|
||||
bool MCOperand_isDFPImm(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kDFPImmediate;
|
||||
}
|
||||
|
||||
bool MCOperand_isExpr(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kExpr;
|
||||
}
|
||||
|
||||
bool MCOperand_isInst(const MCOperand *op)
|
||||
{
|
||||
return op->Kind == kInst;
|
||||
}
|
||||
|
||||
/// getReg - Returns the register number.
|
||||
unsigned MCOperand_getReg(const MCOperand *op)
|
||||
{
|
||||
return op->RegVal;
|
||||
}
|
||||
|
||||
/// setReg - Set the register number.
|
||||
void MCOperand_setReg(MCOperand *op, unsigned Reg)
|
||||
{
|
||||
op->RegVal = Reg;
|
||||
}
|
||||
|
||||
int64_t MCOperand_getImm(const MCOperand *op)
|
||||
{
|
||||
return op->ImmVal;
|
||||
}
|
||||
|
||||
int64_t MCOperand_getExpr(const MCOperand *op)
|
||||
{
|
||||
return op->ImmVal;
|
||||
}
|
||||
|
||||
void MCOperand_setImm(MCOperand *op, int64_t Val)
|
||||
{
|
||||
op->ImmVal = Val;
|
||||
}
|
||||
|
||||
double MCOperand_getFPImm(const MCOperand *op)
|
||||
{
|
||||
return op->FPImmVal;
|
||||
}
|
||||
|
||||
void MCOperand_setFPImm(MCOperand *op, double Val)
|
||||
{
|
||||
op->FPImmVal = Val;
|
||||
}
|
||||
|
||||
MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg)
|
||||
{
|
||||
MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
|
||||
|
||||
op->MachineOperandType = kRegister;
|
||||
op->Kind = kRegister;
|
||||
op->RegVal = Reg;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
|
||||
{
|
||||
CS_ASSERT_RET(mcInst->size < MAX_MC_OPS);
|
||||
MCOperand *op = &(mcInst->Operands[mcInst->size]);
|
||||
mcInst->size++;
|
||||
|
||||
op->MachineOperandType = kRegister;
|
||||
op->Kind = kRegister;
|
||||
op->RegVal = Reg;
|
||||
}
|
||||
|
||||
MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val)
|
||||
{
|
||||
MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
|
||||
|
||||
op->MachineOperandType = kImmediate;
|
||||
op->Kind = kImmediate;
|
||||
op->ImmVal = Val;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val)
|
||||
{
|
||||
CS_ASSERT_RET(mcInst->size < MAX_MC_OPS);
|
||||
MCOperand *op = &(mcInst->Operands[mcInst->size]);
|
||||
mcInst->size++;
|
||||
|
||||
op->MachineOperandType = kImmediate;
|
||||
op->Kind = kImmediate;
|
||||
op->ImmVal = Val;
|
||||
}
|
||||
|
||||
/// Check if any operand of the MCInstrDesc is predicable
|
||||
bool MCInst_isPredicable(const MCInstrDesc *MIDesc)
|
||||
{
|
||||
const MCOperandInfo *OpInfo = MIDesc->OpInfo;
|
||||
unsigned NumOps = MIDesc->NumOperands;
|
||||
for (unsigned i = 0; i < NumOps; ++i) {
|
||||
if (MCOperandInfo_isPredicate(&OpInfo[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Checks if tied operands exist in the instruction and sets
|
||||
/// - The writeback flag in detail
|
||||
/// - Saves the indices of the tied destination operands.
|
||||
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDescTable,
|
||||
unsigned tbl_size)
|
||||
{
|
||||
const MCInstrDesc *InstDesc = NULL;
|
||||
const MCOperandInfo *OpInfo = NULL;
|
||||
unsigned short NumOps = 0;
|
||||
InstDesc =
|
||||
MCInstrDesc_get(MCInst_getOpcode(MI), InstDescTable, tbl_size);
|
||||
OpInfo = InstDesc->OpInfo;
|
||||
NumOps = InstDesc->NumOperands;
|
||||
|
||||
for (unsigned i = 0; i < NumOps; ++i) {
|
||||
if (MCOperandInfo_isTiedToOp(&OpInfo[i])) {
|
||||
int idx = MCOperandInfo_getOperandConstraint(
|
||||
InstDesc, i, MCOI_TIED_TO);
|
||||
|
||||
if (idx == -1)
|
||||
continue;
|
||||
|
||||
if (i >= MAX_MC_OPS) {
|
||||
assert(0 &&
|
||||
"Maximum number of MC operands reached.");
|
||||
}
|
||||
MI->tied_op_idx[i] = idx;
|
||||
|
||||
if (MI->flat_insn->detail)
|
||||
MI->flat_insn->detail->writeback = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if operand with OpNum is tied by another operand
|
||||
/// (operand is tying destination).
|
||||
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum)
|
||||
{
|
||||
assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
|
||||
for (int i = 0; i < MAX_MC_OPS; ++i) {
|
||||
if (MI->tied_op_idx[i] == OpNum)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if operand with OpNum is tying another operand
|
||||
/// (operand is tying src).
|
||||
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum)
|
||||
{
|
||||
assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
|
||||
return MI->tied_op_idx[OpNum] != -1;
|
||||
}
|
||||
|
||||
/// Returns the value of the @MCInst operand at index @OpNum.
|
||||
uint64_t MCInst_getOpVal(MCInst *MI, unsigned OpNum)
|
||||
{
|
||||
assert(OpNum < MAX_MC_OPS);
|
||||
MCOperand *op = MCInst_getOperand(MI, OpNum);
|
||||
if (MCOperand_isReg(op))
|
||||
return MCOperand_getReg(op);
|
||||
else if (MCOperand_isImm(op))
|
||||
return MCOperand_getImm(op);
|
||||
else
|
||||
assert(0 && "Operand type not handled in this getter.");
|
||||
return MCOperand_getImm(op);
|
||||
}
|
||||
|
||||
void MCInst_setIsAlias(MCInst *MI, bool Flag)
|
||||
{
|
||||
assert(MI);
|
||||
MI->isAliasInstr = Flag;
|
||||
MI->flat_insn->is_alias = Flag;
|
||||
}
|
||||
|
||||
/// @brief Copies the relevant members of a temporary MCInst to
|
||||
/// the main MCInst. This is used if TryDecode was run on a temporary MCInst.
|
||||
/// @param MI The main MCInst
|
||||
/// @param TmpMI The temporary MCInst.
|
||||
void MCInst_updateWithTmpMI(MCInst *MI, MCInst *TmpMI)
|
||||
{
|
||||
MI->size = TmpMI->size;
|
||||
MI->Opcode = TmpMI->Opcode;
|
||||
assert(MI->size < MAX_MC_OPS);
|
||||
memcpy(MI->Operands, TmpMI->Operands,
|
||||
sizeof(MI->Operands[0]) * MI->size);
|
||||
}
|
||||
|
||||
/// @brief Sets the softfail/illegal flag in the cs_insn.
|
||||
/// Setting it indicates the instruction can be decoded, but is invalid
|
||||
/// due to not allowed operands or an illegal context.
|
||||
///
|
||||
/// @param MI The MCInst holding the cs_insn currently decoded.
|
||||
void MCInst_setSoftFail(MCInst *MI)
|
||||
{
|
||||
assert(MI && MI->flat_insn);
|
||||
MI->flat_insn->illegal = true;
|
||||
}
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
//===-- llvm/MC/MCInst.h - MCInst class -------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the MCInst and MCOperand classes, which
|
||||
// is the basic representation used to represent low-level machine code
|
||||
// instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_MCINST_H
|
||||
#define CS_MCINST_H
|
||||
|
||||
#include "include/capstone/capstone.h"
|
||||
#include "MCAsmInfo.h"
|
||||
#include "MCInstrDesc.h"
|
||||
#include "MCRegisterInfo.h"
|
||||
|
||||
typedef struct MCInst MCInst;
|
||||
typedef struct cs_struct cs_struct;
|
||||
typedef struct MCOperand MCOperand;
|
||||
typedef void MCExpr;
|
||||
|
||||
/// MCOperand - Instances of this class represent operands of the MCInst class.
|
||||
/// This is a simple discriminated union.
|
||||
struct MCOperand {
|
||||
enum {
|
||||
kInvalid = 0, ///< Uninitialized.
|
||||
kRegister, ///< Register operand.
|
||||
kImmediate, ///< Immediate operand.
|
||||
kFPImmediate, ///< Floating-point immediate operand.
|
||||
kDFPImmediate, ///< Double-Floating-point immediate operand.
|
||||
kExpr, ///< Relocatable immediate operand.
|
||||
kInst ///< Sub-instruction operand.
|
||||
} MachineOperandType;
|
||||
unsigned char Kind;
|
||||
|
||||
union {
|
||||
uint64_t RegVal;
|
||||
int64_t ImmVal;
|
||||
double FPImmVal;
|
||||
};
|
||||
};
|
||||
|
||||
bool MCOperand_isValid(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isReg(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isImm(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isFPImm(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isDFPImm(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isExpr(const MCOperand *op);
|
||||
|
||||
bool MCOperand_isInst(const MCOperand *op);
|
||||
|
||||
/// getReg - Returns the register number.
|
||||
unsigned MCOperand_getReg(const MCOperand *op);
|
||||
|
||||
/// setReg - Set the register number.
|
||||
void MCOperand_setReg(MCOperand *op, unsigned Reg);
|
||||
|
||||
int64_t MCOperand_getImm(const MCOperand *op);
|
||||
|
||||
void MCOperand_setImm(MCOperand *op, int64_t Val);
|
||||
|
||||
int64_t MCOperand_getExpr(const MCOperand *op);
|
||||
|
||||
double MCOperand_getFPImm(const MCOperand *op);
|
||||
|
||||
void MCOperand_setFPImm(MCOperand *op, double Val);
|
||||
|
||||
const MCInst *MCOperand_getInst(const MCOperand *op);
|
||||
|
||||
void MCOperand_setInst(MCOperand *op, const MCInst *Val);
|
||||
|
||||
// create Reg operand in the next slot
|
||||
void MCOperand_CreateReg0(MCInst *inst, unsigned Reg);
|
||||
|
||||
// create Reg operand use the last-unused slot
|
||||
MCOperand *MCOperand_CreateReg1(MCInst *inst, unsigned Reg);
|
||||
|
||||
// create Imm operand in the next slot
|
||||
void MCOperand_CreateImm0(MCInst *inst, int64_t Val);
|
||||
|
||||
// create Imm operand in the last-unused slot
|
||||
MCOperand *MCOperand_CreateImm1(MCInst *inst, int64_t Val);
|
||||
|
||||
#define MAX_MC_OPS 48
|
||||
|
||||
/// MCInst - Instances of this class represent a single low-level machine
|
||||
/// instruction.
|
||||
struct MCInst {
|
||||
unsigned OpcodePub; // public opcode (<arch>_INS_yyy in header files <arch>.h)
|
||||
uint8_t size; // number of operands
|
||||
bool has_imm; // indicate this instruction has an X86_OP_IMM operand - used for ATT syntax
|
||||
uint8_t op1_size; // size of 1st operand - for X86 Intel syntax
|
||||
unsigned Opcode; // private opcode
|
||||
MCOperand Operands[MAX_MC_OPS];
|
||||
cs_insn *flat_insn; // insn to be exposed to public
|
||||
uint64_t address; // address of this insn
|
||||
cs_struct *csh; // save the main csh
|
||||
uint8_t x86opsize; // opsize for [mem] operand
|
||||
|
||||
// These flags could be used to pass some info from one target subcomponent
|
||||
// to another, for example, from disassembler to asm printer. The values of
|
||||
// the flags have any sense on target level only (e.g. prefixes on x86).
|
||||
unsigned flags;
|
||||
|
||||
// (Optional) instruction prefix, which can be up to 4 bytes.
|
||||
// A prefix byte gets value 0 when irrelevant.
|
||||
// This is copied from cs_x86 struct
|
||||
uint8_t x86_prefix[4];
|
||||
uint8_t imm_size; // immediate size for X86_OP_IMM operand
|
||||
bool writeback; // writeback for ARM
|
||||
int8_t tied_op_idx
|
||||
[MAX_MC_OPS]; ///< Tied operand indices. Index = Src op; Value: Dest op
|
||||
// operand access index for list of registers sharing the same access right (for ARM)
|
||||
uint8_t ac_idx;
|
||||
uint8_t popcode_adjust; // Pseudo X86 instruction adjust
|
||||
char assembly[8]; // for special instruction, so that we don't need printer
|
||||
unsigned char evm_data[32]; // for EVM PUSH operand
|
||||
cs_wasm_op wasm_data; // for WASM operand
|
||||
MCRegisterInfo *MRI;
|
||||
uint8_t xAcquireRelease; // X86 xacquire/xrelease
|
||||
uint8_t x86Lock; // Set when the X86 LOCK prefix is present
|
||||
bool isAliasInstr; // Flag if this MCInst is an alias.
|
||||
bool fillDetailOps; // If set, detail->operands gets filled.
|
||||
hppa_ext hppa_ext; ///< for HPPA operand. Contains info about modifiers and their effect on the instruction
|
||||
MCAsmInfo MAI; ///< The equivalent to MCAsmInfo in LLVM. It holds flags relevant for the asm style to print.
|
||||
};
|
||||
|
||||
void MCInst_Init(MCInst *inst, cs_arch arch);
|
||||
|
||||
void MCInst_clear(MCInst *inst);
|
||||
|
||||
// do not free operand after inserting
|
||||
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op);
|
||||
|
||||
void MCInst_setOpcode(MCInst *inst, unsigned Op);
|
||||
|
||||
unsigned MCInst_getOpcode(const MCInst *);
|
||||
|
||||
void MCInst_setOpcodePub(MCInst *inst, unsigned Op);
|
||||
|
||||
unsigned MCInst_getOpcodePub(const MCInst *);
|
||||
|
||||
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i);
|
||||
|
||||
unsigned MCInst_getNumOperands(const MCInst *inst);
|
||||
|
||||
// This addOperand2 function doesn't free Op
|
||||
void MCInst_addOperand2(MCInst *inst, MCOperand *Op);
|
||||
|
||||
bool MCInst_isPredicable(const MCInstrDesc *MIDesc);
|
||||
|
||||
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDescTable,
|
||||
unsigned tbl_size);
|
||||
|
||||
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
uint64_t MCInst_getOpVal(MCInst *MI, unsigned OpNum);
|
||||
|
||||
void MCInst_setIsAlias(MCInst *MI, bool Flag);
|
||||
|
||||
static inline bool MCInst_isAlias(const MCInst *MI)
|
||||
{
|
||||
return MI->isAliasInstr;
|
||||
}
|
||||
|
||||
void MCInst_updateWithTmpMI(MCInst *MI, MCInst *TmpMI);
|
||||
|
||||
void MCInst_setSoftFail(MCInst *MI);
|
||||
|
||||
#endif
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Rot127 <unisono@quyllur.org>, 2023 */
|
||||
|
||||
#include "MCInstPrinter.h"
|
||||
#include "cs_priv.h"
|
||||
#include <capstone/platform.h>
|
||||
|
||||
extern bool ARM_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
extern bool PPC_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
extern bool Mips_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
extern bool AArch64_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
extern bool TriCore_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
extern bool Sparc_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
extern bool RISCV_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
|
||||
static bool testFeatureBits(const MCInst *MI, uint32_t Value)
|
||||
{
|
||||
assert(MI && MI->csh);
|
||||
switch (MI->csh->arch) {
|
||||
default:
|
||||
assert(0 && "Not implemented for current arch.");
|
||||
return false;
|
||||
#ifdef CAPSTONE_HAS_ARM
|
||||
case CS_ARCH_ARM:
|
||||
return ARM_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
#ifdef CAPSTONE_HAS_POWERPC
|
||||
case CS_ARCH_PPC:
|
||||
return PPC_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
#ifdef CAPSTONE_HAS_MIPS
|
||||
case CS_ARCH_MIPS:
|
||||
return Mips_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
#ifdef CAPSTONE_HAS_AARCH64
|
||||
case CS_ARCH_AARCH64:
|
||||
return AArch64_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
#ifdef CAPSTONE_HAS_TRICORE
|
||||
case CS_ARCH_TRICORE:
|
||||
return TriCore_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
#ifdef CAPSTONE_HAS_SPARC
|
||||
case CS_ARCH_SPARC:
|
||||
return Sparc_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
#ifdef CAPSTONE_HAS_RISCV
|
||||
case CS_ARCH_RISCV:
|
||||
return RISCV_getFeatureBits(MI->csh->mode, Value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchAliasCondition(MCInst *MI, const MCRegisterInfo *MRI,
|
||||
unsigned *OpIdx, const AliasMatchingData *M,
|
||||
const AliasPatternCond *C,
|
||||
bool *OrPredicateResult)
|
||||
{
|
||||
// Feature tests are special, they don't consume operands.
|
||||
if (C->Kind == AliasPatternCond_K_Feature)
|
||||
return testFeatureBits(MI, C->Value);
|
||||
if (C->Kind == AliasPatternCond_K_NegFeature)
|
||||
return !testFeatureBits(MI, C->Value);
|
||||
// For feature tests where just one feature is required in a list, set the
|
||||
// predicate result bit to whether the expression will return true, and only
|
||||
// return the real result at the end of list marker.
|
||||
if (C->Kind == AliasPatternCond_K_OrFeature) {
|
||||
*OrPredicateResult |= testFeatureBits(MI, C->Value);
|
||||
return true;
|
||||
}
|
||||
if (C->Kind == AliasPatternCond_K_OrNegFeature) {
|
||||
*OrPredicateResult |= !(testFeatureBits(MI, C->Value));
|
||||
return true;
|
||||
}
|
||||
if (C->Kind == AliasPatternCond_K_EndOrFeatures) {
|
||||
bool Res = *OrPredicateResult;
|
||||
*OrPredicateResult = false;
|
||||
return Res;
|
||||
}
|
||||
|
||||
// Get and consume an operand.
|
||||
MCOperand *Opnd = MCInst_getOperand(MI, *OpIdx);
|
||||
++(*OpIdx);
|
||||
|
||||
// Check the specific condition for the operand.
|
||||
switch (C->Kind) {
|
||||
default:
|
||||
assert(0 && "invalid kind");
|
||||
case AliasPatternCond_K_Imm:
|
||||
// Operand must be a specific immediate.
|
||||
return MCOperand_isImm(Opnd) &&
|
||||
MCOperand_getImm(Opnd) == (int32_t)C->Value;
|
||||
case AliasPatternCond_K_Reg:
|
||||
// Operand must be a specific register.
|
||||
return MCOperand_isReg(Opnd) &&
|
||||
MCOperand_getReg(Opnd) == C->Value;
|
||||
case AliasPatternCond_K_TiedReg:
|
||||
// Operand must match the register of another operand.
|
||||
return MCOperand_isReg(Opnd) &&
|
||||
MCOperand_getReg(Opnd) ==
|
||||
MCOperand_getReg(
|
||||
MCInst_getOperand(MI, C->Value));
|
||||
case AliasPatternCond_K_RegClass:
|
||||
// Operand must be a register in this class. Value is a register class
|
||||
// id.
|
||||
return MCOperand_isReg(Opnd) &&
|
||||
MCRegisterClass_contains(
|
||||
MCRegisterInfo_getRegClass(MRI, C->Value),
|
||||
MCOperand_getReg(Opnd));
|
||||
case AliasPatternCond_K_Custom:
|
||||
// Operand must match some custom criteria.
|
||||
assert(M->ValidateMCOperand &&
|
||||
"A custom validator should be set but isn't.");
|
||||
return M->ValidateMCOperand(Opnd, C->Value);
|
||||
case AliasPatternCond_K_Ignore:
|
||||
// Operand can be anything.
|
||||
return true;
|
||||
case AliasPatternCond_K_Feature:
|
||||
case AliasPatternCond_K_NegFeature:
|
||||
case AliasPatternCond_K_OrFeature:
|
||||
case AliasPatternCond_K_OrNegFeature:
|
||||
case AliasPatternCond_K_EndOrFeatures:
|
||||
assert(0 && "handled earlier");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if PatternsForOpcode is all zero.
|
||||
static inline bool validOpToPatter(const PatternsForOpcode *P)
|
||||
{
|
||||
return !(P->Opcode == 0 && P->PatternStart == 0 && P->NumPatterns == 0);
|
||||
}
|
||||
|
||||
const char *matchAliasPatterns(MCInst *MI, const AliasMatchingData *M)
|
||||
{
|
||||
// TODO Rewrite to C
|
||||
|
||||
// auto It = lower_bound(M.OpToPatterns, MI->getOpcode(),
|
||||
// [](const PatternsForOpcode &L, unsigned Opcode) {
|
||||
// return L.Opcode < Opcode;
|
||||
// });
|
||||
// if (It == M.OpToPatterns.end() || It->Opcode != MI->getOpcode())
|
||||
// return nullptr;
|
||||
|
||||
// Binary search by opcode. Return false if there are no aliases for this
|
||||
// opcode.
|
||||
unsigned MIOpcode = MI->Opcode;
|
||||
size_t i = 0;
|
||||
uint32_t PatternOpcode = M->OpToPatterns[i].Opcode;
|
||||
while (PatternOpcode < MIOpcode && validOpToPatter(&M->OpToPatterns[i]))
|
||||
PatternOpcode = M->OpToPatterns[++i].Opcode;
|
||||
if (PatternOpcode != MI->Opcode ||
|
||||
!validOpToPatter(&M->OpToPatterns[i]))
|
||||
return NULL;
|
||||
|
||||
// // Try all patterns for this opcode.
|
||||
uint32_t AsmStrOffset = ~0U;
|
||||
const AliasPattern *Patterns =
|
||||
M->Patterns + M->OpToPatterns[i].PatternStart;
|
||||
for (const AliasPattern *P = Patterns;
|
||||
P != Patterns + M->OpToPatterns[i].NumPatterns; ++P) {
|
||||
// Check operand count first.
|
||||
if (MCInst_getNumOperands(MI) != P->NumOperands)
|
||||
return NULL;
|
||||
|
||||
// Test all conditions for this pattern.
|
||||
const AliasPatternCond *Conds =
|
||||
M->PatternConds + P->AliasCondStart;
|
||||
unsigned OpIdx = 0;
|
||||
bool OrPredicateResult = false;
|
||||
bool allMatch = true;
|
||||
for (const AliasPatternCond *C = Conds;
|
||||
C != Conds + P->NumConds; ++C) {
|
||||
if (!matchAliasCondition(MI, MI->MRI, &OpIdx, M, C,
|
||||
&OrPredicateResult)) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allMatch) {
|
||||
AsmStrOffset = P->AsmStrOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If no alias matched, don't print an alias.
|
||||
if (AsmStrOffset == ~0U)
|
||||
return NULL;
|
||||
|
||||
// Go to offset AsmStrOffset and use the null terminated string there. The
|
||||
// offset should point to the beginning of an alias string, so it should
|
||||
// either be zero or be preceded by a null byte.
|
||||
return M->AsmStrings + AsmStrOffset;
|
||||
}
|
||||
|
||||
// TODO Add functionality to toggle the flag.
|
||||
bool getUseMarkup(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Utility functions to make adding mark ups simpler.
|
||||
const char *markup(const char *s)
|
||||
{
|
||||
static const char *no_markup = "";
|
||||
if (getUseMarkup())
|
||||
return s;
|
||||
else
|
||||
return no_markup;
|
||||
}
|
||||
|
||||
// binary search for encoding in IndexType array
|
||||
// return -1 if not found, or index if found
|
||||
unsigned int binsearch_IndexTypeEncoding(const struct IndexType *index,
|
||||
size_t size, uint16_t encoding)
|
||||
{
|
||||
// binary searching since the index is sorted in encoding order
|
||||
size_t left, right, m;
|
||||
|
||||
right = size - 1;
|
||||
|
||||
if (encoding < index[0].encoding || encoding > index[right].encoding)
|
||||
// not found
|
||||
return -1;
|
||||
|
||||
left = 0;
|
||||
|
||||
while (left <= right) {
|
||||
m = (left + right) / 2;
|
||||
if (encoding == index[m].encoding) {
|
||||
// LLVM actually uses lower_bound for the index table search
|
||||
// Here we need to check if a previous entry is of the same encoding
|
||||
// and return the first one.
|
||||
while (m > 0 && encoding == index[m - 1].encoding)
|
||||
--m;
|
||||
return m;
|
||||
}
|
||||
|
||||
if (encoding < index[m].encoding)
|
||||
right = m - 1;
|
||||
else
|
||||
left = m + 1;
|
||||
}
|
||||
|
||||
// not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
// binary search for encoding in IndexTypeStr array
|
||||
// return -1 if not found, or index if found
|
||||
unsigned int binsearch_IndexTypeStrEncoding(const struct IndexTypeStr *index,
|
||||
size_t size, const char *name)
|
||||
{
|
||||
// binary searching since the index is sorted in encoding order
|
||||
size_t left, right, m;
|
||||
|
||||
right = size - 1;
|
||||
|
||||
int str_left_cmp = strcmp(name, index[0].name);
|
||||
int str_right_cmp = strcmp(name, index[right].name);
|
||||
if (str_left_cmp < 0 || str_right_cmp > 0)
|
||||
// not found
|
||||
return -1;
|
||||
|
||||
left = 0;
|
||||
|
||||
while (left <= right) {
|
||||
m = (left + right) / 2;
|
||||
if (strcmp(name, index[m].name) == 0) {
|
||||
// LLVM actually uses lower_bound for the index table search
|
||||
// Here we need to check if a previous entry is of the same encoding
|
||||
// and return the first one.
|
||||
while (m > 0 && (strcmp(name, index[m - 1].name) == 0))
|
||||
--m;
|
||||
return m;
|
||||
}
|
||||
|
||||
if (strcmp(name, index[m].name) < 0)
|
||||
right = m - 1;
|
||||
else
|
||||
left = m + 1;
|
||||
}
|
||||
|
||||
// not found
|
||||
return -1;
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Rot127 <unisono@quyllur.org>, 2023 */
|
||||
|
||||
#ifndef CS_MCINSTPRINTER_H
|
||||
#define CS_MCINSTPRINTER_H
|
||||
|
||||
#include "MCInst.h"
|
||||
#include <assert.h>
|
||||
#include <capstone/platform.h>
|
||||
|
||||
/// Returned by getMnemonic() of the AsmPrinters.
|
||||
typedef struct {
|
||||
const char *first; // Mnemonic
|
||||
uint64_t second; // Bits
|
||||
} MnemonicBitsInfo;
|
||||
|
||||
/// Map from opcode to pattern list by binary search.
|
||||
typedef struct {
|
||||
uint32_t Opcode;
|
||||
uint16_t PatternStart;
|
||||
uint16_t NumPatterns;
|
||||
} PatternsForOpcode;
|
||||
|
||||
/// Data for each alias pattern. Includes feature bits, string, number of
|
||||
/// operands, and a variadic list of conditions to check.
|
||||
typedef struct {
|
||||
uint32_t AsmStrOffset;
|
||||
uint32_t AliasCondStart;
|
||||
uint8_t NumOperands;
|
||||
uint8_t NumConds;
|
||||
} AliasPattern;
|
||||
|
||||
typedef enum {
|
||||
AliasPatternCond_K_Feature, // Match only if a feature is enabled.
|
||||
AliasPatternCond_K_NegFeature, // Match only if a feature is disabled.
|
||||
AliasPatternCond_K_OrFeature, // Match only if one of a set of features is
|
||||
// enabled.
|
||||
AliasPatternCond_K_OrNegFeature, // Match only if one of a set of features
|
||||
// is disabled.
|
||||
AliasPatternCond_K_EndOrFeatures, // Note end of list of K_Or(Neg)?Features.
|
||||
AliasPatternCond_K_Ignore, // Match any operand.
|
||||
AliasPatternCond_K_Reg, // Match a specific register.
|
||||
AliasPatternCond_K_TiedReg, // Match another already matched register.
|
||||
AliasPatternCond_K_Imm, // Match a specific immediate.
|
||||
AliasPatternCond_K_RegClass, // Match registers in a class.
|
||||
AliasPatternCond_K_Custom, // Call custom matcher by index.
|
||||
} AliasPatternCond_CondKind;
|
||||
|
||||
typedef struct {
|
||||
AliasPatternCond_CondKind Kind;
|
||||
uint32_t Value;
|
||||
} AliasPatternCond;
|
||||
|
||||
typedef bool (*ValidateMCOperandFunc)(const MCOperand *MCOp,
|
||||
unsigned PredicateIndex);
|
||||
|
||||
/// Tablegenerated data structures needed to match alias patterns.
|
||||
typedef struct {
|
||||
const PatternsForOpcode *OpToPatterns;
|
||||
const AliasPattern *Patterns;
|
||||
const AliasPatternCond *PatternConds;
|
||||
const char *AsmStrings;
|
||||
const ValidateMCOperandFunc ValidateMCOperand;
|
||||
} AliasMatchingData;
|
||||
|
||||
const char *matchAliasPatterns(MCInst *MI, const AliasMatchingData *M);
|
||||
bool getUseMarkup(void);
|
||||
const char *markup(const char *s);
|
||||
|
||||
struct IndexType {
|
||||
uint16_t encoding;
|
||||
unsigned index;
|
||||
};
|
||||
|
||||
struct IndexTypeStr {
|
||||
const char *name;
|
||||
unsigned index;
|
||||
};
|
||||
|
||||
// binary search for encoding in IndexType array
|
||||
// return -1 if not found, or index if found
|
||||
unsigned int binsearch_IndexTypeEncoding(const struct IndexType *index,
|
||||
size_t size, uint16_t encoding);
|
||||
unsigned int binsearch_IndexTypeStrEncoding(const struct IndexTypeStr *index,
|
||||
size_t size, const char *name);
|
||||
|
||||
#endif // CS_MCINSTPRINTER_H
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include "MCInstrDesc.h"
|
||||
|
||||
/// isPredicate - Set if this is one of the operands that made up of
|
||||
/// the predicate operand that controls an isPredicable() instruction.
|
||||
bool MCOperandInfo_isPredicate(const MCOperandInfo *m)
|
||||
{
|
||||
return m->Flags & (1 << MCOI_Predicate);
|
||||
}
|
||||
|
||||
/// isOptionalDef - Set if this operand is a optional def.
|
||||
///
|
||||
bool MCOperandInfo_isOptionalDef(const MCOperandInfo *m)
|
||||
{
|
||||
return m->Flags & (1 << MCOI_OptionalDef);
|
||||
}
|
||||
|
||||
/// Checks if operand is tied to another one.
|
||||
bool MCOperandInfo_isTiedToOp(const MCOperandInfo *m)
|
||||
{
|
||||
if (m->Constraints & (1 << MCOI_TIED_TO))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns the value of the specified operand constraint if
|
||||
/// it is present. Returns -1 if it is not present.
|
||||
int MCOperandInfo_getOperandConstraint(const MCInstrDesc *InstrDesc,
|
||||
unsigned OpNum,
|
||||
MCOI_OperandConstraint Constraint)
|
||||
{
|
||||
const MCOperandInfo OpInfo = InstrDesc->OpInfo[OpNum];
|
||||
if (OpNum < InstrDesc->NumOperands &&
|
||||
(OpInfo.Constraints & (1 << Constraint))) {
|
||||
unsigned ValuePos = 4 + Constraint * 4;
|
||||
return (OpInfo.Constraints >> ValuePos) & 0xf;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Returns the instruction description for the given MCInst opcode.
|
||||
/// Function should be called like:
|
||||
/// MCInstrDesc_get(MCInst_getOpcode(MI), ARCHInstDesc, ARR_SIZE(ARCHInstDesc));
|
||||
const MCInstrDesc *MCInstrDesc_get(unsigned opcode, const MCInstrDesc *table,
|
||||
unsigned tbl_size)
|
||||
{
|
||||
return &table[tbl_size - 1 - opcode];
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
//===-- llvm/MC/MCInstrDesc.h - Instruction Descriptors -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the MCOperandInfo and MCInstrDesc classes, which
|
||||
// are used to describe target instructions and their operands.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_MC_MCINSTRDESC_H
|
||||
#define CS_LLVM_MC_MCINSTRDESC_H
|
||||
|
||||
#include "MCRegisterInfo.h"
|
||||
#include "capstone/platform.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Machine Operand Flags and Description
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Operand constraints. These are encoded in 16 bits with one of the
|
||||
/// low-order 3 bits specifying that a constraint is present and the
|
||||
/// corresponding high-order hex digit specifying the constraint value.
|
||||
/// This allows for a maximum of 3 constraints.
|
||||
typedef enum {
|
||||
MCOI_TIED_TO = 0, // Operand tied to another operand.
|
||||
MCOI_EARLY_CLOBBER // Operand is an early clobber register operand
|
||||
} MCOI_OperandConstraint;
|
||||
|
||||
// Define a macro to produce each constraint value.
|
||||
#define CONSTRAINT_MCOI_TIED_TO(op) \
|
||||
((1 << MCOI_TIED_TO) | ((op) << (4 + MCOI_TIED_TO * 4)))
|
||||
|
||||
#define CONSTRAINT_MCOI_EARLY_CLOBBER (1 << MCOI_EARLY_CLOBBER)
|
||||
|
||||
/// OperandFlags - These are flags set on operands, but should be considered
|
||||
/// private, all access should go through the MCOperandInfo accessors.
|
||||
/// See the accessors for a description of what these are.
|
||||
enum MCOI_OperandFlags {
|
||||
MCOI_LookupPtrRegClass = 0,
|
||||
MCOI_Predicate,
|
||||
MCOI_OptionalDef
|
||||
};
|
||||
|
||||
/// Operand Type - Operands are tagged with one of the values of this enum.
|
||||
enum MCOI_OperandType {
|
||||
MCOI_OPERAND_UNKNOWN = 0,
|
||||
MCOI_OPERAND_IMMEDIATE = 1,
|
||||
MCOI_OPERAND_REGISTER = 2,
|
||||
MCOI_OPERAND_MEMORY = 3,
|
||||
MCOI_OPERAND_PCREL = 4,
|
||||
|
||||
MCOI_OPERAND_FIRST_GENERIC = 6,
|
||||
MCOI_OPERAND_GENERIC_0 = 6,
|
||||
MCOI_OPERAND_GENERIC_1 = 7,
|
||||
MCOI_OPERAND_GENERIC_2 = 8,
|
||||
MCOI_OPERAND_GENERIC_3 = 9,
|
||||
MCOI_OPERAND_GENERIC_4 = 10,
|
||||
MCOI_OPERAND_GENERIC_5 = 11,
|
||||
MCOI_OPERAND_LAST_GENERIC = 11,
|
||||
|
||||
MCOI_OPERAND_FIRST_GENERIC_IMM = 12,
|
||||
MCOI_OPERAND_GENERIC_IMM_0 = 12,
|
||||
MCOI_OPERAND_LAST_GENERIC_IMM = 12,
|
||||
|
||||
MCOI_OPERAND_FIRST_TARGET = 13,
|
||||
};
|
||||
|
||||
/// MCOperandInfo - This holds information about one operand of a machine
|
||||
/// instruction, indicating the register class for register operands, etc.
|
||||
///
|
||||
typedef struct MCOperandInfo {
|
||||
/// This specifies the register class enumeration of the operand
|
||||
/// if the operand is a register. If isLookupPtrRegClass is set, then this is
|
||||
/// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to
|
||||
/// get a dynamic register class.
|
||||
int16_t RegClass;
|
||||
|
||||
/// These are flags from the MCOI::OperandFlags enum.
|
||||
uint8_t Flags;
|
||||
|
||||
/// Information about the type of the operand.
|
||||
uint8_t OperandType;
|
||||
|
||||
/// The lower 3 bits are used to specify which constraints are set.
|
||||
/// The higher 13 bits are used to specify the value of constraints (4 bits each).
|
||||
uint16_t Constraints;
|
||||
/// Currently no other information.
|
||||
} MCOperandInfo;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Machine Instruction Flags and Description
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// MCInstrDesc flags - These should be considered private to the
|
||||
/// implementation of the MCInstrDesc class. Clients should use the predicate
|
||||
/// methods on MCInstrDesc, not use these directly. These all correspond to
|
||||
/// bitfields in the MCInstrDesc::Flags field.
|
||||
enum {
|
||||
MCID_Variadic = 0,
|
||||
MCID_HasOptionalDef,
|
||||
MCID_Pseudo,
|
||||
MCID_Return,
|
||||
MCID_Call,
|
||||
MCID_Barrier,
|
||||
MCID_Terminator,
|
||||
MCID_Branch,
|
||||
MCID_IndirectBranch,
|
||||
MCID_Compare,
|
||||
MCID_MoveImm,
|
||||
MCID_MoveReg,
|
||||
MCID_Bitcast,
|
||||
MCID_Select,
|
||||
MCID_DelaySlot,
|
||||
MCID_FoldableAsLoad,
|
||||
MCID_MayLoad,
|
||||
MCID_MayStore,
|
||||
MCID_Predicable,
|
||||
MCID_NotDuplicable,
|
||||
MCID_UnmodeledSideEffects,
|
||||
MCID_Commutable,
|
||||
MCID_ConvertibleTo3Addr,
|
||||
MCID_UsesCustomInserter,
|
||||
MCID_HasPostISelHook,
|
||||
MCID_Rematerializable,
|
||||
MCID_CheapAsAMove,
|
||||
MCID_ExtraSrcRegAllocReq,
|
||||
MCID_ExtraDefRegAllocReq,
|
||||
MCID_RegSequence,
|
||||
MCID_ExtractSubreg,
|
||||
MCID_InsertSubreg,
|
||||
MCID_Convergent,
|
||||
MCID_Add,
|
||||
MCID_Trap,
|
||||
};
|
||||
|
||||
/// MCInstrDesc - Describe properties that are true of each instruction in the
|
||||
/// target description file. This captures information about side effects,
|
||||
/// register use and many other things. There is one instance of this struct
|
||||
/// for each target instruction class, and the MachineInstr class points to
|
||||
/// this struct directly to describe itself.
|
||||
typedef struct MCInstrDesc {
|
||||
unsigned char NumOperands; // Num of args (may be more if variable_ops)
|
||||
const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands
|
||||
} MCInstrDesc;
|
||||
|
||||
bool MCOperandInfo_isPredicate(const MCOperandInfo *m);
|
||||
|
||||
bool MCOperandInfo_isOptionalDef(const MCOperandInfo *m);
|
||||
|
||||
bool MCOperandInfo_isTiedToOp(const MCOperandInfo *m);
|
||||
|
||||
int MCOperandInfo_getOperandConstraint(const MCInstrDesc *OpInfo,
|
||||
unsigned OpNum,
|
||||
MCOI_OperandConstraint Constraint);
|
||||
const MCInstrDesc *MCInstrDesc_get(unsigned opcode, const MCInstrDesc *table,
|
||||
unsigned tbl_size);
|
||||
|
||||
#endif
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
//=== MC/MCRegisterInfo.cpp - Target Register Description -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements MCRegisterInfo functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include "MCRegisterInfo.h"
|
||||
|
||||
/// DiffListIterator - Base iterator class that can traverse the
|
||||
/// differentially encoded register and regunit lists in DiffLists.
|
||||
/// Don't use this class directly, use one of the specialized sub-classes
|
||||
/// defined below.
|
||||
typedef struct DiffListIterator {
|
||||
uint16_t Val;
|
||||
const MCPhysReg *List;
|
||||
} DiffListIterator;
|
||||
|
||||
void MCRegisterInfo_InitMCRegisterInfo(MCRegisterInfo *RI,
|
||||
const MCRegisterDesc *D, unsigned NR,
|
||||
unsigned RA, unsigned PC,
|
||||
const MCRegisterClass *C, unsigned NC,
|
||||
uint16_t (*RURoots)[2], unsigned NRU,
|
||||
const MCPhysReg *DL, const char *Strings,
|
||||
const uint16_t *SubIndices,
|
||||
unsigned NumIndices, const uint16_t *RET)
|
||||
{
|
||||
RI->Desc = D;
|
||||
RI->NumRegs = NR;
|
||||
RI->RAReg = RA;
|
||||
RI->PCReg = PC;
|
||||
RI->Classes = C;
|
||||
RI->DiffLists = DL;
|
||||
RI->RegStrings = Strings;
|
||||
RI->NumClasses = NC;
|
||||
RI->RegUnitRoots = RURoots;
|
||||
RI->NumRegUnits = NRU;
|
||||
RI->SubRegIndices = SubIndices;
|
||||
RI->NumSubRegIndices = NumIndices;
|
||||
RI->RegEncodingTable = RET;
|
||||
}
|
||||
|
||||
static void DiffListIterator_init(DiffListIterator *d, MCPhysReg InitVal,
|
||||
const MCPhysReg *DiffList)
|
||||
{
|
||||
d->Val = InitVal;
|
||||
d->List = DiffList;
|
||||
}
|
||||
|
||||
static uint16_t DiffListIterator_getVal(DiffListIterator *d)
|
||||
{
|
||||
return d->Val;
|
||||
}
|
||||
|
||||
static bool DiffListIterator_next(DiffListIterator *d)
|
||||
{
|
||||
MCPhysReg D;
|
||||
|
||||
if (d->List == 0)
|
||||
return false;
|
||||
|
||||
D = *d->List;
|
||||
d->List++;
|
||||
d->Val += D;
|
||||
|
||||
if (!D)
|
||||
d->List = 0;
|
||||
|
||||
return (D != 0);
|
||||
}
|
||||
|
||||
static bool DiffListIterator_isValid(DiffListIterator *d)
|
||||
{
|
||||
return (d->List != 0);
|
||||
}
|
||||
|
||||
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI,
|
||||
unsigned Reg, unsigned SubIdx,
|
||||
const MCRegisterClass *RC)
|
||||
{
|
||||
DiffListIterator iter;
|
||||
|
||||
if (Reg >= RI->NumRegs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DiffListIterator_init(&iter, (MCPhysReg)Reg,
|
||||
RI->DiffLists + RI->Desc[Reg].SuperRegs);
|
||||
DiffListIterator_next(&iter);
|
||||
|
||||
while (DiffListIterator_isValid(&iter)) {
|
||||
uint16_t val = DiffListIterator_getVal(&iter);
|
||||
if (MCRegisterClass_contains(RC, val) &&
|
||||
Reg == MCRegisterInfo_getSubReg(RI, val, SubIdx))
|
||||
return val;
|
||||
|
||||
DiffListIterator_next(&iter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg,
|
||||
unsigned Idx)
|
||||
{
|
||||
DiffListIterator iter;
|
||||
const uint16_t *SRI = RI->SubRegIndices + RI->Desc[Reg].SubRegIndices;
|
||||
|
||||
DiffListIterator_init(&iter, (MCPhysReg)Reg,
|
||||
RI->DiffLists + RI->Desc[Reg].SubRegs);
|
||||
DiffListIterator_next(&iter);
|
||||
|
||||
while (DiffListIterator_isValid(&iter)) {
|
||||
if (*SRI == Idx)
|
||||
return DiffListIterator_getVal(&iter);
|
||||
DiffListIterator_next(&iter);
|
||||
++SRI;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const MCRegisterClass *MCRegisterInfo_getRegClass(const MCRegisterInfo *RI,
|
||||
unsigned i)
|
||||
{
|
||||
//assert(i < getNumRegClasses() && "Register Class ID out of range");
|
||||
if (i >= RI->NumClasses)
|
||||
return 0;
|
||||
return &(RI->Classes[i]);
|
||||
}
|
||||
|
||||
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg)
|
||||
{
|
||||
unsigned InByte = 0;
|
||||
unsigned Byte = 0;
|
||||
|
||||
// Make sure that MCRegisterInfo_getRegClass didn't return 0
|
||||
// (for calls to GETREGCLASS_CONTAIN0)
|
||||
if (!c)
|
||||
return false;
|
||||
|
||||
InByte = Reg % 8;
|
||||
Byte = Reg / 8;
|
||||
|
||||
if (Byte >= c->RegSetSize)
|
||||
return false;
|
||||
|
||||
return (c->RegSet[Byte] & (1 << InByte)) != 0;
|
||||
}
|
||||
|
||||
unsigned MCRegisterClass_getRegister(const MCRegisterClass *c, unsigned RegNo)
|
||||
{
|
||||
return c->RegsBegin[RegNo];
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
//=== MC/MCRegisterInfo.h - Target Register Description ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file describes an abstract interface used to get information about a
|
||||
// target machines register file. This information is used for a variety of
|
||||
// purposed, especially register allocation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_MC_MCREGISTERINFO_H
|
||||
#define CS_LLVM_MC_MCREGISTERINFO_H
|
||||
|
||||
#include "capstone/platform.h"
|
||||
#include "SStream.h"
|
||||
|
||||
/// An unsigned integer type large enough to represent all physical registers,
|
||||
/// but not necessarily virtual registers.
|
||||
typedef int16_t MCPhysReg;
|
||||
typedef const MCPhysReg *iterator;
|
||||
typedef uint16_t MCRegister;
|
||||
|
||||
typedef struct MCRegisterClass2 {
|
||||
iterator RegsBegin;
|
||||
const uint8_t *RegSet;
|
||||
uint8_t RegsSize;
|
||||
uint8_t RegSetSize;
|
||||
} MCRegisterClass2;
|
||||
|
||||
typedef struct MCRegisterClass {
|
||||
iterator RegsBegin;
|
||||
const uint8_t *RegSet;
|
||||
uint16_t RegSetSize;
|
||||
} MCRegisterClass;
|
||||
|
||||
/// MCRegisterDesc - This record contains information about a particular
|
||||
/// register. The SubRegs field is a zero terminated array of registers that
|
||||
/// are sub-registers of the specific register, e.g. AL, AH are sub-registers
|
||||
/// of AX. The SuperRegs field is a zero terminated array of registers that are
|
||||
/// super-registers of AX.
|
||||
typedef struct MCRegisterDesc {
|
||||
uint32_t Name; // Printable name for the reg (for debugging)
|
||||
uint32_t SubRegs; // Sub-register set, described above
|
||||
uint32_t SuperRegs; // Super-register set, described above
|
||||
|
||||
// Offset into MCRI::SubRegIndices of a list of sub-register indices for each
|
||||
// sub-register in SubRegs.
|
||||
uint32_t SubRegIndices;
|
||||
|
||||
// RegUnits - Points to the list of register units. The low 4 bits holds the
|
||||
// Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator.
|
||||
uint32_t RegUnits;
|
||||
|
||||
/// Index into list with lane mask sequences. The sequence contains a lanemask
|
||||
/// for every register unit.
|
||||
uint16_t RegUnitLaneMasks; // ???
|
||||
} MCRegisterDesc;
|
||||
|
||||
/// MCRegisterInfo base class - We assume that the target defines a static
|
||||
/// array of MCRegisterDesc objects that represent all of the machine
|
||||
/// registers that the target has. As such, we simply have to track a pointer
|
||||
/// to this array so that we can turn register number into a register
|
||||
/// descriptor.
|
||||
///
|
||||
/// Note this class is designed to be a base class of TargetRegisterInfo, which
|
||||
/// is the interface used by codegen. However, specific targets *should never*
|
||||
/// specialize this class. MCRegisterInfo should only contain getters to access
|
||||
/// TableGen generated physical register data. It must not be extended with
|
||||
/// virtual methods.
|
||||
typedef struct MCRegisterInfo {
|
||||
const MCRegisterDesc *Desc; // Pointer to the descriptor array
|
||||
unsigned NumRegs; // Number of entries in the array
|
||||
unsigned RAReg; // Return address register
|
||||
unsigned PCReg; // Program counter register
|
||||
const MCRegisterClass *Classes; // Pointer to the regclass array
|
||||
unsigned NumClasses; // Number of entries in the array
|
||||
unsigned NumRegUnits; // Number of regunits.
|
||||
uint16_t (*RegUnitRoots)[2]; // Pointer to regunit root table.
|
||||
const MCPhysReg *DiffLists; // Pointer to the difflists array
|
||||
// const LaneBitmask *RegUnitMaskSequences; // Pointer to lane mask sequences
|
||||
const char *RegStrings; // Pointer to the string table.
|
||||
// const char *RegClassStrings; // Pointer to the class strings.
|
||||
const uint16_t *SubRegIndices; // Pointer to the subreg lookup
|
||||
// array.
|
||||
unsigned NumSubRegIndices; // Number of subreg indices.
|
||||
const uint16_t *RegEncodingTable; // Pointer to array of register
|
||||
// encodings.
|
||||
} MCRegisterInfo;
|
||||
|
||||
void MCRegisterInfo_InitMCRegisterInfo(
|
||||
MCRegisterInfo *RI, const MCRegisterDesc *D, unsigned NR, unsigned RA,
|
||||
unsigned PC, const MCRegisterClass *C, unsigned NC,
|
||||
uint16_t (*RURoots)[2], unsigned NRU, const MCPhysReg *DL,
|
||||
const char *Strings, const uint16_t *SubIndices, unsigned NumIndices,
|
||||
const uint16_t *RET);
|
||||
|
||||
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI,
|
||||
unsigned Reg, unsigned SubIdx,
|
||||
const MCRegisterClass *RC);
|
||||
|
||||
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg,
|
||||
unsigned Idx);
|
||||
|
||||
const MCRegisterClass *MCRegisterInfo_getRegClass(const MCRegisterInfo *RI,
|
||||
unsigned i);
|
||||
|
||||
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg);
|
||||
|
||||
unsigned MCRegisterClass_getRegister(const MCRegisterClass *c, unsigned i);
|
||||
|
||||
#endif
|
||||
+671
@@ -0,0 +1,671 @@
|
||||
# Capstone Disassembly Engine
|
||||
# By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014
|
||||
|
||||
include config.mk
|
||||
include pkgconfig.mk # package version
|
||||
include functions.mk
|
||||
|
||||
# Verbose output?
|
||||
V ?= 0
|
||||
|
||||
OS := $(shell uname)
|
||||
ifeq ($(OS),Darwin)
|
||||
LIBARCHS ?= x86_64 arm64
|
||||
PREFIX ?= /usr/local
|
||||
endif
|
||||
|
||||
ifeq ($(PKG_EXTRA),)
|
||||
PKG_VERSION = $(PKG_MAJOR).$(PKG_MINOR)
|
||||
else
|
||||
PKG_VERSION = $(PKG_MAJOR).$(PKG_MINOR).$(PKG_EXTRA)
|
||||
endif
|
||||
|
||||
ifeq ($(CROSS),)
|
||||
RANLIB ?= ranlib
|
||||
else ifeq ($(ANDROID), 1)
|
||||
CC = $(CROSS)/../../bin/clang
|
||||
AR = $(CROSS)/ar
|
||||
RANLIB = $(CROSS)/ranlib
|
||||
STRIP = $(CROSS)/strip
|
||||
else
|
||||
CC = $(CROSS)gcc
|
||||
AR = $(CROSS)ar
|
||||
RANLIB = $(CROSS)ranlib
|
||||
STRIP = $(CROSS)strip
|
||||
endif
|
||||
|
||||
ifeq ($(OS),OS/390)
|
||||
RANLIB = touch
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring yes,$(CAPSTONE_DIET)))
|
||||
CFLAGS ?= -Os
|
||||
CFLAGS += -DCAPSTONE_DIET
|
||||
else
|
||||
CFLAGS ?= -O3
|
||||
endif
|
||||
|
||||
# C99 has been enforced elsewhere like xcode
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
ifneq (,$(findstring yes,$(CAPSTONE_X86_ATT_DISABLE)))
|
||||
CFLAGS += -DCAPSTONE_X86_ATT_DISABLE
|
||||
endif
|
||||
|
||||
ifeq ($(CC),xlc)
|
||||
CFLAGS += -qcpluscmt -qkeyword=inline -qlanglvl=extc1x -Iinclude
|
||||
ifneq ($(OS),OS/390)
|
||||
CFLAGS += -fPIC
|
||||
endif
|
||||
else
|
||||
CFLAGS += -fPIC -Wall -Wwrite-strings -Wmissing-prototypes -Iinclude
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_USE_SYS_DYN_MEM),yes)
|
||||
CFLAGS += -DCAPSTONE_USE_SYS_DYN_MEM
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_HAS_OSXKERNEL), yes)
|
||||
CFLAGS += -DCAPSTONE_HAS_OSXKERNEL
|
||||
SDKROOT ?= $(shell xcodebuild -version -sdk macosx Path)
|
||||
CFLAGS += -mmacosx-version-min=10.5 \
|
||||
-isysroot$(SDKROOT) \
|
||||
-I$(SDKROOT)/System/Library/Frameworks/Kernel.framework/Headers \
|
||||
-mkernel \
|
||||
-fno-builtin
|
||||
endif
|
||||
|
||||
PREFIX ?= /usr
|
||||
DESTDIR ?=
|
||||
ifndef BUILDDIR
|
||||
BLDIR = .
|
||||
OBJDIR = .
|
||||
else
|
||||
BLDIR = $(abspath $(BUILDDIR))
|
||||
OBJDIR = $(BLDIR)/obj
|
||||
endif
|
||||
INCDIR ?= $(PREFIX)/include
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
LIBDIRARCH ?= lib
|
||||
# Uncomment the below line to installs x86_64 libs to lib64/ directory.
|
||||
# Or better, pass 'LIBDIRARCH=lib64' to 'make install/uninstall' via 'make.sh'.
|
||||
#LIBDIRARCH ?= lib64
|
||||
LIBDIR = $(DESTDIR)$(PREFIX)/$(LIBDIRARCH)
|
||||
BINDIR = $(DESTDIR)$(PREFIX)/bin
|
||||
|
||||
LIBDATADIR = $(LIBDIR)
|
||||
|
||||
# Don't redefine $LIBDATADIR when global environment variable
|
||||
# USE_GENERIC_LIBDATADIR is set. This is used by the pkgsrc framework.
|
||||
|
||||
ifndef USE_GENERIC_LIBDATADIR
|
||||
ifeq ($(UNAME_S), FreeBSD)
|
||||
LIBDATADIR = $(DESTDIR)$(PREFIX)/libdata
|
||||
endif
|
||||
ifeq ($(UNAME_S), DragonFly)
|
||||
LIBDATADIR = $(DESTDIR)$(PREFIX)/libdata
|
||||
endif
|
||||
endif
|
||||
|
||||
INSTALL_BIN ?= install
|
||||
INSTALL_DATA ?= $(INSTALL_BIN) -m0644
|
||||
INSTALL_LIB ?= $(INSTALL_BIN) -m0755
|
||||
|
||||
LIBNAME = capstone
|
||||
|
||||
|
||||
DEP_ARM =
|
||||
DEP_ARM += $(wildcard arch/ARM/ARM*.inc)
|
||||
|
||||
LIBOBJ_ARM =
|
||||
ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_ARM
|
||||
LIBSRC_ARM += $(wildcard arch/ARM/ARM*.c)
|
||||
LIBOBJ_ARM += $(LIBSRC_ARM:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_AARCH64 =
|
||||
DEP_AARCH64 += $(wildcard arch/AArch64/AArch64*.inc)
|
||||
|
||||
LIBOBJ_AARCH64 =
|
||||
ifneq (,$(findstring aarch64,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_ARM64
|
||||
CFLAGS += -DCAPSTONE_HAS_AARCH64
|
||||
LIBSRC_AARCH64 += $(wildcard arch/AArch64/AArch64*.c)
|
||||
LIBOBJ_AARCH64 += $(LIBSRC_AARCH64:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_M68K =
|
||||
DEP_M68K += $(wildcard arch/M68K/M68K*.inc)
|
||||
DEP_M68K += $(wildcard arch/M68K/M68K*.h)
|
||||
|
||||
LIBOBJ_M68K =
|
||||
ifneq (,$(findstring m68k,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_M68K
|
||||
LIBSRC_M68K += $(wildcard arch/M68K/M68K*.c)
|
||||
LIBOBJ_M68K += $(LIBSRC_M68K:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_MIPS =
|
||||
DEP_MIPS += $(wildcard arch/Mips/Mips*.inc)
|
||||
|
||||
LIBOBJ_MIPS =
|
||||
ifneq (,$(findstring mips,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_MIPS
|
||||
LIBSRC_MIPS += $(wildcard arch/Mips/Mips*.c)
|
||||
LIBOBJ_MIPS += $(LIBSRC_MIPS:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_SH = $(wildcard arch/SH/SH*.inc)
|
||||
|
||||
LIBOBJ_SH =
|
||||
ifneq (,$(findstring sh,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_SH
|
||||
LIBSRC_SH += $(wildcard arch/SH/SH*.c)
|
||||
LIBOBJ_SH += $(LIBSRC_SH:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_PPC =
|
||||
DEP_PPC += $(wildcard arch/PowerPC/PPC*.inc)
|
||||
|
||||
LIBOBJ_PPC =
|
||||
ifneq (,$(findstring powerpc,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_POWERPC
|
||||
LIBSRC_PPC += $(wildcard arch/PowerPC/PPC*.c)
|
||||
LIBOBJ_PPC += $(LIBSRC_PPC:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_SPARC =
|
||||
DEP_SPARC += $(wildcard arch/Sparc/Sparc*.inc)
|
||||
|
||||
LIBOBJ_SPARC =
|
||||
ifneq (,$(findstring sparc,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_SPARC
|
||||
LIBSRC_SPARC += $(wildcard arch/Sparc/Sparc*.c)
|
||||
LIBOBJ_SPARC += $(LIBSRC_SPARC:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_SYSZ =
|
||||
DEP_SYSZ += $(wildcard arch/SystemZ/SystemZ*.inc)
|
||||
|
||||
LIBOBJ_SYSZ =
|
||||
ifneq (,$(findstring systemz,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_SYSTEMZ
|
||||
LIBSRC_SYSZ += $(wildcard arch/SystemZ/SystemZ*.c)
|
||||
LIBOBJ_SYSZ += $(LIBSRC_SYSZ:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
# by default, we compile full X86 instruction sets
|
||||
X86_REDUCE =
|
||||
ifneq (,$(findstring yes,$(CAPSTONE_X86_REDUCE)))
|
||||
X86_REDUCE = _reduce
|
||||
CFLAGS += -DCAPSTONE_X86_REDUCE -Os
|
||||
endif
|
||||
|
||||
|
||||
DEP_X86 =
|
||||
DEP_X86 += $(wildcard arch/X86/X86*.inc)
|
||||
|
||||
LIBOBJ_X86 =
|
||||
ifneq (,$(findstring x86,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_X86
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86DisassemblerDecoder.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86Disassembler.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86InstPrinterCommon.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86IntelInstPrinter.o
|
||||
# assembly syntax is irrelevant in Diet mode, when this info is suppressed
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_DIET)))
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_X86_ATT_DISABLE)))
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86ATTInstPrinter.o
|
||||
endif
|
||||
endif
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86Mapping.o
|
||||
LIBOBJ_X86 += $(OBJDIR)/arch/X86/X86Module.o
|
||||
endif
|
||||
|
||||
|
||||
DEP_XCORE =
|
||||
DEP_XCORE += $(wildcard arch/XCore/XCore*.inc)
|
||||
|
||||
LIBOBJ_XCORE =
|
||||
ifneq (,$(findstring xcore,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_XCORE
|
||||
LIBSRC_XCORE += $(wildcard arch/XCore/XCore*.c)
|
||||
LIBOBJ_XCORE += $(LIBSRC_XCORE:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_TMS320C64X =
|
||||
DEP_TMS320C64X += $(wildcard arch/TMS320C64x/TMS320C64x*.inc)
|
||||
|
||||
LIBOBJ_TMS320C64X =
|
||||
ifneq (,$(findstring tms320c64x,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_TMS320C64X
|
||||
LIBSRC_TMS320C64X += $(wildcard arch/TMS320C64x/TMS320C64x*.c)
|
||||
LIBOBJ_TMS320C64X += $(LIBSRC_TMS320C64X:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_M680X =
|
||||
DEP_M680X += $(wildcard arch/M680X/*.inc)
|
||||
DEP_M680X += $(wildcard arch/M680X/M680X*.h)
|
||||
|
||||
LIBOBJ_M680X =
|
||||
ifneq (,$(findstring m680x,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_M680X
|
||||
LIBSRC_M680X += $(wildcard arch/M680X/*.c)
|
||||
LIBOBJ_M680X += $(LIBSRC_M680X:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_EVM =
|
||||
DEP_EVM += $(wildcard arch/EVM/EVM*.inc)
|
||||
|
||||
LIBOBJ_EVM =
|
||||
ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_EVM
|
||||
LIBSRC_EVM += $(wildcard arch/EVM/EVM*.c)
|
||||
LIBOBJ_EVM += $(LIBSRC_EVM:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_RISCV =
|
||||
DEP_RISCV += $(wildcard arch/RISCV/RISCV*.inc)
|
||||
|
||||
LIBOBJ_RISCV =
|
||||
ifneq (,$(findstring riscv,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_RISCV
|
||||
LIBSRC_RISCV += $(wildcard arch/RISCV/RISCV*.c)
|
||||
LIBOBJ_RISCV += $(LIBSRC_RISCV:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_WASM =
|
||||
DEP_WASM += $(wildcard arch/WASM/WASM*.inc)
|
||||
|
||||
LIBOBJ_WASM =
|
||||
ifneq (,$(findstring wasm,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_WASM
|
||||
LIBSRC_WASM += $(wildcard arch/WASM/WASM*.c)
|
||||
LIBOBJ_WASM += $(LIBSRC_WASM:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_MOS65XX =
|
||||
DEP_MOS65XX += $(wildcard arch/MOS65XX/MOS65XX*.inc)
|
||||
|
||||
LIBOBJ_MOS65XX =
|
||||
ifneq (,$(findstring mos65xx,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_MOS65XX
|
||||
LIBSRC_MOS65XX += $(wildcard arch/MOS65XX/MOS65XX*.c)
|
||||
LIBOBJ_MOS65XX += $(LIBSRC_MOS65XX:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
|
||||
DEP_BPF =
|
||||
DEP_BPF += $(wildcard arch/BPF/BPF*.inc)
|
||||
|
||||
LIBOBJ_BPF =
|
||||
ifneq (,$(findstring bpf,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_BPF
|
||||
LIBSRC_BPF += $(wildcard arch/BPF/BPF*.c)
|
||||
LIBOBJ_BPF += $(LIBSRC_BPF:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_TRICORE =
|
||||
DEP_TRICORE +=$(wildcard arch/TriCore/TriCore*.inc)
|
||||
|
||||
LIBOBJ_TRICORE =
|
||||
ifneq (,$(findstring tricore,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_TRICORE
|
||||
LIBSRC_TRICORE += $(wildcard arch/TriCore/TriCore*.c)
|
||||
LIBOBJ_TRICORE += $(LIBSRC_TRICORE:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_ALPHA =
|
||||
DEP_ALPHA +=$(wildcard arch/Alpha/Alpha*.inc)
|
||||
|
||||
LIBOBJ_ALPHA =
|
||||
ifneq (,$(findstring alpha,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_ALPHA
|
||||
LIBSRC_ALPHA += $(wildcard arch/Alpha/Alpha*.c)
|
||||
LIBOBJ_ALPHA += $(LIBSRC_ALPHA:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_HPPA =
|
||||
DEP_HPPA += $(wildcard arch/HPPA/HPPA*.inc)
|
||||
|
||||
LIBOBJ_HPPA =
|
||||
ifneq (,$(findstring hppa,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_HPPA
|
||||
LIBSRC_HPPA += $(wildcard arch/HPPA/HPPA*.c)
|
||||
LIBOBJ_HPPA += $(LIBSRC_HPPA:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_LOONGARCH =
|
||||
DEP_LOONGARCH += $(wildcard arch/LoongArch/LoongArch*.inc)
|
||||
|
||||
LIBOBJ_LOONGARCH =
|
||||
ifneq (,$(findstring loongarch,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_LOONGARCH
|
||||
LIBSRC_LOONGARCH += $(wildcard arch/LoongArch/LoongArch*.c)
|
||||
LIBOBJ_LOONGARCH += $(LIBSRC_LOONGARCH:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_XTENSA =
|
||||
DEP_XTENSA += $(wildcard arch/Xtensa/Xtensa*.inc)
|
||||
|
||||
LIBOBJ_XTENSA =
|
||||
ifneq (,$(findstring xtensa,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_XTENSA
|
||||
LIBSRC_XTENSA += $(wildcard arch/Xtensa/Xtensa*.c)
|
||||
LIBOBJ_XTENSA += $(LIBSRC_XTENSA:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
DEP_ARC =
|
||||
DEP_ARC += $(wildcard arch/ARC/ARC*.inc)
|
||||
|
||||
LIBOBJ_ARC =
|
||||
ifneq (,$(findstring arc,$(CAPSTONE_ARCHS)))
|
||||
CFLAGS += -DCAPSTONE_HAS_ARC
|
||||
LIBSRC_ARC += $(wildcard arch/ARC/ARC*.c)
|
||||
LIBOBJ_ARC += $(LIBSRC_ARC:%.c=$(OBJDIR)/%.o)
|
||||
endif
|
||||
|
||||
LIBOBJ =
|
||||
LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o $(OBJDIR)/MCInst.o $(OBJDIR)/MCInstPrinter.o $(OBJDIR)/Mapping.o
|
||||
LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_AARCH64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_RISCV) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ) $(LIBOBJ_SH)
|
||||
LIBOBJ += $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX) $(LIBOBJ_WASM) $(LIBOBJ_BPF)
|
||||
LIBOBJ += $(LIBOBJ_TRICORE) $(LIBOBJ_ALPHA) $(LIBOBJ_HPPA) $(LIBOBJ_LOONGARCH) $(LIBOBJ_XTENSA) $(LIBOBJ_ARC)
|
||||
|
||||
|
||||
ifeq ($(PKG_EXTRA),)
|
||||
PKGCFGDIR = $(LIBDATADIR)/pkgconfig
|
||||
else
|
||||
PKGCFGDIR ?= $(LIBDATADIR)/pkgconfig
|
||||
ifeq ($(PKGCFGDIR),)
|
||||
PKGCFGDIR = $(LIBDATADIR)/pkgconfig
|
||||
endif
|
||||
endif
|
||||
|
||||
API_MAJOR=$(shell echo `grep -e CS_API_MAJOR include/capstone/capstone.h | grep -v = | awk '{print $$3}'` | awk '{print $$1}')
|
||||
VERSION_EXT =
|
||||
|
||||
IS_APPLE := $(shell $(CC) -dM -E - < /dev/null 2> /dev/null | grep __APPLE__ | wc -l | tr -d " ")
|
||||
ifeq ($(IS_APPLE),1)
|
||||
# on MacOS, do not build in Universal format by default
|
||||
MACOS_UNIVERSAL ?= no
|
||||
ifeq ($(MACOS_UNIVERSAL),yes)
|
||||
CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
endif
|
||||
EXT = dylib
|
||||
VERSION_EXT = $(API_MAJOR).$(EXT)
|
||||
$(LIBNAME)_LDFLAGS += -dynamiclib -install_name lib$(LIBNAME).$(VERSION_EXT) -current_version $(PKG_MAJOR).$(PKG_MINOR).$(PKG_EXTRA) -compatibility_version $(PKG_MAJOR).$(PKG_MINOR)
|
||||
AR_EXT = a
|
||||
# Homebrew wants to make sure its formula does not disable FORTIFY_SOURCE
|
||||
# However, this is not really necessary because 'CAPSTONE_USE_SYS_DYN_MEM=yes' by default
|
||||
ifneq ($(HOMEBREW_CAPSTONE),1)
|
||||
ifneq ($(CAPSTONE_USE_SYS_DYN_MEM),yes)
|
||||
# remove string check because OSX kernel complains about missing symbols
|
||||
CFLAGS += -D_FORTIFY_SOURCE=0
|
||||
endif
|
||||
endif
|
||||
else
|
||||
CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
|
||||
ifeq ($(OS), AIX)
|
||||
$(LIBNAME)_LDFLAGS += -qmkshrobj
|
||||
else
|
||||
$(LIBNAME)_LDFLAGS += -shared
|
||||
endif
|
||||
# Cygwin?
|
||||
IS_CYGWIN := $(shell $(CC) -dumpmachine 2>/dev/null | grep -i cygwin | wc -l)
|
||||
ifeq ($(IS_CYGWIN),1)
|
||||
EXT = dll
|
||||
AR_EXT = lib
|
||||
# Cygwin doesn't like -fPIC
|
||||
CFLAGS := $(CFLAGS:-fPIC=)
|
||||
# On Windows we need the shared library to be executable
|
||||
else
|
||||
# mingw?
|
||||
IS_MINGW := $(shell $(CC) --version 2>/dev/null | grep -i "\(mingw\|MSYS\)" | wc -l)
|
||||
ifeq ($(IS_MINGW),1)
|
||||
EXT = dll
|
||||
AR_EXT = lib
|
||||
# mingw doesn't like -fPIC either
|
||||
CFLAGS := $(CFLAGS:-fPIC=)
|
||||
# On Windows we need the shared library to be executable
|
||||
else
|
||||
# Linux, *BSD
|
||||
EXT = so
|
||||
VERSION_EXT = $(EXT).$(API_MAJOR)
|
||||
AR_EXT = a
|
||||
$(LIBNAME)_LDFLAGS += -Wl,-soname,lib$(LIBNAME).$(VERSION_EXT)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_SHARED),yes)
|
||||
ifeq ($(IS_MINGW),1)
|
||||
LIBRARY = $(BLDIR)/$(LIBNAME).$(VERSION_EXT)
|
||||
else ifeq ($(IS_CYGWIN),1)
|
||||
LIBRARY = $(BLDIR)/$(LIBNAME).$(EXT)
|
||||
else # *nix
|
||||
LIBRARY = $(BLDIR)/lib$(LIBNAME).$(VERSION_EXT)
|
||||
CFLAGS += -fvisibility=hidden
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_STATIC),yes)
|
||||
ifeq ($(IS_MINGW),1)
|
||||
ARCHIVE = $(BLDIR)/$(LIBNAME).$(AR_EXT)
|
||||
else ifeq ($(IS_CYGWIN),1)
|
||||
ARCHIVE = $(BLDIR)/$(LIBNAME).$(AR_EXT)
|
||||
else
|
||||
ARCHIVE = $(BLDIR)/lib$(LIBNAME).$(AR_EXT)
|
||||
endif
|
||||
endif
|
||||
|
||||
PKGCFGF = $(BLDIR)/$(LIBNAME).pc
|
||||
|
||||
.PHONY: all clean install uninstall dist
|
||||
|
||||
all: $(LIBRARY) $(ARCHIVE) $(PKGCFGF)
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
@V=$(V) CC=$(CC) $(MAKE) -C cstool
|
||||
endif
|
||||
|
||||
ifeq ($(CAPSTONE_SHARED),yes)
|
||||
$(LIBRARY): $(LIBOBJ)
|
||||
ifeq ($(V),0)
|
||||
$(call log,LINK,$(@:$(BLDIR)/%=%))
|
||||
@$(create-library)
|
||||
else
|
||||
$(create-library)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(LIBOBJ): config.mk
|
||||
|
||||
$(LIBOBJ_ARM): $(DEP_ARM)
|
||||
$(LIBOBJ_AARCH64): $(DEP_AARCH64)
|
||||
$(LIBOBJ_M68K): $(DEP_M68K)
|
||||
$(LIBOBJ_MIPS): $(DEP_MIPS)
|
||||
$(LIBOBJ_PPC): $(DEP_PPC)
|
||||
$(LIBOBJ_SH): $(DEP_SH)
|
||||
$(LIBOBJ_SPARC): $(DEP_SPARC)
|
||||
$(LIBOBJ_SYSZ): $(DEP_SYSZ)
|
||||
$(LIBOBJ_X86): $(DEP_X86)
|
||||
$(LIBOBJ_XCORE): $(DEP_XCORE)
|
||||
$(LIBOBJ_TMS320C64X): $(DEP_TMS320C64X)
|
||||
$(LIBOBJ_M680X): $(DEP_M680X)
|
||||
$(LIBOBJ_EVM): $(DEP_EVM)
|
||||
$(LIBOBJ_RISCV): $(DEP_RISCV)
|
||||
$(LIBOBJ_WASM): $(DEP_WASM)
|
||||
$(LIBOBJ_MOS65XX): $(DEP_MOS65XX)
|
||||
$(LIBOBJ_BPF): $(DEP_BPF)
|
||||
$(LIBOBJ_TRICORE): $(DEP_TRICORE)
|
||||
$(LIBOBJ_ALPHA): $(DEP_ALPHA)
|
||||
$(LIBOBJ_HPPA): $(DEP_HPPA)
|
||||
$(LIBOBJ_LOONGARCH): $(DEP_LOONGARCH)
|
||||
$(LIBOBJ_XTENSA): $(DEP_XTENSA)
|
||||
$(LIBOBJ_ARC): $(DEP_ARC)
|
||||
|
||||
ifeq ($(CAPSTONE_STATIC),yes)
|
||||
$(ARCHIVE): $(LIBOBJ)
|
||||
@rm -f $(ARCHIVE)
|
||||
ifeq ($(V),0)
|
||||
$(call log,AR,$(@:$(BLDIR)/%=%))
|
||||
@$(create-archive)
|
||||
else
|
||||
$(create-archive)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(PKGCFGF):
|
||||
ifeq ($(V),0)
|
||||
$(call log,GEN,$(@:$(BLDIR)/%=%))
|
||||
@$(generate-pkgcfg)
|
||||
else
|
||||
$(generate-pkgcfg)
|
||||
endif
|
||||
|
||||
# create a list of auto dependencies
|
||||
AUTODEPS:= $(patsubst %.o,%.d, $(LIBOBJ))
|
||||
|
||||
# include by auto dependencies
|
||||
-include $(AUTODEPS)
|
||||
|
||||
install: $(PKGCFGF) $(ARCHIVE) $(LIBRARY)
|
||||
mkdir -p $(LIBDIR)
|
||||
$(call install-library,$(LIBDIR))
|
||||
ifeq ($(CAPSTONE_STATIC),yes)
|
||||
$(INSTALL_DATA) $(ARCHIVE) $(LIBDIR)
|
||||
endif
|
||||
mkdir -p $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
||||
$(INSTALL_DATA) include/capstone/*.h $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
||||
mkdir -p $(PKGCFGDIR)
|
||||
$(INSTALL_DATA) $(PKGCFGF) $(PKGCFGDIR)
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
mkdir -p $(BINDIR)
|
||||
$(INSTALL_LIB) cstool/cstool $(BINDIR)
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
rm -rf $(DESTDIR)$(INCDIR)/$(LIBNAME)
|
||||
rm -f $(LIBDIR)/lib$(LIBNAME).*
|
||||
rm -f $(PKGCFGDIR)/$(LIBNAME).pc
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
rm -f $(BINDIR)/cstool
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJ)
|
||||
rm -f $(BLDIR)/lib$(LIBNAME).* $(BLDIR)/$(LIBNAME).pc
|
||||
rm -f $(PKGCFGF)
|
||||
rm -f $(AUTODEPS)
|
||||
[ "${ANDROID}" = "1" ] && rm -rf android-ndk-* || true
|
||||
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
$(MAKE) -C cstool clean
|
||||
$(MAKE) -C suite/fuzz clean
|
||||
endif
|
||||
|
||||
ifdef BUILDDIR
|
||||
rm -rf $(BUILDDIR)
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||
$(MAKE) -C bindings/python clean
|
||||
$(MAKE) -C bindings/java clean
|
||||
$(MAKE) -C bindings/ocaml clean
|
||||
endif
|
||||
|
||||
|
||||
TAG ?= HEAD
|
||||
ifeq ($(TAG), HEAD)
|
||||
DIST_VERSION = latest
|
||||
else
|
||||
DIST_VERSION = $(TAG)
|
||||
endif
|
||||
|
||||
dist:
|
||||
git archive --format=tar.gz --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).tgz
|
||||
git archive --format=zip --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).zip
|
||||
|
||||
checkfuzz: fuzztest fuzzallcorp
|
||||
|
||||
FUZZ_INPUTS = $(shell find suite/MC -type f -name '*.cs')
|
||||
|
||||
buildfuzz:
|
||||
ifndef BUILDDIR
|
||||
$(MAKE) -C suite/fuzz
|
||||
else
|
||||
$(MAKE) -C suite/fuzz BUILDDIR=$(BLDIR)
|
||||
endif
|
||||
|
||||
fuzztest:
|
||||
./suite/fuzz/fuzz_disasm $(FUZZ_INPUTS)
|
||||
|
||||
fuzzallcorp:
|
||||
ifneq ($(wildcard suite/fuzz/corpus-libFuzzer-capstone_fuzz_disasmnext-latest),)
|
||||
./suite/fuzz/fuzz_bindisasm suite/fuzz/corpus-libFuzzer-capstone_fuzz_disasmnext-latest/ > fuzz_bindisasm.log || (tail -1 fuzz_bindisasm.log; false)
|
||||
else
|
||||
@echo "Skipping tests on whole corpus"
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(@D)
|
||||
ifeq ($(V),0)
|
||||
$(call log,CC,$(@:$(OBJDIR)/%=%))
|
||||
@$(compile)
|
||||
else
|
||||
$(compile)
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CAPSTONE_SHARED),yes)
|
||||
define install-library
|
||||
$(INSTALL_LIB) $(LIBRARY) $1
|
||||
$(if $(VERSION_EXT),
|
||||
cd $1 && \
|
||||
rm -f lib$(LIBNAME).$(EXT) && \
|
||||
ln -s lib$(LIBNAME).$(VERSION_EXT) lib$(LIBNAME).$(EXT))
|
||||
endef
|
||||
else
|
||||
define install-library
|
||||
endef
|
||||
endif
|
||||
|
||||
ifeq ($(AR_FLAGS),)
|
||||
AR_FLAGS := q
|
||||
endif
|
||||
|
||||
define create-archive
|
||||
$(AR) $(AR_FLAGS) $(ARCHIVE) $(LIBOBJ)
|
||||
$(RANLIB) $(ARCHIVE)
|
||||
endef
|
||||
|
||||
|
||||
define create-library
|
||||
$(CC) $(LDFLAGS) $($(LIBNAME)_LDFLAGS) $(LIBOBJ) -o $(LIBRARY)
|
||||
endef
|
||||
|
||||
|
||||
define generate-pkgcfg
|
||||
mkdir -p $(BLDIR)
|
||||
echo 'Name: capstone' > $(PKGCFGF)
|
||||
echo 'Description: Capstone disassembly engine' >> $(PKGCFGF)
|
||||
echo 'Version: $(PKG_VERSION)' >> $(PKGCFGF)
|
||||
echo 'libdir=$(LIBDIR)' >> $(PKGCFGF)
|
||||
echo 'includedir=$(INCDIR)/capstone' >> $(PKGCFGF)
|
||||
echo 'archive=$${libdir}/libcapstone.a' >> $(PKGCFGF)
|
||||
echo 'Libs: -L$${libdir} -lcapstone' >> $(PKGCFGF)
|
||||
echo 'Libs.private: -L$${libdir} -l:libcapstone.a' >> $(PKGCFGF)
|
||||
echo 'Cflags: -I$${includedir}' >> $(PKGCFGF)
|
||||
echo 'archs=${CAPSTONE_ARCHS}' >> $(PKGCFGF)
|
||||
endef
|
||||
+525
@@ -0,0 +1,525 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
||||
|
||||
#include "Mapping.h"
|
||||
#include "capstone/capstone.h"
|
||||
#include "cs_priv.h"
|
||||
#include "utils.h"
|
||||
|
||||
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
|
||||
// the architecture needs this.
|
||||
cs_err populate_insn_map_cache(cs_struct *handle)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
// If this architecture doesn't use instruction mapping, do nothing
|
||||
if (!handle->insn_map || handle->insn_map_size <= 0)
|
||||
return CS_ERR_OK;
|
||||
|
||||
// Since the instruction map is assumed to be stored in ascending
|
||||
// order, we can get the maximum LLVM instruction id just by looking at
|
||||
// the last element.
|
||||
unsigned int cache_elements =
|
||||
handle->insn_map[handle->insn_map_size - 1].id + 1;
|
||||
|
||||
// This should not be initialized yet.
|
||||
CS_ASSERT(!handle->insn_cache);
|
||||
|
||||
unsigned short *cache = cs_mem_calloc(cache_elements, sizeof(*cache));
|
||||
if (!cache) {
|
||||
handle->errnum = CS_ERR_MEM;
|
||||
return CS_ERR_MEM;
|
||||
}
|
||||
handle->insn_cache = cache;
|
||||
|
||||
for (i = 1; i < handle->insn_map_size; ++i)
|
||||
handle->insn_cache[handle->insn_map[i].id] = i;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
const insn_map *lookup_insn_map(cs_struct *handle, unsigned short id)
|
||||
{
|
||||
// If this is getting called, we need the cache to already be populated
|
||||
// (this should be done when populate_insn_map_cache() gets called).
|
||||
CS_ASSERT(handle->insn_cache);
|
||||
CS_ASSERT(handle->insn_map_size);
|
||||
|
||||
unsigned short highest_id =
|
||||
handle->insn_map[handle->insn_map_size - 1].id;
|
||||
if (id > highest_id)
|
||||
return NULL;
|
||||
|
||||
unsigned short i = handle->insn_cache[id];
|
||||
|
||||
return &handle->insn_map[i];
|
||||
}
|
||||
|
||||
// Gives the id for the given @name if it is saved in @map.
|
||||
// Returns the id or -1 if not found.
|
||||
int name2id(const name_map *map, int max, const char *name)
|
||||
{
|
||||
CS_ASSERT_RET_VAL(map && name, -1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (!map[i].name) {
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(map[i].name, name)) {
|
||||
return map[i].id;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing match
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Gives the name for the given @id if it is saved in @map.
|
||||
// Returns the name or NULL if not found.
|
||||
const char *id2name(const name_map *map, int max, const unsigned int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (map[i].id == id) {
|
||||
return map[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing match
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Adds a register to the implicit write register list.
|
||||
/// It will not add the same register twice.
|
||||
void map_add_implicit_write(MCInst *MI, uint32_t Reg)
|
||||
{
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
uint16_t *regs_write = MI->flat_insn->detail->regs_write;
|
||||
for (int i = 0; i < MAX_IMPL_W_REGS; ++i) {
|
||||
if (i == MI->flat_insn->detail->regs_write_count) {
|
||||
regs_write[i] = Reg;
|
||||
MI->flat_insn->detail->regs_write_count++;
|
||||
return;
|
||||
}
|
||||
if (regs_write[i] == Reg)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a register to the implicit read register list.
|
||||
/// It will not add the same register twice.
|
||||
void map_add_implicit_read(MCInst *MI, uint32_t Reg)
|
||||
{
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
uint16_t *regs_read = MI->flat_insn->detail->regs_read;
|
||||
for (int i = 0; i < MAX_IMPL_R_REGS; ++i) {
|
||||
if (i == MI->flat_insn->detail->regs_read_count) {
|
||||
regs_read[i] = Reg;
|
||||
MI->flat_insn->detail->regs_read_count++;
|
||||
return;
|
||||
}
|
||||
if (regs_read[i] == Reg)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a register from the implicit write register list.
|
||||
void map_remove_implicit_write(MCInst *MI, uint32_t Reg)
|
||||
{
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
uint16_t *regs_write = MI->flat_insn->detail->regs_write;
|
||||
bool shorten_list = false;
|
||||
for (int i = 0; i < MAX_IMPL_W_REGS; ++i) {
|
||||
if (shorten_list) {
|
||||
regs_write[i - 1] = regs_write[i];
|
||||
}
|
||||
if (i >= MI->flat_insn->detail->regs_write_count)
|
||||
return;
|
||||
|
||||
if (regs_write[i] == Reg) {
|
||||
MI->flat_insn->detail->regs_write_count--;
|
||||
// The register should exist only once in the list.
|
||||
CS_ASSERT_RET(!shorten_list);
|
||||
shorten_list = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the implicit read registers of @imap to @MI->flat_insn.
|
||||
/// Already present registers will be preserved.
|
||||
void map_implicit_reads(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
unsigned i = 0;
|
||||
uint16_t reg = imap[Opcode].regs_use[i];
|
||||
while (reg != 0) {
|
||||
if (i >= MAX_IMPL_R_REGS ||
|
||||
detail->regs_read_count >= MAX_IMPL_R_REGS) {
|
||||
printf("ERROR: Too many implicit read register defined in "
|
||||
"instruction mapping.\n");
|
||||
return;
|
||||
}
|
||||
detail->regs_read[detail->regs_read_count++] = reg;
|
||||
if (i + 1 < MAX_IMPL_R_REGS) {
|
||||
// Select next one
|
||||
reg = imap[Opcode].regs_use[++i];
|
||||
}
|
||||
}
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
/// Copies the implicit write registers of @imap to @MI->flat_insn.
|
||||
/// Already present registers will be preserved.
|
||||
void map_implicit_writes(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
unsigned i = 0;
|
||||
uint16_t reg = imap[Opcode].regs_mod[i];
|
||||
while (reg != 0) {
|
||||
if (i >= MAX_IMPL_W_REGS ||
|
||||
detail->regs_write_count >= MAX_IMPL_W_REGS) {
|
||||
printf("ERROR: Too many implicit write register defined in "
|
||||
"instruction mapping.\n");
|
||||
return;
|
||||
}
|
||||
detail->regs_write[detail->regs_write_count++] = reg;
|
||||
if (i + 1 < MAX_IMPL_W_REGS) {
|
||||
// Select next one
|
||||
reg = imap[Opcode].regs_mod[++i];
|
||||
}
|
||||
}
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
/// Adds a given group to @MI->flat_insn.
|
||||
/// A group is never added twice.
|
||||
void add_group(MCInst *MI, unsigned /* arch_group */ group)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
if (detail->groups_count >= MAX_NUM_GROUPS) {
|
||||
printf("ERROR: Too many groups defined.\n");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < detail->groups_count; ++i) {
|
||||
if (detail->groups[i] == group) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
detail->groups[detail->groups_count++] = group;
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
/// Copies the groups from @imap to @MI->flat_insn.
|
||||
/// Already present groups will be preserved.
|
||||
void map_groups(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return;
|
||||
|
||||
cs_detail *detail = MI->flat_insn->detail;
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
unsigned i = 0;
|
||||
uint16_t group = imap[Opcode].groups[i];
|
||||
while (group != 0) {
|
||||
if (detail->groups_count >= MAX_NUM_GROUPS) {
|
||||
printf("ERROR: Too many groups defined in instruction mapping.\n");
|
||||
return;
|
||||
}
|
||||
detail->groups[detail->groups_count++] = group;
|
||||
group = imap[Opcode].groups[++i];
|
||||
}
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
/// Returns the pointer to the supllementary information in
|
||||
/// the instruction mapping table @imap or NULL in case of failure.
|
||||
const void *map_get_suppl_info(MCInst *MI, const insn_map *imap)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (!MI->flat_insn->detail)
|
||||
return NULL;
|
||||
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
return &imap[Opcode].suppl_info;
|
||||
#else
|
||||
return NULL;
|
||||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
// Search for the CS instruction id for the given @MC_Opcode in @imap.
|
||||
// return -1 if none is found.
|
||||
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
|
||||
unsigned imap_size)
|
||||
{
|
||||
// binary searching since the IDs are sorted in order
|
||||
unsigned int left, right, m;
|
||||
unsigned int max = imap_size;
|
||||
|
||||
right = max - 1;
|
||||
|
||||
if (MC_Opcode < imap[0].id || MC_Opcode > imap[right].id)
|
||||
// not found
|
||||
return -1;
|
||||
|
||||
left = 0;
|
||||
|
||||
while (left <= right) {
|
||||
m = (left + right) / 2;
|
||||
if (MC_Opcode == imap[m].id) {
|
||||
return m;
|
||||
}
|
||||
|
||||
if (MC_Opcode < imap[m].id)
|
||||
right = m - 1;
|
||||
else
|
||||
left = m + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Sets the Capstone instruction id which maps to the @MI opcode.
|
||||
/// If no mapping is found the function returns and prints an error.
|
||||
void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size)
|
||||
{
|
||||
unsigned int i = find_cs_id(MCInst_getOpcode(MI), imap, imap_size);
|
||||
if (i != -1) {
|
||||
MI->flat_insn->id = imap[i].mapid;
|
||||
return;
|
||||
}
|
||||
printf("ERROR: Could not find CS id for MCInst opcode: %d\n",
|
||||
MCInst_getOpcode(MI));
|
||||
return;
|
||||
}
|
||||
|
||||
/// Returns the operand type information from the
|
||||
/// mapping table for instruction operands.
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size)
|
||||
{
|
||||
assert(MI);
|
||||
assert(MI->Opcode < map_size);
|
||||
assert(OpNum < sizeof(insn_ops_map[MI->Opcode].ops) /
|
||||
sizeof(insn_ops_map[MI->Opcode].ops[0]));
|
||||
|
||||
return insn_ops_map[MI->Opcode].ops[OpNum].type;
|
||||
}
|
||||
|
||||
/// Returns the operand access flags from the
|
||||
/// mapping table for instruction operands.
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size)
|
||||
{
|
||||
assert(MI);
|
||||
assert(MI->Opcode < map_size);
|
||||
assert(OpNum < sizeof(insn_ops_map[MI->Opcode].ops) /
|
||||
sizeof(insn_ops_map[MI->Opcode].ops[0]));
|
||||
|
||||
cs_ac_type access = insn_ops_map[MI->Opcode].ops[OpNum].access;
|
||||
if (MCInst_opIsTied(MI, OpNum) || MCInst_opIsTying(MI, OpNum))
|
||||
access |= (access == CS_AC_READ) ? CS_AC_WRITE : CS_AC_READ;
|
||||
return access;
|
||||
}
|
||||
|
||||
/// Returns the operand at detail->arch.operands[op_count + offset]
|
||||
/// Or NULL if detail is not set or the offset would be out of bounds.
|
||||
#define DEFINE_get_detail_op(arch, ARCH, ARCH_UPPER) \
|
||||
cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset) \
|
||||
{ \
|
||||
if (!MI->flat_insn->detail) \
|
||||
return NULL; \
|
||||
int OpIdx = MI->flat_insn->detail->arch.op_count + offset; \
|
||||
if (OpIdx < 0 || OpIdx >= NUM_##ARCH_UPPER##_OPS) { \
|
||||
return NULL; \
|
||||
} \
|
||||
return &MI->flat_insn->detail->arch.operands[OpIdx]; \
|
||||
}
|
||||
|
||||
DEFINE_get_detail_op(arm, ARM, ARM);
|
||||
DEFINE_get_detail_op(ppc, PPC, PPC);
|
||||
DEFINE_get_detail_op(tricore, TriCore, TRICORE);
|
||||
DEFINE_get_detail_op(aarch64, AArch64, AARCH64);
|
||||
DEFINE_get_detail_op(alpha, Alpha, ALPHA);
|
||||
DEFINE_get_detail_op(hppa, HPPA, HPPA);
|
||||
DEFINE_get_detail_op(loongarch, LoongArch, LOONGARCH);
|
||||
DEFINE_get_detail_op(mips, Mips, MIPS);
|
||||
DEFINE_get_detail_op(riscv, RISCV, RISCV);
|
||||
DEFINE_get_detail_op(systemz, SystemZ, SYSTEMZ);
|
||||
DEFINE_get_detail_op(xtensa, Xtensa, XTENSA);
|
||||
DEFINE_get_detail_op(bpf, BPF, BPF);
|
||||
DEFINE_get_detail_op(arc, ARC, ARC);
|
||||
DEFINE_get_detail_op(sparc, Sparc, SPARC);
|
||||
|
||||
/// Returns the operand at detail->arch.operands[index]
|
||||
/// Or NULL if detail is not set or the index would be out of bounds.
|
||||
#define DEFINE_get_detail_op_at(arch, ARCH, ARCH_UPPER) \
|
||||
cs_##arch##_op *ARCH##_get_detail_op_at(MCInst *MI, int index) \
|
||||
{ \
|
||||
if (!MI->flat_insn->detail) \
|
||||
return NULL; \
|
||||
if (index < 0 || index >= NUM_##ARCH_UPPER##_OPS) { \
|
||||
return NULL; \
|
||||
} \
|
||||
return &MI->flat_insn->detail->arch.operands[index]; \
|
||||
}
|
||||
|
||||
DEFINE_get_detail_op_at(arm, ARM, ARM);
|
||||
DEFINE_get_detail_op_at(ppc, PPC, PPC);
|
||||
DEFINE_get_detail_op_at(tricore, TriCore, TRICORE);
|
||||
DEFINE_get_detail_op_at(aarch64, AArch64, AARCH64);
|
||||
DEFINE_get_detail_op_at(alpha, Alpha, ALPHA);
|
||||
DEFINE_get_detail_op_at(hppa, HPPA, HPPA);
|
||||
DEFINE_get_detail_op_at(loongarch, LoongArch, LOONGARCH);
|
||||
DEFINE_get_detail_op_at(mips, Mips, MIPS);
|
||||
DEFINE_get_detail_op_at(riscv, RISCV, RISCV);
|
||||
DEFINE_get_detail_op_at(systemz, SystemZ, SYSTEMZ);
|
||||
DEFINE_get_detail_op_at(xtensa, Xtensa, XTENSA);
|
||||
DEFINE_get_detail_op_at(bpf, BPF, BPF);
|
||||
DEFINE_get_detail_op_at(arc, ARC, ARC);
|
||||
DEFINE_get_detail_op_at(sparc, Sparc, SPARC);
|
||||
|
||||
/// Returns true if for this architecture the
|
||||
/// alias operands should be filled.
|
||||
/// TODO: Replace this with a proper option.
|
||||
/// So it can be toggled between disas() calls.
|
||||
bool map_use_alias_details(const MCInst *MI)
|
||||
{
|
||||
assert(MI);
|
||||
return (MI->csh->detail_opt & CS_OPT_ON) &&
|
||||
!(MI->csh->detail_opt & CS_OPT_DETAIL_REAL);
|
||||
}
|
||||
|
||||
/// Sets the setDetailOps flag to @p Val.
|
||||
/// If detail == NULLit refuses to set the flag to true.
|
||||
void map_set_fill_detail_ops(MCInst *MI, bool Val)
|
||||
{
|
||||
CS_ASSERT_RET(MI);
|
||||
if (!detail_is_set(MI)) {
|
||||
MI->fillDetailOps = false;
|
||||
return;
|
||||
}
|
||||
|
||||
MI->fillDetailOps = Val;
|
||||
}
|
||||
|
||||
/// Sets the instruction alias flags and the given alias id.
|
||||
void map_set_is_alias_insn(MCInst *MI, bool Val, uint64_t Alias)
|
||||
{
|
||||
CS_ASSERT_RET(MI);
|
||||
MI->isAliasInstr = Val;
|
||||
MI->flat_insn->is_alias = Val;
|
||||
MI->flat_insn->alias_id = Alias;
|
||||
}
|
||||
|
||||
static inline bool char_ends_mnem(const char c, cs_arch arch)
|
||||
{
|
||||
switch (arch) {
|
||||
default:
|
||||
return (!c || c == ' ' || c == '\t' || c == '.');
|
||||
case CS_ARCH_PPC:
|
||||
case CS_ARCH_RISCV:
|
||||
return (!c || c == ' ' || c == '\t');
|
||||
case CS_ARCH_SPARC:
|
||||
return (!c || c == ' ' || c == '\t' || c == ',');
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets an alternative id for some instruction.
|
||||
/// Or -1 if it fails.
|
||||
/// You must add (<ARCH>_INS_ALIAS_BEGIN + 1) to the id to get the real id.
|
||||
void map_set_alias_id(MCInst *MI, const SStream *O,
|
||||
const name_map *alias_mnem_id_map, int map_size)
|
||||
{
|
||||
if (!MCInst_isAlias(MI))
|
||||
return;
|
||||
|
||||
char alias_mnem[16] = { 0 };
|
||||
int i = 0, j = 0;
|
||||
const char *asm_str_buf = O->buffer;
|
||||
// Skip spaces and tabs
|
||||
while (is_blank_char(asm_str_buf[i])) {
|
||||
if (!asm_str_buf[i]) {
|
||||
MI->flat_insn->alias_id = -1;
|
||||
return;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
for (; j < sizeof(alias_mnem) - 1; ++j, ++i) {
|
||||
if (char_ends_mnem(asm_str_buf[i], MI->csh->arch))
|
||||
break;
|
||||
alias_mnem[j] = asm_str_buf[i];
|
||||
}
|
||||
|
||||
MI->flat_insn->alias_id =
|
||||
name2id(alias_mnem_id_map, map_size, alias_mnem);
|
||||
}
|
||||
|
||||
/// Does a binary search over the given map and searches for @id.
|
||||
/// If @id exists in @map, it sets @found to true and returns
|
||||
/// the value for the @id.
|
||||
/// Otherwise, @found is set to false and it returns UINT64_MAX.
|
||||
///
|
||||
/// Of course it assumes the map is sorted.
|
||||
uint64_t enum_map_bin_search(const cs_enum_id_map *map, size_t map_len,
|
||||
const char *id, bool *found)
|
||||
{
|
||||
size_t l = 0;
|
||||
size_t r = map_len;
|
||||
size_t id_len = strlen(id);
|
||||
|
||||
while (l <= r) {
|
||||
size_t m = (l + r) / 2;
|
||||
size_t j = 0;
|
||||
size_t i = 0;
|
||||
size_t entry_len = strlen(map[m].str);
|
||||
|
||||
while (j < entry_len && i < id_len && id[i] == map[m].str[j]) {
|
||||
++j, ++i;
|
||||
}
|
||||
if (i == id_len && j == entry_len) {
|
||||
*found = true;
|
||||
return map[m].val;
|
||||
}
|
||||
|
||||
if (id[i] < map[m].str[j]) {
|
||||
r = m - 1;
|
||||
} else if (id[i] > map[m].str[j]) {
|
||||
l = m + 1;
|
||||
}
|
||||
if ((m == 0 && id[i] < map[m].str[j]) ||
|
||||
(l + r) / 2 >= map_len) {
|
||||
// Break before we go out of bounds.
|
||||
break;
|
||||
}
|
||||
}
|
||||
*found = false;
|
||||
return UINT64_MAX;
|
||||
}
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
||||
|
||||
#ifndef CS_MAPPING_H
|
||||
#define CS_MAPPING_H
|
||||
|
||||
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
||||
#include <libkern/libkern.h>
|
||||
#else
|
||||
#include "include/capstone/capstone.h"
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include "cs_priv.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
|
||||
// the architecture needs this.
|
||||
cs_err populate_insn_map_cache(cs_struct *handle);
|
||||
|
||||
// Lookup the insn_map instance for an LLVM instruction ID. This method assumes
|
||||
// that this architecture uses the instruction mapping functionality available
|
||||
// from populate_insn_map_cache().
|
||||
// Returns NULL in case id is larger than the maximum mapped LLVM instruction
|
||||
// ID.
|
||||
const insn_map *lookup_insn_map(cs_struct *handle, unsigned short id);
|
||||
|
||||
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
|
||||
unsigned imap_size);
|
||||
|
||||
#define MAX_NO_DATA_TYPES 32
|
||||
|
||||
///< A LLVM<->CS Mapping entry of an MCOperand.
|
||||
typedef struct {
|
||||
uint8_t /* cs_op_type */ type; ///< Operand type (e.g.: reg, imm, mem)
|
||||
uint8_t /* cs_ac_type */ access; ///< The access type (read, write)
|
||||
/// List of op types. Terminated by CS_DATA_TYPE_LAST
|
||||
uint8_t /* cs_data_type */ dtypes[MAX_NO_DATA_TYPES];
|
||||
} mapping_op;
|
||||
|
||||
#define MAX_NO_INSN_MAP_OPS 16
|
||||
|
||||
///< MCOperands of an instruction.
|
||||
typedef struct {
|
||||
mapping_op
|
||||
ops[MAX_NO_INSN_MAP_OPS]; ///< NULL terminated array of insn_op.
|
||||
} map_insn_ops;
|
||||
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_op_type mapping_get_op_type(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size);
|
||||
|
||||
/// Only usable by `auto-sync` archs!
|
||||
const cs_ac_type mapping_get_op_access(MCInst *MI, unsigned OpNum,
|
||||
const map_insn_ops *insn_ops_map,
|
||||
size_t map_size);
|
||||
|
||||
/// Macro for easier access of operand types from the map.
|
||||
/// Assumes the istruction operands map is called "insn_operands"
|
||||
/// Only usable by `auto-sync` archs!
|
||||
#ifndef CAPSTONE_DIET
|
||||
#define map_get_op_type(MI, OpNum) \
|
||||
mapping_get_op_type(MI, OpNum, (const map_insn_ops *)insn_operands, \
|
||||
sizeof(insn_operands) / sizeof(insn_operands[0]))
|
||||
#else
|
||||
#define map_get_op_type(MI, OpNum) CS_OP_INVALID
|
||||
#endif
|
||||
|
||||
/// Macro for easier access of operand access flags from the map.
|
||||
/// Assumes the istruction operands map is called "insn_operands"
|
||||
/// Only usable by `auto-sync` archs!
|
||||
#ifndef CAPSTONE_DIET
|
||||
#define map_get_op_access(MI, OpNum) \
|
||||
mapping_get_op_access(MI, OpNum, (const map_insn_ops *)insn_operands, \
|
||||
sizeof(insn_operands) / \
|
||||
sizeof(insn_operands[0]))
|
||||
#else
|
||||
#define map_get_op_access(MI, OpNum) CS_AC_INVALID
|
||||
#endif
|
||||
|
||||
///< Map for ids to their string
|
||||
typedef struct name_map {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
} name_map;
|
||||
|
||||
// map a name to its ID
|
||||
// return 0 if not found
|
||||
int name2id(const name_map *map, int max, const char *name);
|
||||
|
||||
// map ID to a name
|
||||
// return NULL if not found
|
||||
const char *id2name(const name_map *map, int max, const unsigned int id);
|
||||
|
||||
void map_add_implicit_write(MCInst *MI, uint32_t Reg);
|
||||
void map_add_implicit_read(MCInst *MI, uint32_t Reg);
|
||||
void map_remove_implicit_write(MCInst *MI, uint32_t Reg);
|
||||
|
||||
void map_implicit_reads(MCInst *MI, const insn_map *imap);
|
||||
|
||||
void map_implicit_writes(MCInst *MI, const insn_map *imap);
|
||||
|
||||
void add_group(MCInst *MI, unsigned /* arch_group */ group);
|
||||
|
||||
void map_groups(MCInst *MI, const insn_map *imap);
|
||||
|
||||
void map_cs_id(MCInst *MI, const insn_map *imap, unsigned int imap_size);
|
||||
|
||||
const void *map_get_suppl_info(MCInst *MI, const insn_map *imap);
|
||||
|
||||
#define DECL_get_detail_op(arch, ARCH) \
|
||||
cs_##arch##_op *ARCH##_get_detail_op(MCInst *MI, int offset);
|
||||
|
||||
DECL_get_detail_op(arm, ARM);
|
||||
DECL_get_detail_op(ppc, PPC);
|
||||
DECL_get_detail_op(tricore, TriCore);
|
||||
DECL_get_detail_op(aarch64, AArch64);
|
||||
DECL_get_detail_op(alpha, Alpha);
|
||||
DECL_get_detail_op(hppa, HPPA);
|
||||
DECL_get_detail_op(loongarch, LoongArch);
|
||||
DECL_get_detail_op(mips, Mips);
|
||||
DECL_get_detail_op(riscv, RISCV);
|
||||
DECL_get_detail_op(systemz, SystemZ);
|
||||
DECL_get_detail_op(xtensa, Xtensa);
|
||||
DECL_get_detail_op(bpf, BPF);
|
||||
DECL_get_detail_op(arc, ARC);
|
||||
DECL_get_detail_op(sparc, Sparc);
|
||||
|
||||
#define DECL_get_detail_op_at(arch, ARCH) \
|
||||
cs_##arch##_op *ARCH##_get_detail_op_at(MCInst *MI, int offset);
|
||||
|
||||
DECL_get_detail_op_at(arm, ARM);
|
||||
DECL_get_detail_op_at(ppc, PPC);
|
||||
DECL_get_detail_op_at(tricore, TriCore);
|
||||
DECL_get_detail_op_at(aarch64, AArch64);
|
||||
DECL_get_detail_op_at(alpha, Alpha);
|
||||
DECL_get_detail_op_at(hppa, HPPA);
|
||||
DECL_get_detail_op_at(loongarch, LoongArch);
|
||||
DECL_get_detail_op_at(mips, Mips);
|
||||
DECL_get_detail_op_at(riscv, RISCV);
|
||||
DECL_get_detail_op_at(systemz, SystemZ);
|
||||
DECL_get_detail_op_at(xtensa, Xtensa);
|
||||
DECL_get_detail_op_at(bpf, BPF);
|
||||
DECL_get_detail_op_at(arc, ARC);
|
||||
DECL_get_detail_op_at(sparc, Sparc);
|
||||
|
||||
/// Increments the detail->arch.op_count by one.
|
||||
#define DEFINE_inc_detail_op_count(arch, ARCH) \
|
||||
static inline void ARCH##_inc_op_count(MCInst *MI) \
|
||||
{ \
|
||||
MI->flat_insn->detail->arch.op_count++; \
|
||||
}
|
||||
|
||||
/// Decrements the detail->arch.op_count by one.
|
||||
#define DEFINE_dec_detail_op_count(arch, ARCH) \
|
||||
static inline void ARCH##_dec_op_count(MCInst *MI) \
|
||||
{ \
|
||||
MI->flat_insn->detail->arch.op_count--; \
|
||||
}
|
||||
|
||||
DEFINE_inc_detail_op_count(arm, ARM);
|
||||
DEFINE_dec_detail_op_count(arm, ARM);
|
||||
DEFINE_inc_detail_op_count(ppc, PPC);
|
||||
DEFINE_dec_detail_op_count(ppc, PPC);
|
||||
DEFINE_inc_detail_op_count(tricore, TriCore);
|
||||
DEFINE_dec_detail_op_count(tricore, TriCore);
|
||||
DEFINE_inc_detail_op_count(aarch64, AArch64);
|
||||
DEFINE_dec_detail_op_count(aarch64, AArch64);
|
||||
DEFINE_inc_detail_op_count(alpha, Alpha);
|
||||
DEFINE_dec_detail_op_count(alpha, Alpha);
|
||||
DEFINE_inc_detail_op_count(hppa, HPPA);
|
||||
DEFINE_dec_detail_op_count(hppa, HPPA);
|
||||
DEFINE_inc_detail_op_count(loongarch, LoongArch);
|
||||
DEFINE_dec_detail_op_count(loongarch, LoongArch);
|
||||
DEFINE_inc_detail_op_count(mips, Mips);
|
||||
DEFINE_dec_detail_op_count(mips, Mips);
|
||||
DEFINE_inc_detail_op_count(riscv, RISCV);
|
||||
DEFINE_dec_detail_op_count(riscv, RISCV);
|
||||
DEFINE_inc_detail_op_count(systemz, SystemZ);
|
||||
DEFINE_dec_detail_op_count(systemz, SystemZ);
|
||||
DEFINE_inc_detail_op_count(xtensa, Xtensa);
|
||||
DEFINE_dec_detail_op_count(xtensa, Xtensa);
|
||||
DEFINE_inc_detail_op_count(bpf, BPF);
|
||||
DEFINE_dec_detail_op_count(bpf, BPF);
|
||||
DEFINE_inc_detail_op_count(arc, ARC);
|
||||
DEFINE_dec_detail_op_count(arc, ARC);
|
||||
DEFINE_inc_detail_op_count(sparc, Sparc);
|
||||
DEFINE_dec_detail_op_count(sparc, Sparc);
|
||||
|
||||
/// Returns true if a memory operand is currently edited.
|
||||
static inline bool doing_mem(const MCInst *MI)
|
||||
{
|
||||
return MI->csh->doing_mem;
|
||||
}
|
||||
|
||||
/// Sets the doing_mem flag to @status.
|
||||
static inline void set_doing_mem(const MCInst *MI, bool status)
|
||||
{
|
||||
MI->csh->doing_mem = status;
|
||||
}
|
||||
|
||||
/// Returns detail->arch
|
||||
#define DEFINE_get_arch_detail(arch, ARCH) \
|
||||
static inline cs_##arch *ARCH##_get_detail(const MCInst *MI) \
|
||||
{ \
|
||||
assert(MI && MI->flat_insn && MI->flat_insn->detail); \
|
||||
return &MI->flat_insn->detail->arch; \
|
||||
}
|
||||
|
||||
DEFINE_get_arch_detail(arm, ARM);
|
||||
DEFINE_get_arch_detail(ppc, PPC);
|
||||
DEFINE_get_arch_detail(tricore, TriCore);
|
||||
DEFINE_get_arch_detail(aarch64, AArch64);
|
||||
DEFINE_get_arch_detail(alpha, Alpha);
|
||||
DEFINE_get_arch_detail(hppa, HPPA);
|
||||
DEFINE_get_arch_detail(loongarch, LoongArch);
|
||||
DEFINE_get_arch_detail(mips, Mips);
|
||||
DEFINE_get_arch_detail(riscv, RISCV);
|
||||
DEFINE_get_arch_detail(arc, ARC);
|
||||
DEFINE_get_arch_detail(systemz, SystemZ);
|
||||
DEFINE_get_arch_detail(xtensa, Xtensa);
|
||||
DEFINE_get_arch_detail(bpf, BPF);
|
||||
DEFINE_get_arch_detail(sparc, Sparc);
|
||||
|
||||
#define DEFINE_check_safe_inc(Arch, ARCH) \
|
||||
static inline void Arch##_check_safe_inc(const MCInst *MI) \
|
||||
{ \
|
||||
assert(Arch##_get_detail(MI)->op_count + 1 < \
|
||||
NUM_##ARCH##_OPS); \
|
||||
}
|
||||
|
||||
DEFINE_check_safe_inc(ARM, ARM);
|
||||
DEFINE_check_safe_inc(PPC, PPC);
|
||||
DEFINE_check_safe_inc(TriCore, TRICORE);
|
||||
DEFINE_check_safe_inc(AArch64, AARCH64);
|
||||
DEFINE_check_safe_inc(Alpha, ALPHA);
|
||||
DEFINE_check_safe_inc(HPPA, HPPA);
|
||||
DEFINE_check_safe_inc(LoongArch, LOONGARCH);
|
||||
DEFINE_check_safe_inc(RISCV, RISCV);
|
||||
DEFINE_check_safe_inc(SystemZ, SYSTEMZ);
|
||||
DEFINE_check_safe_inc(Mips, MIPS);
|
||||
DEFINE_check_safe_inc(BPF, BPF);
|
||||
DEFINE_check_safe_inc(ARC, ARC);
|
||||
DEFINE_check_safe_inc(Sparc, SPARC);
|
||||
|
||||
static inline bool detail_is_set(const MCInst *MI)
|
||||
{
|
||||
assert(MI && MI->flat_insn);
|
||||
return MI->flat_insn->detail != NULL && MI->csh->detail_opt & CS_OPT_ON;
|
||||
}
|
||||
|
||||
static inline cs_detail *get_detail(const MCInst *MI)
|
||||
{
|
||||
assert(MI && MI->flat_insn);
|
||||
return MI->flat_insn->detail;
|
||||
}
|
||||
|
||||
/// Returns if the given instruction is an alias instruction.
|
||||
#define RETURN_IF_INSN_IS_ALIAS(MI) \
|
||||
do { \
|
||||
if (MI->isAliasInstr) \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
void map_set_fill_detail_ops(MCInst *MI, bool Val);
|
||||
|
||||
static inline bool map_fill_detail_ops(MCInst *MI)
|
||||
{
|
||||
assert(MI);
|
||||
return MI->fillDetailOps;
|
||||
}
|
||||
|
||||
void map_set_is_alias_insn(MCInst *MI, bool Val, uint64_t Alias);
|
||||
|
||||
bool map_use_alias_details(const MCInst *MI);
|
||||
|
||||
void map_set_alias_id(MCInst *MI, const SStream *O,
|
||||
const name_map *alias_mnem_id_map, int map_size);
|
||||
|
||||
/// Mapping from Capstone enumeration identifiers and their values.
|
||||
///
|
||||
/// This map MUST BE sorted to allow binary searches.
|
||||
/// Please always ensure the map is sorted after you added a value.
|
||||
///
|
||||
/// You can sort the map with Python.
|
||||
/// Copy the map into a file and run:
|
||||
///
|
||||
/// ```python
|
||||
/// with open("/tmp/file_with_map_entries") as f:
|
||||
/// text = f.readlines()
|
||||
///
|
||||
/// text.sort()
|
||||
/// print(''.join(text))
|
||||
/// ```
|
||||
typedef struct {
|
||||
const char *str; ///< The name of the enumeration identifier
|
||||
uint64_t val; ///< The value of the identifier
|
||||
} cs_enum_id_map;
|
||||
|
||||
uint64_t enum_map_bin_search(const cs_enum_id_map *map, size_t map_len,
|
||||
const char *id, bool *found);
|
||||
|
||||
#endif // CS_MAPPING_H
|
||||
+570
@@ -0,0 +1,570 @@
|
||||
//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains some functions that are useful for math stuff.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_LLVM_SUPPORT_MATHEXTRAS_H
|
||||
#define CS_LLVM_SUPPORT_MATHEXTRAS_H
|
||||
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 0x800)
|
||||
#include "windowsce/intrin.h"
|
||||
#elif defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifdef _MSC_VER
|
||||
#define inline /* inline */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// NOTE: The following support functions use the _32/_64 extensions instead of
|
||||
// type overloading so that signed and unsigned integers can be used without
|
||||
// ambiguity.
|
||||
|
||||
/// Hi_32 - This function returns the high 32 bits of a 64 bit value.
|
||||
static inline uint32_t Hi_32(uint64_t Value)
|
||||
{
|
||||
return (uint32_t)(Value >> 32);
|
||||
}
|
||||
|
||||
/// Lo_32 - This function returns the low 32 bits of a 64 bit value.
|
||||
static inline uint32_t Lo_32(uint64_t Value)
|
||||
{
|
||||
return (uint32_t)(Value);
|
||||
}
|
||||
|
||||
/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
|
||||
/// bit width.
|
||||
static inline bool isUIntN(unsigned N, uint64_t x)
|
||||
{
|
||||
return x == (x & (~0ULL >> (64 - N)));
|
||||
}
|
||||
|
||||
/// isIntN - Checks if an signed integer fits into the given (dynamic)
|
||||
/// bit width.
|
||||
static inline bool isIntN(unsigned N, int64_t x)
|
||||
{
|
||||
return N >= 64 ||
|
||||
(-(INT64_C(1) << (N - 1)) <= x && x < (INT64_C(1) << (N - 1)));
|
||||
}
|
||||
|
||||
/// isShiftedIntN - Checks if a signed integer is an N bit number shifted left by S.
|
||||
static inline bool isShiftedIntN(unsigned N, unsigned S, int64_t x)
|
||||
{
|
||||
return isIntN(N + S, x) && (x % (UINT64_C(1) << S) == 0);
|
||||
}
|
||||
|
||||
static inline bool isShiftedUIntN(unsigned N, unsigned S, uint64_t x)
|
||||
{
|
||||
return isUIntN(N + S, x) && (x % (UINT64_C(1) << S) == 0);
|
||||
}
|
||||
|
||||
/// isMask_32 - This function returns true if the argument is a sequence of ones
|
||||
/// starting at the least significant bit with the remainder zero (32 bit
|
||||
/// version). Ex. isMask_32(0x0000FFFFU) == true.
|
||||
static inline bool isMask_32(uint32_t Value)
|
||||
{
|
||||
return Value && ((Value + 1) & Value) == 0;
|
||||
}
|
||||
|
||||
/// isMask_64 - This function returns true if the argument is a sequence of ones
|
||||
/// starting at the least significant bit with the remainder zero (64 bit
|
||||
/// version).
|
||||
static inline bool isMask_64(uint64_t Value)
|
||||
{
|
||||
return Value && ((Value + 1) & Value) == 0;
|
||||
}
|
||||
|
||||
/// isShiftedMask_32 - This function returns true if the argument contains a
|
||||
/// sequence of ones with the remainder zero (32 bit version.)
|
||||
/// Ex. isShiftedMask_32(0x0000FF00U) == true.
|
||||
static inline bool isShiftedMask_32(uint32_t Value)
|
||||
{
|
||||
return isMask_32((Value - 1) | Value);
|
||||
}
|
||||
|
||||
/// isShiftedMask_64 - This function returns true if the argument contains a
|
||||
/// sequence of ones with the remainder zero (64 bit version.)
|
||||
static inline bool isShiftedMask_64(uint64_t Value)
|
||||
{
|
||||
return isMask_64((Value - 1) | Value);
|
||||
}
|
||||
|
||||
/// isPowerOf2_32 - This function returns true if the argument is a power of
|
||||
/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
|
||||
static inline bool isPowerOf2_32(uint32_t Value)
|
||||
{
|
||||
return Value && !(Value & (Value - 1));
|
||||
}
|
||||
|
||||
/// CountLeadingZeros_32 - this function performs the platform optimal form of
|
||||
/// counting the number of zeros from the most significant bit to the first one
|
||||
/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8.
|
||||
/// Returns 32 if the word is zero.
|
||||
static inline unsigned CountLeadingZeros_32(uint32_t Value)
|
||||
{
|
||||
unsigned Count; // result
|
||||
#if __GNUC__ >= 4
|
||||
// PowerPC is defined for __builtin_clz(0)
|
||||
#if !defined(__ppc__) && !defined(__ppc64__)
|
||||
if (!Value)
|
||||
return 32;
|
||||
#endif
|
||||
Count = __builtin_clz(Value);
|
||||
#else
|
||||
unsigned Shift;
|
||||
if (!Value)
|
||||
return 32;
|
||||
Count = 0;
|
||||
// bisection method for count leading zeros
|
||||
for (Shift = 32 >> 1; Shift; Shift >>= 1) {
|
||||
uint32_t Tmp = Value >> Shift;
|
||||
if (Tmp) {
|
||||
Value = Tmp;
|
||||
} else {
|
||||
Count |= Shift;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return Count;
|
||||
}
|
||||
|
||||
/// CountLeadingOnes_32 - this function performs the operation of
|
||||
/// counting the number of ones from the most significant bit to the first zero
|
||||
/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8.
|
||||
/// Returns 32 if the word is all ones.
|
||||
static inline unsigned CountLeadingOnes_32(uint32_t Value)
|
||||
{
|
||||
return CountLeadingZeros_32(~Value);
|
||||
}
|
||||
|
||||
/// CountLeadingZeros_64 - This function performs the platform optimal form
|
||||
/// of counting the number of zeros from the most significant bit to the first
|
||||
/// one bit (64 bit edition.)
|
||||
/// Returns 64 if the word is zero.
|
||||
static inline unsigned CountLeadingZeros_64(uint64_t Value)
|
||||
{
|
||||
unsigned Count; // result
|
||||
#if __GNUC__ >= 4
|
||||
// PowerPC is defined for __builtin_clzll(0)
|
||||
#if !defined(__ppc__) && !defined(__ppc64__)
|
||||
if (!Value)
|
||||
return 64;
|
||||
#endif
|
||||
Count = __builtin_clzll(Value);
|
||||
#else
|
||||
#ifndef _MSC_VER
|
||||
unsigned Shift;
|
||||
if (sizeof(long) == sizeof(int64_t)) {
|
||||
if (!Value)
|
||||
return 64;
|
||||
Count = 0;
|
||||
// bisection method for count leading zeros
|
||||
for (Shift = 64 >> 1; Shift; Shift >>= 1) {
|
||||
uint64_t Tmp = Value >> Shift;
|
||||
if (Tmp) {
|
||||
Value = Tmp;
|
||||
} else {
|
||||
Count |= Shift;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// get hi portion
|
||||
uint32_t Hi = Hi_32(Value);
|
||||
|
||||
// if some bits in hi portion
|
||||
if (Hi) {
|
||||
// leading zeros in hi portion plus all bits in lo portion
|
||||
Count = CountLeadingZeros_32(Hi);
|
||||
} else {
|
||||
// get lo portion
|
||||
uint32_t Lo = Lo_32(Value);
|
||||
// same as 32 bit value
|
||||
Count = CountLeadingZeros_32(Lo) + 32;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return Count;
|
||||
}
|
||||
|
||||
/// CountLeadingOnes_64 - This function performs the operation
|
||||
/// of counting the number of ones from the most significant bit to the first
|
||||
/// zero bit (64 bit edition.)
|
||||
/// Returns 64 if the word is all ones.
|
||||
static inline unsigned CountLeadingOnes_64(uint64_t Value)
|
||||
{
|
||||
return CountLeadingZeros_64(~Value);
|
||||
}
|
||||
|
||||
/// CountTrailingZeros_32 - this function performs the platform optimal form of
|
||||
/// counting the number of zeros from the least significant bit to the first one
|
||||
/// bit. Ex. CountTrailingZeros_32(0xFF00FF00) == 8.
|
||||
/// Returns 32 if the word is zero.
|
||||
static inline unsigned CountTrailingZeros_32(uint32_t Value)
|
||||
{
|
||||
#if __GNUC__ >= 4
|
||||
return Value ? __builtin_ctz(Value) : 32;
|
||||
#else
|
||||
static const unsigned Mod37BitPosition[] = {
|
||||
32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28,
|
||||
11, 0, 13, 4, 7, 17, 0, 25, 22, 31, 15, 29, 10,
|
||||
12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18
|
||||
};
|
||||
// Replace "-Value" by "1+~Value" in the following commented code to avoid
|
||||
// MSVC warning C4146
|
||||
// return Mod37BitPosition[(-Value & Value) % 37];
|
||||
return Mod37BitPosition[((1 + ~Value) & Value) % 37];
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count trailing zeros as in:
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightParallel
|
||||
static inline unsigned CountTrailingZeros_8(uint8_t Value)
|
||||
{
|
||||
uint8_t c = 8;
|
||||
Value &= -((int8_t)Value);
|
||||
if (Value)
|
||||
c--;
|
||||
if (Value & 0x0F)
|
||||
c -= 4;
|
||||
if (Value & 0x33)
|
||||
c -= 2;
|
||||
if (Value & 0x55)
|
||||
c -= 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// CountTrailingOnes_32 - this function performs the operation of
|
||||
/// counting the number of ones from the least significant bit to the first zero
|
||||
/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8.
|
||||
/// Returns 32 if the word is all ones.
|
||||
static inline unsigned CountTrailingOnes_32(uint32_t Value)
|
||||
{
|
||||
return CountTrailingZeros_32(~Value);
|
||||
}
|
||||
|
||||
/// CountTrailingZeros_64 - This function performs the platform optimal form
|
||||
/// of counting the number of zeros from the least significant bit to the first
|
||||
/// one bit (64 bit edition.)
|
||||
/// Returns 64 if the word is zero.
|
||||
static inline unsigned CountTrailingZeros_64(uint64_t Value)
|
||||
{
|
||||
#if __GNUC__ >= 4
|
||||
return Value ? __builtin_ctzll(Value) : 64;
|
||||
#else
|
||||
static const unsigned Mod67Position[] = {
|
||||
64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19,
|
||||
24, 54, 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51,
|
||||
25, 44, 55, 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53,
|
||||
63, 9, 61, 27, 29, 50, 43, 46, 31, 37, 21, 57, 52, 8,
|
||||
26, 49, 45, 36, 56, 7, 48, 35, 6, 34, 33, 0
|
||||
};
|
||||
// Replace "-Value" by "1+~Value" in the following commented code to avoid
|
||||
// MSVC warning C4146
|
||||
// return Mod67Position[(-Value & Value) % 67];
|
||||
return Mod67Position[((1 + ~Value) & Value) % 67];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// CountTrailingOnes_64 - This function performs the operation
|
||||
/// of counting the number of ones from the least significant bit to the first
|
||||
/// zero bit (64 bit edition.)
|
||||
/// Returns 64 if the word is all ones.
|
||||
static inline unsigned CountTrailingOnes_64(uint64_t Value)
|
||||
{
|
||||
return CountTrailingZeros_64(~Value);
|
||||
}
|
||||
|
||||
/// CountPopulation_32 - this function counts the number of set bits in a value.
|
||||
/// Ex. CountPopulation(0xF000F000) = 8
|
||||
/// Returns 0 if the word is zero.
|
||||
static inline unsigned CountPopulation_32(uint32_t Value)
|
||||
{
|
||||
#if __GNUC__ >= 4
|
||||
return __builtin_popcount(Value);
|
||||
#else
|
||||
uint32_t v = Value - ((Value >> 1) & 0x55555555);
|
||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||
return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// CountPopulation_64 - this function counts the number of set bits in a value,
|
||||
/// (64 bit edition.)
|
||||
static inline unsigned CountPopulation_64(uint64_t Value)
|
||||
{
|
||||
#if __GNUC__ >= 4
|
||||
return __builtin_popcountll(Value);
|
||||
#else
|
||||
uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL);
|
||||
v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
|
||||
v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
return (uint64_t)((v * 0x0101010101010101ULL) >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Log2_32 - This function returns the floor log base 2 of the specified value,
|
||||
/// UINT_MAX if the value is zero. (32 bit edition.)
|
||||
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
|
||||
static inline unsigned Log2_32(uint32_t Value)
|
||||
{
|
||||
if (Value == 0) {
|
||||
return UINT_MAX;
|
||||
}
|
||||
return 31 - CountLeadingZeros_32(Value);
|
||||
}
|
||||
|
||||
/// Log2_64 - This function returns the floor log base 2 of the specified value,
|
||||
/// UINT_MAX if the value is zero. (64 bit edition.)
|
||||
static inline unsigned Log2_64(uint64_t Value)
|
||||
{
|
||||
if (Value == 0) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return 63 - CountLeadingZeros_64(Value);
|
||||
}
|
||||
|
||||
/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified
|
||||
/// value, 32 if the value is zero. (32 bit edition).
|
||||
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
|
||||
static inline unsigned Log2_32_Ceil(uint32_t Value)
|
||||
{
|
||||
return 32 - CountLeadingZeros_32(Value - 1);
|
||||
}
|
||||
|
||||
/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified
|
||||
/// value, 64 if the value is zero. (64 bit edition.)
|
||||
static inline unsigned Log2_64_Ceil(uint64_t Value)
|
||||
{
|
||||
return 64 - CountLeadingZeros_64(Value - 1);
|
||||
}
|
||||
|
||||
/// GreatestCommonDivisor64 - Return the greatest common divisor of the two
|
||||
/// values using Euclid's algorithm.
|
||||
static inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B)
|
||||
{
|
||||
while (B) {
|
||||
uint64_t T = B;
|
||||
B = A % B;
|
||||
A = T;
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
/// BitsToDouble - This function takes a 64-bit integer and returns the bit
|
||||
/// equivalent double.
|
||||
static inline double BitsToDouble(uint64_t Bits)
|
||||
{
|
||||
union {
|
||||
uint64_t L;
|
||||
double D;
|
||||
} T;
|
||||
T.L = Bits;
|
||||
return T.D;
|
||||
}
|
||||
|
||||
/// BitsToFloat - This function takes a 32-bit integer and returns the bit
|
||||
/// equivalent float.
|
||||
static inline float BitsToFloat(uint32_t Bits)
|
||||
{
|
||||
union {
|
||||
uint32_t I;
|
||||
float F;
|
||||
} T;
|
||||
T.I = Bits;
|
||||
return T.F;
|
||||
}
|
||||
|
||||
/// DoubleToBits - This function takes a double and returns the bit
|
||||
/// equivalent 64-bit integer. Note that copying doubles around
|
||||
/// changes the bits of NaNs on some hosts, notably x86, so this
|
||||
/// routine cannot be used if these bits are needed.
|
||||
static inline uint64_t DoubleToBits(double Double)
|
||||
{
|
||||
union {
|
||||
uint64_t L;
|
||||
double D;
|
||||
} T;
|
||||
T.D = Double;
|
||||
return T.L;
|
||||
}
|
||||
|
||||
/// FloatToBits - This function takes a float and returns the bit
|
||||
/// equivalent 32-bit integer. Note that copying floats around
|
||||
/// changes the bits of NaNs on some hosts, notably x86, so this
|
||||
/// routine cannot be used if these bits are needed.
|
||||
static inline uint32_t FloatToBits(float Float)
|
||||
{
|
||||
union {
|
||||
uint32_t I;
|
||||
float F;
|
||||
} T;
|
||||
T.F = Float;
|
||||
return T.I;
|
||||
}
|
||||
|
||||
/// MinAlign - A and B are either alignments or offsets. Return the minimum
|
||||
/// alignment that may be assumed after adding the two together.
|
||||
static inline uint64_t MinAlign(uint64_t A, uint64_t B)
|
||||
{
|
||||
// The largest power of 2 that divides both A and B.
|
||||
//
|
||||
// Replace "-Value" by "1+~Value" in the following commented code to avoid
|
||||
// MSVC warning C4146
|
||||
// return (A | B) & -(A | B);
|
||||
return (A | B) & (1 + ~(A | B));
|
||||
}
|
||||
|
||||
/// NextPowerOf2 - Returns the next power of two (in 64-bits)
|
||||
/// that is strictly greater than A. Returns zero on overflow.
|
||||
static inline uint64_t NextPowerOf2(uint64_t A)
|
||||
{
|
||||
A |= (A >> 1);
|
||||
A |= (A >> 2);
|
||||
A |= (A >> 4);
|
||||
A |= (A >> 8);
|
||||
A |= (A >> 16);
|
||||
A |= (A >> 32);
|
||||
return A + 1;
|
||||
}
|
||||
|
||||
/// Returns the next integer (mod 2**64) that is greater than or equal to
|
||||
/// \p Value and is a multiple of \p Align. \p Align must be non-zero.
|
||||
///
|
||||
/// Examples:
|
||||
/// \code
|
||||
/// RoundUpToAlignment(5, 8) = 8
|
||||
/// RoundUpToAlignment(17, 8) = 24
|
||||
/// RoundUpToAlignment(~0LL, 8) = 0
|
||||
/// \endcode
|
||||
static inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
|
||||
{
|
||||
return ((Value + Align - 1) / Align) * Align;
|
||||
}
|
||||
|
||||
/// Returns the offset to the next integer (mod 2**64) that is greater than
|
||||
/// or equal to \p Value and is a multiple of \p Align. \p Align must be
|
||||
/// non-zero.
|
||||
static inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align)
|
||||
{
|
||||
return RoundUpToAlignment(Value, Align) - Value;
|
||||
}
|
||||
|
||||
/// abs64 - absolute value of a 64-bit int. Not all environments support
|
||||
/// "abs" on whatever their name for the 64-bit int type is. The absolute
|
||||
/// value of the largest negative number is undefined, as with "abs".
|
||||
static inline int64_t abs64(int64_t x)
|
||||
{
|
||||
return (x < 0) ? -x : x;
|
||||
}
|
||||
|
||||
/// \brief Sign extend number in the bottom B bits of X to a 32-bit int.
|
||||
/// Requires 0 < B <= 32.
|
||||
/// Note that this implementation relies on right shift of signed
|
||||
/// integers being an arithmetic shift.
|
||||
static inline int32_t SignExtend32(uint32_t X, unsigned B)
|
||||
{
|
||||
return (int32_t)(X << (32 - B)) >> (32 - B);
|
||||
}
|
||||
|
||||
/// \brief Sign extend number in the bottom B bits of X to a 64-bit int.
|
||||
/// Requires 0 < B <= 64.
|
||||
/// Note that this implementation relies on right shift of signed
|
||||
/// integers being an arithmetic shift.
|
||||
static inline int64_t SignExtend64(uint64_t X, unsigned B)
|
||||
{
|
||||
return (int64_t)(X << (64 - B)) >> (64 - B);
|
||||
}
|
||||
|
||||
/// \brief Removes the rightmost bit of x and extends the field to the left with that
|
||||
/// bit to form a 64-bit quantity. The field is of size len
|
||||
static inline int64_t LowSignExtend64(uint64_t x, unsigned len)
|
||||
{
|
||||
return (x >> 1) - ((x & 1) << (len - 1));
|
||||
}
|
||||
|
||||
/// \brief One extend number X starting at bit B and returns it as int32_t.
|
||||
/// Requires 0 < B <= 32.
|
||||
static inline int32_t OneExtend32(uint32_t X, unsigned B)
|
||||
{
|
||||
return (~0U << B) | X;
|
||||
}
|
||||
|
||||
/// \brief One extend number X starting at bit B and returns it as int64_t.
|
||||
/// Requires 0 < B <= 64.
|
||||
static inline int64_t OneExtend64(uint64_t X, unsigned B)
|
||||
{
|
||||
return (~0ULL << B) | X;
|
||||
}
|
||||
|
||||
/// \brief Count number of 0's from the most significant bit to the least
|
||||
/// stopping at the first 1.
|
||||
///
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
||||
/// valid arguments.
|
||||
static inline unsigned int countLeadingZeros(int x)
|
||||
{
|
||||
int i;
|
||||
const unsigned bits = sizeof(x) * 8;
|
||||
unsigned count = bits;
|
||||
|
||||
if (x < 0) {
|
||||
return 0;
|
||||
}
|
||||
for (i = bits; --i;) {
|
||||
if (x == 0)
|
||||
break;
|
||||
count--;
|
||||
x >>= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// \brief Get specified field from 32-bit instruction. Returns bits from the segment [from, to]
|
||||
/// The right most bit of insn is bit 31.
|
||||
static inline uint32_t get_insn_field(uint32_t insn, uint8_t from, uint8_t to)
|
||||
{
|
||||
return insn >> (31 - to) & ((1 << (to - from + 1)) - 1);
|
||||
}
|
||||
|
||||
/// \brief Get specified field from 32-bit instruction. Returns bits from the segment [from, to]
|
||||
/// The right most bit of insn is bit 0.
|
||||
static inline uint32_t get_insn_field_r(uint32_t insn, uint8_t from, uint8_t to)
|
||||
{
|
||||
return insn >> from & ((1 << (to - from + 1)) - 1);
|
||||
}
|
||||
|
||||
/// \brief Get specified bit from 32-bit instruction
|
||||
static inline uint32_t get_insn_bit(uint32_t insn, uint8_t bit)
|
||||
{
|
||||
return get_insn_field(insn, bit, bit);
|
||||
}
|
||||
|
||||
/// \brief Create a bitmask with the N right-most bits set to 1, and all other
|
||||
/// bits set to 0. Only unsigned types are allowed.
|
||||
static inline uint32_t maskTrailingOnes32(uint32_t N)
|
||||
{
|
||||
const unsigned Bits = CHAR_BIT * sizeof(uint32_t);
|
||||
return N == 0 ? 0 : (((uint32_t)-1) >> (Bits - N));
|
||||
}
|
||||
|
||||
#endif
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
Capstone Engine
|
||||
===============
|
||||
|
||||
[](https://ci.appveyor.com/project/aquynh/capstone/branch/next)
|
||||
[](https://pypi.python.org/pypi/capstone)
|
||||
[](https://pepy.tech/project/capstone)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:capstone)
|
||||
|
||||
> [!TIP]
|
||||
> Welcome to join our community group!
|
||||
>   [<img src="https://img.shields.io/badge/Telegram-2CA5E0?style=flat-squeare&logo=telegram&logoColor=white" height="22" />](https://t.me/CapstoneEngine)
|
||||
|
||||
Capstone is a disassembly framework with the target of becoming the ultimate
|
||||
disasm engine for binary analysis and reversing in the security community.
|
||||
|
||||
Created by Nguyen Anh Quynh, then developed and maintained by a small community,
|
||||
Capstone offers some unparalleled features:
|
||||
|
||||
- Support multiple hardware architectures: ARM, AArch64, Alpha, ARC, BPF, Ethereum VM,
|
||||
LoongArch, HP PA-RISC (HPPA), M68K, M680X, Mips, MOS65XX, PPC, RISC-V(rv32G/rv64G), SH,
|
||||
Sparc, SystemZ, TMS320C64X, TriCore, Webassembly, XCore and X86 (16, 32, 64), Xtensa.
|
||||
|
||||
- Having clean/simple/lightweight/intuitive architecture-neutral API.
|
||||
|
||||
- Provide details on disassembled instruction (called “decomposer” by others).
|
||||
|
||||
- Provide semantics of the disassembled instruction, such as list of implicit
|
||||
registers read & written.
|
||||
|
||||
- Implemented in pure C language, with lightweight bindings for Swift, D, Clojure, F#,
|
||||
Common Lisp, Visual Basic, PHP, PowerShell, Emacs, Haskell, Perl, Python,
|
||||
Ruby, C#, NodeJS, Java, GO, C++, OCaml, Lua, Rust, Delphi, Free Pascal & Vala
|
||||
ready either in main code, or provided externally by the community).
|
||||
|
||||
- Native support for all popular platforms: Windows, Mac OSX, iOS, Android,
|
||||
Linux, \*BSD, Solaris, etc.
|
||||
|
||||
- Thread-safe by design.
|
||||
|
||||
- Special support for embedding into firmware or OS kernel.
|
||||
|
||||
- High performance & suitable for malware analysis (capable of handling various
|
||||
X86 malware tricks).
|
||||
|
||||
- Distributed under the open source BSD license.
|
||||
|
||||
Further information is available at https://www.capstone-engine.org
|
||||
|
||||
|
||||
Compile
|
||||
-------
|
||||
|
||||
See [BUILDING.md](BUILDING.md) file for how to compile and install Capstone.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
- Useful links and tutorials: [docs/README](docs/README)
|
||||
- Software architecture overview: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
|
||||
- Testing documentation: [tests/README.md](tests/README.md)
|
||||
- Updater (Auto-Sync) documentation: [suite/auto-sync/README.md](suite/auto-sync/README.md)
|
||||
|
||||
Contributing
|
||||
----
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for an intro.
|
||||
|
||||
Fuzz
|
||||
----
|
||||
|
||||
See suite/fuzz/README.md for more information.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This project is released under the BSD license. If you redistribute the binary
|
||||
or source code of Capstone, please attach file LICENSE.TXT with your products.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
* Version 6 - 2024
|
||||
|
||||
Release v6 was sponsored by RizinOrg (https://rizin.re)
|
||||
|
||||
----------------------------
|
||||
* Version 5 - July 5th, 2023
|
||||
|
||||
The TriCore module in release v5 was sponsored by RizinOrg (https://rizin.re)
|
||||
|
||||
------------------------------------
|
||||
* Version 4.0.1 - January 10th, 2019
|
||||
|
||||
Release 4.0.1 was sponsored by the following companies (in no particular order).
|
||||
|
||||
- NowSecure: https://www.nowsecure.com
|
||||
- Verichains: https://verichains.io
|
||||
- Vsec: https://vsec.com.vn
|
||||
|
||||
-----------------------------------
|
||||
* Version 4.0 - December 18th, 2018
|
||||
|
||||
Capstone 4.0 version marks 5 years of the project!
|
||||
This release was sponsored by the following companies (in no particular order).
|
||||
|
||||
- Thinkst Canary: https://canary.tools
|
||||
- NowSecure: https://www.nowsecure.com
|
||||
- ECQ: https://e-cq.net
|
||||
- Senrio: https://senr.io
|
||||
- GracefulBits: https://gracefulbits.com
|
||||
- Catena Cyber: https://catenacyber.fr
|
||||
+588
@@ -0,0 +1,588 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#include <stdarg.h>
|
||||
#if defined(CAPSTONE_HAS_OSXKERNEL)
|
||||
#include <Availability.h>
|
||||
#include <libkern/libkern.h>
|
||||
#include <i386/limits.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "SStream.h"
|
||||
#include "cs_priv.h"
|
||||
#include "utils.h"
|
||||
|
||||
static size_t SStream_remaining(SStream *ss)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->index >= SSTREAM_BUF_LEN) {
|
||||
ss->index = SSTREAM_BUF_LEN - 1;
|
||||
ss->buffer[ss->index] = '\0';
|
||||
return 0;
|
||||
}
|
||||
return SSTREAM_BUF_LEN - ss->index - 1;
|
||||
}
|
||||
|
||||
static void SStream_concat_raw(SStream *ss, const char *s, size_t len)
|
||||
{
|
||||
size_t remaining = SStream_remaining(ss);
|
||||
if (len > remaining) {
|
||||
len = remaining;
|
||||
}
|
||||
if (len > 0) {
|
||||
memcpy(ss->buffer + ss->index, s, len);
|
||||
ss->index += len;
|
||||
}
|
||||
ss->buffer[ss->index] = '\0';
|
||||
}
|
||||
|
||||
static void SStream_concat1_raw(SStream *ss, char c)
|
||||
{
|
||||
if (SStream_remaining(ss) == 0) {
|
||||
return;
|
||||
}
|
||||
ss->buffer[ss->index] = c;
|
||||
ss->index++;
|
||||
ss->buffer[ss->index] = '\0';
|
||||
}
|
||||
|
||||
static void SStream_close_markup(SStream *ss)
|
||||
{
|
||||
if (ss->markup_stream && ss->prefixed_by_markup) {
|
||||
SStream_concat1_raw(ss, '>');
|
||||
}
|
||||
}
|
||||
|
||||
void SStream_Init(SStream *ss)
|
||||
{
|
||||
assert(ss);
|
||||
ss->index = 0;
|
||||
memset(ss->buffer, 0, sizeof(ss->buffer));
|
||||
ss->is_closed = false;
|
||||
ss->markup_stream = false;
|
||||
ss->prefixed_by_markup = false;
|
||||
ss->unsigned_num = false;
|
||||
}
|
||||
|
||||
void SStream_opt_unum(SStream *ss, bool print_unsigned_numbers)
|
||||
{
|
||||
assert(ss);
|
||||
ss->unsigned_num = print_unsigned_numbers;
|
||||
}
|
||||
|
||||
/// Returns the a pointer to the internal string buffer of the stream.
|
||||
/// For reading only.
|
||||
const char *SStream_rbuf(const SStream *ss)
|
||||
{
|
||||
assert(ss);
|
||||
return ss->buffer;
|
||||
}
|
||||
|
||||
/// Searches in the stream for the first (from the left) occurrence of @elem and replaces
|
||||
/// it with @repl. It returns the pointer *after* the replaced character
|
||||
/// or NULL if no character was replaced.
|
||||
///
|
||||
/// It will never replace the final \0 byte in the stream buffer.
|
||||
const char *SStream_replc(const SStream *ss, char elem, char repl)
|
||||
{
|
||||
assert(ss);
|
||||
char *found = strchr(ss->buffer, elem);
|
||||
if (!found || found == ss->buffer + (SSTREAM_BUF_LEN - 1)) {
|
||||
return NULL;
|
||||
}
|
||||
*found = repl;
|
||||
found++;
|
||||
return found;
|
||||
}
|
||||
|
||||
/// Searches in the stream for the first (from the left) occurrence of @chr and replaces
|
||||
/// it with @rstr.
|
||||
void SStream_replc_str(SStream *ss, char chr, const char *rstr)
|
||||
{
|
||||
assert(ss && rstr);
|
||||
char *found = strchr(ss->buffer, chr);
|
||||
if (!found || found == ss->buffer + (SSTREAM_BUF_LEN - 1)) {
|
||||
return;
|
||||
}
|
||||
size_t post_len = strlen(found + 1);
|
||||
size_t buf_str_len = strlen(ss->buffer);
|
||||
size_t repl_len = strlen(rstr);
|
||||
if (repl_len - 1 + buf_str_len >= SSTREAM_BUF_LEN) {
|
||||
return;
|
||||
}
|
||||
memmove(found + repl_len, found + 1, post_len);
|
||||
memcpy(found, rstr, repl_len);
|
||||
ss->index = strlen(ss->buffer);
|
||||
}
|
||||
|
||||
/// Removes the space characters '\t' and ' ' from the beginning of the stream buffer.
|
||||
void SStream_trimls(SStream *ss)
|
||||
{
|
||||
assert(ss);
|
||||
size_t buf_off = 0;
|
||||
/// Remove leading spaces
|
||||
while (ss->buffer[buf_off] == ' ' || ss->buffer[buf_off] == '\t') {
|
||||
buf_off++;
|
||||
}
|
||||
if (buf_off > 0) {
|
||||
memmove(ss->buffer, ss->buffer + buf_off,
|
||||
SSTREAM_BUF_LEN - buf_off);
|
||||
ss->index -= buf_off;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the mnemonic to @mnem_buf and the operand string into @op_str_buf from the stream buffer.
|
||||
/// The mnemonic is everything up until the first ' ' or '\t' character.
|
||||
/// The operand string is everything after the first ' ' or '\t' sequence.
|
||||
void SStream_extract_mnem_opstr(const SStream *ss, char *mnem_buf,
|
||||
size_t mnem_buf_size, char *op_str_buf,
|
||||
size_t op_str_buf_size)
|
||||
{
|
||||
assert(ss && mnem_buf && mnem_buf_size > 0 && op_str_buf &&
|
||||
op_str_buf_size > 0);
|
||||
size_t off = 0;
|
||||
// Copy all non space chars to as mnemonic.
|
||||
while (ss->buffer[off] && ss->buffer[off] != ' ' &&
|
||||
ss->buffer[off] != '\t') {
|
||||
if (off < mnem_buf_size - 1) {
|
||||
// Only copy if there is space left.
|
||||
mnem_buf[off] = ss->buffer[off];
|
||||
}
|
||||
off++;
|
||||
}
|
||||
if (!ss->buffer[off]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate until next non space char.
|
||||
do {
|
||||
off++;
|
||||
} while (ss->buffer[off] &&
|
||||
(ss->buffer[off] == ' ' || ss->buffer[off] == '\t'));
|
||||
|
||||
if (!ss->buffer[off]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy all follow up characters as op_str
|
||||
const char *ss_op_str = ss->buffer + off;
|
||||
off = 0;
|
||||
while (ss_op_str[off] && off < op_str_buf_size - 1) {
|
||||
op_str_buf[off] = ss_op_str[off];
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
/// Empty the stream @ss to given @file (stdin/stderr).
|
||||
/// @file can be NULL. Then the buffer content is not emitted.
|
||||
void SStream_Flush(SStream *ss, FILE *file)
|
||||
{
|
||||
assert(ss);
|
||||
if (file) {
|
||||
fprintf(file, "%s\n", ss->buffer);
|
||||
}
|
||||
SStream_Init(ss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the output stream. Every write attempt is accepted again.
|
||||
*/
|
||||
void SStream_Open(SStream *ss)
|
||||
{
|
||||
assert(ss);
|
||||
ss->is_closed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the output stream. Every write attempt is ignored.
|
||||
*/
|
||||
void SStream_Close(SStream *ss)
|
||||
{
|
||||
assert(ss);
|
||||
ss->is_closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the string \p s to the buffer of \p ss and terminate it with a '\\0' byte.
|
||||
*/
|
||||
void SStream_concat0(SStream *ss, const char *s)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
assert(ss && s);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (s[0] == '\0')
|
||||
return;
|
||||
|
||||
SStream_concat_raw(ss, s, strlen(s));
|
||||
SStream_close_markup(ss);
|
||||
#else
|
||||
ss->buffer[ss->index] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the single char \p c to the buffer of \p ss.
|
||||
*/
|
||||
void SStream_concat1(SStream *ss, const char c)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (c == '\0')
|
||||
return;
|
||||
|
||||
SStream_concat1_raw(ss, c);
|
||||
SStream_close_markup(ss);
|
||||
#else
|
||||
ss->buffer[ss->index] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all strings given to the buffer of \p ss according to formatting \p fmt.
|
||||
*/
|
||||
void SStream_concat(SStream *ss, const char *fmt, ...)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
assert(ss && fmt);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
va_list ap;
|
||||
int ret;
|
||||
size_t remaining = SStream_remaining(ss);
|
||||
if (remaining == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = cs_vsnprintf(ss->buffer + ss->index, remaining + 1, fmt, ap);
|
||||
va_end(ap);
|
||||
if (ret < 0) {
|
||||
ss->buffer[ss->index] = '\0';
|
||||
return;
|
||||
}
|
||||
if ((size_t)ret > remaining) {
|
||||
ss->index += remaining;
|
||||
} else {
|
||||
ss->index += (size_t)ret;
|
||||
}
|
||||
SStream_close_markup(ss);
|
||||
#else
|
||||
ss->buffer[ss->index] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
// print number with prefix #
|
||||
void printInt64Bang(SStream *ss, int64_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt64Bang(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat1(ss, '#');
|
||||
printInt64(ss, val);
|
||||
}
|
||||
|
||||
void printUInt64Bang(SStream *ss, uint64_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat1(ss, '#');
|
||||
printUInt64(ss, val);
|
||||
}
|
||||
|
||||
// print number
|
||||
void printInt64(SStream *ss, int64_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt64(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx64, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRIu64, val);
|
||||
} else {
|
||||
if (val < -HEX_THRESHOLD) {
|
||||
if (val == INT64_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx64,
|
||||
(uint64_t)INT64_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx64,
|
||||
(uint64_t)-val);
|
||||
} else
|
||||
SStream_concat(ss, "-%" PRIu64, -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printUInt64(SStream *ss, uint64_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx64, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRIu64, val);
|
||||
}
|
||||
|
||||
// print number in decimal mode
|
||||
void printInt32BangDec(SStream *ss, int32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0)
|
||||
SStream_concat(ss, "#%" PRIu32, val);
|
||||
else {
|
||||
if (val == INT32_MIN)
|
||||
SStream_concat(ss, "#-%" PRIu32, val);
|
||||
else
|
||||
SStream_concat(ss, "#-%" PRIu32, (uint32_t)-val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt32Bang(SStream *ss, int32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt32Bang(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat1(ss, '#');
|
||||
printInt32(ss, val);
|
||||
}
|
||||
|
||||
void printUInt8(SStream *ss, uint8_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx8, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRIu8, val);
|
||||
}
|
||||
|
||||
void printUInt16(SStream *ss, uint16_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx16, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRIu16, val);
|
||||
}
|
||||
|
||||
void printInt8(SStream *ss, int8_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt8(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx8, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRId8, val);
|
||||
} else {
|
||||
if (val < -HEX_THRESHOLD) {
|
||||
if (val == INT8_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx8,
|
||||
(uint8_t)INT8_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx8, (int8_t)-val);
|
||||
} else
|
||||
SStream_concat(ss, "-%" PRIu8, -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt16(SStream *ss, int16_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt16(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx16, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRId16, val);
|
||||
} else {
|
||||
if (val < -HEX_THRESHOLD) {
|
||||
if (val == INT16_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx16,
|
||||
(uint16_t)INT16_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx16,
|
||||
(int16_t)-val);
|
||||
} else
|
||||
SStream_concat(ss, "-%" PRIu16, -val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt16HexOffset(SStream *ss, int16_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt16(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
SStream_concat(ss, "+0x%" PRIx16, val);
|
||||
} else {
|
||||
if (val == INT16_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx16,
|
||||
(uint16_t)INT16_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx16, (int16_t)-val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt32(SStream *ss, int32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt32(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%" PRIx32, val);
|
||||
else
|
||||
SStream_concat(ss, "%" PRId32, val);
|
||||
} else {
|
||||
if (val < -HEX_THRESHOLD) {
|
||||
if (val == INT32_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx32,
|
||||
(uint32_t)INT32_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx32,
|
||||
(int32_t)-val);
|
||||
} else {
|
||||
SStream_concat(ss, "-%" PRIu32, (uint32_t)-val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printInt32HexOffset(SStream *ss, int32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
if (ss->unsigned_num) {
|
||||
printUInt32(ss, val);
|
||||
return;
|
||||
}
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
SStream_concat(ss, "+0x%" PRIx32, val);
|
||||
} else {
|
||||
if (val == INT32_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx32,
|
||||
(uint32_t)INT32_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx32, (int32_t)-val);
|
||||
}
|
||||
}
|
||||
|
||||
void printInt32Hex(SStream *ss, int32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val >= 0) {
|
||||
SStream_concat(ss, "0x%" PRIx32, val);
|
||||
} else {
|
||||
if (val == INT32_MIN)
|
||||
SStream_concat(ss, "-0x%" PRIx32,
|
||||
(uint32_t)INT32_MAX + 1);
|
||||
else
|
||||
SStream_concat(ss, "-0x%" PRIx32, (int32_t)-val);
|
||||
}
|
||||
}
|
||||
|
||||
void printUInt32Bang(SStream *ss, uint32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat1(ss, '#');
|
||||
printUInt32(ss, val);
|
||||
}
|
||||
|
||||
void printUInt32(SStream *ss, uint32_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
if (val > HEX_THRESHOLD)
|
||||
SStream_concat(ss, "0x%x", val);
|
||||
else
|
||||
SStream_concat(ss, "%u", val);
|
||||
}
|
||||
|
||||
void printFloat(SStream *ss, float val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat(ss, "%e", val);
|
||||
}
|
||||
|
||||
void printfFloat(SStream *ss, const char *fmt, float val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat(ss, fmt, val);
|
||||
}
|
||||
|
||||
void printFloatBang(SStream *ss, float val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat(ss, "#%e", val);
|
||||
}
|
||||
|
||||
void printExpr(SStream *ss, uint64_t val)
|
||||
{
|
||||
assert(ss);
|
||||
SSTREAM_RETURN_IF_CLOSED(ss);
|
||||
SStream_concat(ss, "%" PRIu64, val);
|
||||
}
|
||||
|
||||
SStream *markup_OS(SStream *OS, SStreamMarkup style)
|
||||
{
|
||||
assert(OS);
|
||||
|
||||
if (OS->is_closed || !OS->markup_stream) {
|
||||
return OS;
|
||||
}
|
||||
OS->markup_stream = false; // Disable temporarily.
|
||||
switch (style) {
|
||||
default:
|
||||
SStream_concat0(OS, "<UNKNOWN:");
|
||||
return OS;
|
||||
case Markup_Immediate:
|
||||
SStream_concat0(OS, "<imm:");
|
||||
break;
|
||||
case Markup_Register:
|
||||
SStream_concat0(OS, "<reg:");
|
||||
break;
|
||||
case Markup_Target:
|
||||
SStream_concat0(OS, "<tar:");
|
||||
break;
|
||||
case Markup_Memory:
|
||||
SStream_concat0(OS, "<mem:");
|
||||
break;
|
||||
}
|
||||
OS->markup_stream = true;
|
||||
OS->prefixed_by_markup = true;
|
||||
return OS;
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_SSTREAM_H_
|
||||
#define CS_SSTREAM_H_
|
||||
|
||||
#include "include/capstone/platform.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum {
|
||||
Markup_Immediate,
|
||||
Markup_Register,
|
||||
Markup_Target,
|
||||
Markup_Memory,
|
||||
} SStreamMarkup;
|
||||
|
||||
#define SSTREAM_BUF_LEN 512
|
||||
|
||||
typedef struct SStream {
|
||||
char buffer[SSTREAM_BUF_LEN];
|
||||
size_t index;
|
||||
bool is_closed;
|
||||
bool markup_stream; ///< If true, markups to the stream are allowed.
|
||||
bool prefixed_by_markup; ///< Set after the stream wrote a markup for an operand.
|
||||
bool unsigned_num; ///< Print all numbers as unsigned. Set with CS_OPT_UNSIGNED.
|
||||
} SStream;
|
||||
|
||||
#define SSTREAM_RETURN_IF_CLOSED(OS) \
|
||||
do { \
|
||||
if (OS->is_closed) \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
void SStream_Init(SStream *ss);
|
||||
void SStream_opt_unum(SStream *ss, bool print_unsigned_numbers);
|
||||
|
||||
const char *SStream_replc(const SStream *ss, char elem, char repl);
|
||||
|
||||
void SStream_replc_str(SStream *ss, char chr, const char *rstr);
|
||||
|
||||
const char *SStream_rbuf(const SStream *ss);
|
||||
|
||||
void SStream_extract_mnem_opstr(const SStream *ss, char *mnem_buf,
|
||||
size_t mnem_buf_size, char *op_str_buf,
|
||||
size_t op_str_buf_size);
|
||||
|
||||
void SStream_trimls(SStream *ss);
|
||||
|
||||
void SStream_Flush(SStream *ss, FILE *file);
|
||||
|
||||
void SStream_Open(SStream *ss);
|
||||
|
||||
void SStream_Close(SStream *ss);
|
||||
|
||||
void SStream_concat(SStream *ss, const char *fmt, ...);
|
||||
|
||||
void SStream_concat0(SStream *ss, const char *s);
|
||||
|
||||
void SStream_concat1(SStream *ss, const char c);
|
||||
|
||||
void printInt64Bang(SStream *O, int64_t val);
|
||||
|
||||
void printUInt64Bang(SStream *O, uint64_t val);
|
||||
|
||||
void printInt64(SStream *O, int64_t val);
|
||||
void printUInt64(SStream *O, uint64_t val);
|
||||
|
||||
void printInt32Bang(SStream *O, int32_t val);
|
||||
|
||||
void printInt8(SStream *O, int8_t val);
|
||||
void printInt16(SStream *O, int16_t val);
|
||||
void printInt16HexOffset(SStream *O, int16_t val);
|
||||
|
||||
void printInt32(SStream *O, int32_t val);
|
||||
void printInt32Hex(SStream *ss, int32_t val);
|
||||
void printInt32HexOffset(SStream *ss, int32_t val);
|
||||
|
||||
void printUInt32Bang(SStream *O, uint32_t val);
|
||||
|
||||
void printUInt8(SStream *ss, uint8_t val);
|
||||
void printUInt16(SStream *ss, uint16_t val);
|
||||
void printUInt32(SStream *O, uint32_t val);
|
||||
|
||||
// print number in decimal mode
|
||||
void printInt32BangDec(SStream *O, int32_t val);
|
||||
|
||||
void printFloat(SStream *O, float val);
|
||||
|
||||
void printfFloat(SStream *ss, const char *fmt, float val);
|
||||
|
||||
void printFloatBang(SStream *O, float val);
|
||||
|
||||
void printExpr(SStream *O, uint64_t val);
|
||||
|
||||
SStream *markup_OS(SStream *OS, SStreamMarkup style);
|
||||
|
||||
#endif
|
||||
+1002
File diff suppressed because it is too large
Load Diff
+175
@@ -0,0 +1,175 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===-- AArch64BaseInfo.cpp - AArch64 Base encoding information------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides basic encoding and assembly information for AArch64.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include <capstone/platform.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "AArch64BaseInfo.h"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
#define GET_AT_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_AT_IMPL
|
||||
|
||||
#define GET_DBNXS_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_DBNXS_IMPL
|
||||
|
||||
#define GET_DB_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_DB_IMPL
|
||||
|
||||
#define GET_DC_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_DC_IMPL
|
||||
|
||||
#define GET_IC_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_IC_IMPL
|
||||
|
||||
#define GET_ISB_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_ISB_IMPL
|
||||
|
||||
#define GET_TSB_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_TSB_IMPL
|
||||
|
||||
#define GET_PRCTX_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_PRCTX_IMPL
|
||||
|
||||
#define GET_PRFM_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_PRFM_IMPL
|
||||
|
||||
#define GET_SVEPRFM_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_SVEPRFM_IMPL
|
||||
|
||||
#define GET_RPRFM_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_RPRFM_IMPL
|
||||
|
||||
// namespace AArch64RPRFM
|
||||
// namespace llvm
|
||||
|
||||
#define GET_SVEPREDPAT_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_SVEPREDPAT_IMPL
|
||||
|
||||
#define GET_SVEVECLENSPECIFIER_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_SVEVECLENSPECIFIER_IMPL
|
||||
|
||||
// namespace AArch64SVEVecLenSpecifier
|
||||
// namespace llvm
|
||||
|
||||
#define GET_EXACTFPIMM_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_EXACTFPIMM_IMPL
|
||||
|
||||
#define GET_PSTATEIMM0_15_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_PSTATEIMM0_15_IMPL
|
||||
|
||||
#define GET_PSTATEIMM0_1_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_PSTATEIMM0_1_IMPL
|
||||
|
||||
#define GET_PSB_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_PSB_IMPL
|
||||
|
||||
#define GET_BTI_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_BTI_IMPL
|
||||
|
||||
#define SysReg AArch64SysReg_SysReg
|
||||
#define GET_SYSREG_IMPL
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_SYSREG_IMPL
|
||||
|
||||
#undef SysReg
|
||||
|
||||
// return a string representing the number X
|
||||
// NOTE: result must be big enough to contain the data
|
||||
static void utostr(uint64_t X, bool isNeg, char *result)
|
||||
{
|
||||
char Buffer[22];
|
||||
char *BufPtr = Buffer + 21;
|
||||
|
||||
Buffer[21] = '\0';
|
||||
if (X == 0)
|
||||
*--BufPtr = '0'; // Handle special case...
|
||||
|
||||
while (X) {
|
||||
*--BufPtr = X % 10 + '0';
|
||||
X /= 10;
|
||||
}
|
||||
|
||||
if (isNeg)
|
||||
*--BufPtr = '-'; // Add negative sign...
|
||||
|
||||
// suppose that result is big enough
|
||||
strncpy(result, BufPtr, sizeof(Buffer));
|
||||
}
|
||||
|
||||
// NOTE: result must be big enough to contain the result
|
||||
void AArch64SysReg_genericRegisterString(uint32_t Bits, char *result)
|
||||
{
|
||||
CS_ASSERT_RET(Bits < 0x10000);
|
||||
char Op0Str[32], Op1Str[32], CRnStr[32], CRmStr[32], Op2Str[32];
|
||||
int dummy;
|
||||
uint32_t Op0 = (Bits >> 14) & 0x3;
|
||||
uint32_t Op1 = (Bits >> 11) & 0x7;
|
||||
uint32_t CRn = (Bits >> 7) & 0xf;
|
||||
uint32_t CRm = (Bits >> 3) & 0xf;
|
||||
uint32_t Op2 = Bits & 0x7;
|
||||
|
||||
utostr(Op0, false, Op0Str);
|
||||
utostr(Op1, false, Op1Str);
|
||||
utostr(Op2, false, Op2Str);
|
||||
utostr(CRn, false, CRnStr);
|
||||
utostr(CRm, false, CRmStr);
|
||||
|
||||
dummy = cs_snprintf(result, AARCH64_GRS_LEN, "s%s_%s_c%s_c%s_%s",
|
||||
Op0Str, Op1Str, CRnStr, CRmStr, Op2Str);
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
#define GET_TLBITable_IMPL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_TLBITable_IMPL
|
||||
|
||||
#define GET_SVCR_IMPL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
#undef GET_SVCR_IMPL
|
||||
+986
@@ -0,0 +1,986 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===-- AArch64BaseInfo.h - Top level definitions for AArch64 ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains small standalone helper functions and enum definitions for
|
||||
// the AArch64 target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64BASEINFO_H
|
||||
#define LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64BASEINFO_H
|
||||
|
||||
// FIXME: Is it easiest to fix this layering violation by moving the .inc
|
||||
// #includes from AArch64MCTargetDesc.h to here?
|
||||
#include <capstone/platform.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../MCInstPrinter.h"
|
||||
|
||||
#include "../../utils.h"
|
||||
#include "capstone/aarch64.h"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "AArch64GenSubtargetInfo.inc"
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "AArch64GenRegisterInfo.inc"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "AArch64GenInstrInfo.inc"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
static inline unsigned getWRegFromXReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case AArch64_X0:
|
||||
return AArch64_W0;
|
||||
case AArch64_X1:
|
||||
return AArch64_W1;
|
||||
case AArch64_X2:
|
||||
return AArch64_W2;
|
||||
case AArch64_X3:
|
||||
return AArch64_W3;
|
||||
case AArch64_X4:
|
||||
return AArch64_W4;
|
||||
case AArch64_X5:
|
||||
return AArch64_W5;
|
||||
case AArch64_X6:
|
||||
return AArch64_W6;
|
||||
case AArch64_X7:
|
||||
return AArch64_W7;
|
||||
case AArch64_X8:
|
||||
return AArch64_W8;
|
||||
case AArch64_X9:
|
||||
return AArch64_W9;
|
||||
case AArch64_X10:
|
||||
return AArch64_W10;
|
||||
case AArch64_X11:
|
||||
return AArch64_W11;
|
||||
case AArch64_X12:
|
||||
return AArch64_W12;
|
||||
case AArch64_X13:
|
||||
return AArch64_W13;
|
||||
case AArch64_X14:
|
||||
return AArch64_W14;
|
||||
case AArch64_X15:
|
||||
return AArch64_W15;
|
||||
case AArch64_X16:
|
||||
return AArch64_W16;
|
||||
case AArch64_X17:
|
||||
return AArch64_W17;
|
||||
case AArch64_X18:
|
||||
return AArch64_W18;
|
||||
case AArch64_X19:
|
||||
return AArch64_W19;
|
||||
case AArch64_X20:
|
||||
return AArch64_W20;
|
||||
case AArch64_X21:
|
||||
return AArch64_W21;
|
||||
case AArch64_X22:
|
||||
return AArch64_W22;
|
||||
case AArch64_X23:
|
||||
return AArch64_W23;
|
||||
case AArch64_X24:
|
||||
return AArch64_W24;
|
||||
case AArch64_X25:
|
||||
return AArch64_W25;
|
||||
case AArch64_X26:
|
||||
return AArch64_W26;
|
||||
case AArch64_X27:
|
||||
return AArch64_W27;
|
||||
case AArch64_X28:
|
||||
return AArch64_W28;
|
||||
case AArch64_FP:
|
||||
return AArch64_W29;
|
||||
case AArch64_LR:
|
||||
return AArch64_W30;
|
||||
case AArch64_SP:
|
||||
return AArch64_WSP;
|
||||
case AArch64_XZR:
|
||||
return AArch64_WZR;
|
||||
}
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
static inline unsigned getXRegFromWReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case AArch64_W0:
|
||||
return AArch64_X0;
|
||||
case AArch64_W1:
|
||||
return AArch64_X1;
|
||||
case AArch64_W2:
|
||||
return AArch64_X2;
|
||||
case AArch64_W3:
|
||||
return AArch64_X3;
|
||||
case AArch64_W4:
|
||||
return AArch64_X4;
|
||||
case AArch64_W5:
|
||||
return AArch64_X5;
|
||||
case AArch64_W6:
|
||||
return AArch64_X6;
|
||||
case AArch64_W7:
|
||||
return AArch64_X7;
|
||||
case AArch64_W8:
|
||||
return AArch64_X8;
|
||||
case AArch64_W9:
|
||||
return AArch64_X9;
|
||||
case AArch64_W10:
|
||||
return AArch64_X10;
|
||||
case AArch64_W11:
|
||||
return AArch64_X11;
|
||||
case AArch64_W12:
|
||||
return AArch64_X12;
|
||||
case AArch64_W13:
|
||||
return AArch64_X13;
|
||||
case AArch64_W14:
|
||||
return AArch64_X14;
|
||||
case AArch64_W15:
|
||||
return AArch64_X15;
|
||||
case AArch64_W16:
|
||||
return AArch64_X16;
|
||||
case AArch64_W17:
|
||||
return AArch64_X17;
|
||||
case AArch64_W18:
|
||||
return AArch64_X18;
|
||||
case AArch64_W19:
|
||||
return AArch64_X19;
|
||||
case AArch64_W20:
|
||||
return AArch64_X20;
|
||||
case AArch64_W21:
|
||||
return AArch64_X21;
|
||||
case AArch64_W22:
|
||||
return AArch64_X22;
|
||||
case AArch64_W23:
|
||||
return AArch64_X23;
|
||||
case AArch64_W24:
|
||||
return AArch64_X24;
|
||||
case AArch64_W25:
|
||||
return AArch64_X25;
|
||||
case AArch64_W26:
|
||||
return AArch64_X26;
|
||||
case AArch64_W27:
|
||||
return AArch64_X27;
|
||||
case AArch64_W28:
|
||||
return AArch64_X28;
|
||||
case AArch64_W29:
|
||||
return AArch64_FP;
|
||||
case AArch64_W30:
|
||||
return AArch64_LR;
|
||||
case AArch64_WSP:
|
||||
return AArch64_SP;
|
||||
case AArch64_WZR:
|
||||
return AArch64_XZR;
|
||||
}
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
static inline unsigned getXRegFromXRegTuple(unsigned RegTuple)
|
||||
{
|
||||
switch (RegTuple) {
|
||||
case AArch64_X0_X1_X2_X3_X4_X5_X6_X7:
|
||||
return AArch64_X0;
|
||||
case AArch64_X2_X3_X4_X5_X6_X7_X8_X9:
|
||||
return AArch64_X2;
|
||||
case AArch64_X4_X5_X6_X7_X8_X9_X10_X11:
|
||||
return AArch64_X4;
|
||||
case AArch64_X6_X7_X8_X9_X10_X11_X12_X13:
|
||||
return AArch64_X6;
|
||||
case AArch64_X8_X9_X10_X11_X12_X13_X14_X15:
|
||||
return AArch64_X8;
|
||||
case AArch64_X10_X11_X12_X13_X14_X15_X16_X17:
|
||||
return AArch64_X10;
|
||||
case AArch64_X12_X13_X14_X15_X16_X17_X18_X19:
|
||||
return AArch64_X12;
|
||||
case AArch64_X14_X15_X16_X17_X18_X19_X20_X21:
|
||||
return AArch64_X14;
|
||||
case AArch64_X16_X17_X18_X19_X20_X21_X22_X23:
|
||||
return AArch64_X16;
|
||||
case AArch64_X18_X19_X20_X21_X22_X23_X24_X25:
|
||||
return AArch64_X18;
|
||||
case AArch64_X20_X21_X22_X23_X24_X25_X26_X27:
|
||||
return AArch64_X20;
|
||||
case AArch64_X22_X23_X24_X25_X26_X27_X28_FP:
|
||||
return AArch64_X22;
|
||||
}
|
||||
// For anything else, return it unchanged.
|
||||
return RegTuple;
|
||||
}
|
||||
|
||||
static inline unsigned getBRegFromDReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case AArch64_D0:
|
||||
return AArch64_B0;
|
||||
case AArch64_D1:
|
||||
return AArch64_B1;
|
||||
case AArch64_D2:
|
||||
return AArch64_B2;
|
||||
case AArch64_D3:
|
||||
return AArch64_B3;
|
||||
case AArch64_D4:
|
||||
return AArch64_B4;
|
||||
case AArch64_D5:
|
||||
return AArch64_B5;
|
||||
case AArch64_D6:
|
||||
return AArch64_B6;
|
||||
case AArch64_D7:
|
||||
return AArch64_B7;
|
||||
case AArch64_D8:
|
||||
return AArch64_B8;
|
||||
case AArch64_D9:
|
||||
return AArch64_B9;
|
||||
case AArch64_D10:
|
||||
return AArch64_B10;
|
||||
case AArch64_D11:
|
||||
return AArch64_B11;
|
||||
case AArch64_D12:
|
||||
return AArch64_B12;
|
||||
case AArch64_D13:
|
||||
return AArch64_B13;
|
||||
case AArch64_D14:
|
||||
return AArch64_B14;
|
||||
case AArch64_D15:
|
||||
return AArch64_B15;
|
||||
case AArch64_D16:
|
||||
return AArch64_B16;
|
||||
case AArch64_D17:
|
||||
return AArch64_B17;
|
||||
case AArch64_D18:
|
||||
return AArch64_B18;
|
||||
case AArch64_D19:
|
||||
return AArch64_B19;
|
||||
case AArch64_D20:
|
||||
return AArch64_B20;
|
||||
case AArch64_D21:
|
||||
return AArch64_B21;
|
||||
case AArch64_D22:
|
||||
return AArch64_B22;
|
||||
case AArch64_D23:
|
||||
return AArch64_B23;
|
||||
case AArch64_D24:
|
||||
return AArch64_B24;
|
||||
case AArch64_D25:
|
||||
return AArch64_B25;
|
||||
case AArch64_D26:
|
||||
return AArch64_B26;
|
||||
case AArch64_D27:
|
||||
return AArch64_B27;
|
||||
case AArch64_D28:
|
||||
return AArch64_B28;
|
||||
case AArch64_D29:
|
||||
return AArch64_B29;
|
||||
case AArch64_D30:
|
||||
return AArch64_B30;
|
||||
case AArch64_D31:
|
||||
return AArch64_B31;
|
||||
}
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
static inline unsigned getDRegFromBReg(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case AArch64_B0:
|
||||
return AArch64_D0;
|
||||
case AArch64_B1:
|
||||
return AArch64_D1;
|
||||
case AArch64_B2:
|
||||
return AArch64_D2;
|
||||
case AArch64_B3:
|
||||
return AArch64_D3;
|
||||
case AArch64_B4:
|
||||
return AArch64_D4;
|
||||
case AArch64_B5:
|
||||
return AArch64_D5;
|
||||
case AArch64_B6:
|
||||
return AArch64_D6;
|
||||
case AArch64_B7:
|
||||
return AArch64_D7;
|
||||
case AArch64_B8:
|
||||
return AArch64_D8;
|
||||
case AArch64_B9:
|
||||
return AArch64_D9;
|
||||
case AArch64_B10:
|
||||
return AArch64_D10;
|
||||
case AArch64_B11:
|
||||
return AArch64_D11;
|
||||
case AArch64_B12:
|
||||
return AArch64_D12;
|
||||
case AArch64_B13:
|
||||
return AArch64_D13;
|
||||
case AArch64_B14:
|
||||
return AArch64_D14;
|
||||
case AArch64_B15:
|
||||
return AArch64_D15;
|
||||
case AArch64_B16:
|
||||
return AArch64_D16;
|
||||
case AArch64_B17:
|
||||
return AArch64_D17;
|
||||
case AArch64_B18:
|
||||
return AArch64_D18;
|
||||
case AArch64_B19:
|
||||
return AArch64_D19;
|
||||
case AArch64_B20:
|
||||
return AArch64_D20;
|
||||
case AArch64_B21:
|
||||
return AArch64_D21;
|
||||
case AArch64_B22:
|
||||
return AArch64_D22;
|
||||
case AArch64_B23:
|
||||
return AArch64_D23;
|
||||
case AArch64_B24:
|
||||
return AArch64_D24;
|
||||
case AArch64_B25:
|
||||
return AArch64_D25;
|
||||
case AArch64_B26:
|
||||
return AArch64_D26;
|
||||
case AArch64_B27:
|
||||
return AArch64_D27;
|
||||
case AArch64_B28:
|
||||
return AArch64_D28;
|
||||
case AArch64_B29:
|
||||
return AArch64_D29;
|
||||
case AArch64_B30:
|
||||
return AArch64_D30;
|
||||
case AArch64_B31:
|
||||
return AArch64_D31;
|
||||
}
|
||||
// For anything else, return it unchanged.
|
||||
return Reg;
|
||||
}
|
||||
|
||||
static inline bool atomicBarrierDroppedOnZero(unsigned Opcode)
|
||||
{
|
||||
switch (Opcode) {
|
||||
case AArch64_LDADDAB:
|
||||
case AArch64_LDADDAH:
|
||||
case AArch64_LDADDAW:
|
||||
case AArch64_LDADDAX:
|
||||
case AArch64_LDADDALB:
|
||||
case AArch64_LDADDALH:
|
||||
case AArch64_LDADDALW:
|
||||
case AArch64_LDADDALX:
|
||||
case AArch64_LDCLRAB:
|
||||
case AArch64_LDCLRAH:
|
||||
case AArch64_LDCLRAW:
|
||||
case AArch64_LDCLRAX:
|
||||
case AArch64_LDCLRALB:
|
||||
case AArch64_LDCLRALH:
|
||||
case AArch64_LDCLRALW:
|
||||
case AArch64_LDCLRALX:
|
||||
case AArch64_LDEORAB:
|
||||
case AArch64_LDEORAH:
|
||||
case AArch64_LDEORAW:
|
||||
case AArch64_LDEORAX:
|
||||
case AArch64_LDEORALB:
|
||||
case AArch64_LDEORALH:
|
||||
case AArch64_LDEORALW:
|
||||
case AArch64_LDEORALX:
|
||||
case AArch64_LDSETAB:
|
||||
case AArch64_LDSETAH:
|
||||
case AArch64_LDSETAW:
|
||||
case AArch64_LDSETAX:
|
||||
case AArch64_LDSETALB:
|
||||
case AArch64_LDSETALH:
|
||||
case AArch64_LDSETALW:
|
||||
case AArch64_LDSETALX:
|
||||
case AArch64_LDSMAXAB:
|
||||
case AArch64_LDSMAXAH:
|
||||
case AArch64_LDSMAXAW:
|
||||
case AArch64_LDSMAXAX:
|
||||
case AArch64_LDSMAXALB:
|
||||
case AArch64_LDSMAXALH:
|
||||
case AArch64_LDSMAXALW:
|
||||
case AArch64_LDSMAXALX:
|
||||
case AArch64_LDSMINAB:
|
||||
case AArch64_LDSMINAH:
|
||||
case AArch64_LDSMINAW:
|
||||
case AArch64_LDSMINAX:
|
||||
case AArch64_LDSMINALB:
|
||||
case AArch64_LDSMINALH:
|
||||
case AArch64_LDSMINALW:
|
||||
case AArch64_LDSMINALX:
|
||||
case AArch64_LDUMAXAB:
|
||||
case AArch64_LDUMAXAH:
|
||||
case AArch64_LDUMAXAW:
|
||||
case AArch64_LDUMAXAX:
|
||||
case AArch64_LDUMAXALB:
|
||||
case AArch64_LDUMAXALH:
|
||||
case AArch64_LDUMAXALW:
|
||||
case AArch64_LDUMAXALX:
|
||||
case AArch64_LDUMINAB:
|
||||
case AArch64_LDUMINAH:
|
||||
case AArch64_LDUMINAW:
|
||||
case AArch64_LDUMINAX:
|
||||
case AArch64_LDUMINALB:
|
||||
case AArch64_LDUMINALH:
|
||||
case AArch64_LDUMINALW:
|
||||
case AArch64_LDUMINALX:
|
||||
case AArch64_SWPAB:
|
||||
case AArch64_SWPAH:
|
||||
case AArch64_SWPAW:
|
||||
case AArch64_SWPAX:
|
||||
case AArch64_SWPALB:
|
||||
case AArch64_SWPALH:
|
||||
case AArch64_SWPALW:
|
||||
case AArch64_SWPALX:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// MOVE-NOTICE: AArch64CC_CondCode : moved to aarch64.h
|
||||
// MOVE-NOTICE: AArch64CC_getCondCodeName : moved to aarch64.h
|
||||
// MOVE-NOTICE: AArch64CC_getInvertedCondCode : moved to aarch64.h
|
||||
// MOVE-NOTICE: AArch64CC_getNZCVToSatisfyCondCode : moved to aarch64.h
|
||||
|
||||
typedef struct SysAlias {
|
||||
const char *Name;
|
||||
aarch64_sysop_alias SysAlias;
|
||||
uint16_t Encoding;
|
||||
aarch64_insn_group FeaturesRequired[3];
|
||||
} SysAlias;
|
||||
|
||||
typedef struct SysAliasReg {
|
||||
const char *Name;
|
||||
aarch64_sysop_reg SysReg;
|
||||
uint16_t Encoding;
|
||||
bool NeedsReg;
|
||||
aarch64_insn_group FeaturesRequired[3];
|
||||
} SysAliasReg;
|
||||
|
||||
typedef struct SysAliasImm {
|
||||
const char *Name;
|
||||
aarch64_sysop_imm SysImm;
|
||||
uint16_t ImmValue;
|
||||
uint16_t Encoding;
|
||||
aarch64_insn_group FeaturesRequired[3];
|
||||
} SysAliasImm;
|
||||
|
||||
// CS namespace begin: AArch64SVCR
|
||||
|
||||
#define AArch64SVCR_SVCR SysAlias
|
||||
|
||||
#define GET_SVCR_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64SVCR
|
||||
|
||||
// CS namespace begin: AArch64AT
|
||||
|
||||
#define AArch64AT_AT SysAlias
|
||||
|
||||
#define GET_AT_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64AT
|
||||
|
||||
// CS namespace begin: AArch64DB
|
||||
|
||||
#define AArch64DB_DB SysAlias
|
||||
|
||||
#define GET_DB_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64DB
|
||||
|
||||
// CS namespace begin: AArch64DBnXS
|
||||
|
||||
#define AArch64DBnXS_DBnXS SysAliasImm
|
||||
|
||||
#define GET_DBNXS_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64DBnXS
|
||||
|
||||
// CS namespace begin: AArch64DC
|
||||
|
||||
#define AArch64DC_DC SysAlias
|
||||
|
||||
#define GET_DC_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64DC
|
||||
|
||||
// CS namespace begin: AArch64IC
|
||||
|
||||
#define AArch64IC_IC SysAliasReg
|
||||
|
||||
#define GET_IC_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64IC
|
||||
|
||||
// CS namespace begin: AArch64ISB
|
||||
|
||||
#define AArch64ISB_ISB SysAlias
|
||||
|
||||
#define GET_ISB_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64ISB
|
||||
|
||||
// CS namespace begin: AArch64TSB
|
||||
|
||||
#define AArch64TSB_TSB SysAlias
|
||||
|
||||
#define GET_TSB_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64TSB
|
||||
|
||||
// CS namespace begin: AArch64PRFM
|
||||
|
||||
#define AArch64PRFM_PRFM SysAlias
|
||||
|
||||
#define GET_PRFM_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64PRFM
|
||||
|
||||
// CS namespace begin: AArch64SVEPRFM
|
||||
|
||||
#define AArch64SVEPRFM_SVEPRFM SysAlias
|
||||
|
||||
#define GET_SVEPRFM_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64SVEPRFM
|
||||
|
||||
// CS namespace begin: AArch64RPRFM
|
||||
|
||||
#define AArch64RPRFM_RPRFM SysAlias
|
||||
|
||||
#define GET_RPRFM_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64RPRFM
|
||||
|
||||
// CS namespace begin: AArch64SVEPredPattern
|
||||
|
||||
typedef struct SVEPREDPAT {
|
||||
const char *Name;
|
||||
aarch64_sysop_alias SysAlias;
|
||||
uint16_t Encoding;
|
||||
} AArch64SVEPredPattern_SVEPREDPAT;
|
||||
|
||||
#define GET_SVEPREDPAT_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64SVEPredPattern
|
||||
|
||||
// CS namespace begin: AArch64SVEVecLenSpecifier
|
||||
|
||||
typedef struct SVEVECLENSPECIFIER {
|
||||
const char *Name;
|
||||
aarch64_sysop_alias SysAlias;
|
||||
uint16_t Encoding;
|
||||
} AArch64SVEVecLenSpecifier_SVEVECLENSPECIFIER;
|
||||
|
||||
#define GET_SVEVECLENSPECIFIER_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64SVEVecLenSpecifier
|
||||
|
||||
// namespace AArch64SVEVecLenSpecifier
|
||||
|
||||
/// Return the number of active elements for VL1 to VL256 predicate pattern,
|
||||
/// zero for all other patterns.
|
||||
static inline unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
|
||||
{
|
||||
switch (Pattern) {
|
||||
default:
|
||||
return 0;
|
||||
case AARCH64_SVEPREDPAT_VL1:
|
||||
case AARCH64_SVEPREDPAT_VL2:
|
||||
case AARCH64_SVEPREDPAT_VL3:
|
||||
case AARCH64_SVEPREDPAT_VL4:
|
||||
case AARCH64_SVEPREDPAT_VL5:
|
||||
case AARCH64_SVEPREDPAT_VL6:
|
||||
case AARCH64_SVEPREDPAT_VL7:
|
||||
case AARCH64_SVEPREDPAT_VL8:
|
||||
return Pattern;
|
||||
case AARCH64_SVEPREDPAT_VL16:
|
||||
return 16;
|
||||
case AARCH64_SVEPREDPAT_VL32:
|
||||
return 32;
|
||||
case AARCH64_SVEPREDPAT_VL64:
|
||||
return 64;
|
||||
case AARCH64_SVEPREDPAT_VL128:
|
||||
return 128;
|
||||
case AARCH64_SVEPREDPAT_VL256:
|
||||
return 256;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return specific VL predicate pattern based on the number of elements.
|
||||
static inline unsigned getSVEPredPatternFromNumElements(unsigned MinNumElts)
|
||||
{
|
||||
switch (MinNumElts) {
|
||||
default:
|
||||
return 0;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return MinNumElts;
|
||||
case 16:
|
||||
return AARCH64_SVEPREDPAT_VL16;
|
||||
case 32:
|
||||
return AARCH64_SVEPREDPAT_VL32;
|
||||
case 64:
|
||||
return AARCH64_SVEPREDPAT_VL64;
|
||||
case 128:
|
||||
return AARCH64_SVEPREDPAT_VL128;
|
||||
case 256:
|
||||
return AARCH64_SVEPREDPAT_VL256;
|
||||
}
|
||||
}
|
||||
|
||||
// CS namespace begin: AArch64ExactFPImm
|
||||
|
||||
typedef struct ExactFPImm {
|
||||
const char *Name;
|
||||
aarch64_sysop_imm SysImm;
|
||||
int Enum;
|
||||
const char *Repr;
|
||||
} AArch64ExactFPImm_ExactFPImm;
|
||||
|
||||
enum {
|
||||
AArch64ExactFPImm_half = 1,
|
||||
AArch64ExactFPImm_one = 2,
|
||||
AArch64ExactFPImm_two = 3,
|
||||
AArch64ExactFPImm_zero = 0,
|
||||
};
|
||||
|
||||
#define GET_EXACTFPIMM_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64ExactFPImm
|
||||
|
||||
// CS namespace begin: AArch64PState
|
||||
|
||||
#define AArch64PState_PStateImm0_15 SysAlias
|
||||
|
||||
#define GET_PSTATEIMM0_15_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
#define AArch64PState_PStateImm0_1 SysAlias
|
||||
|
||||
#define GET_PSTATEIMM0_1_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64PState
|
||||
|
||||
// CS namespace begin: AArch64PSBHint
|
||||
|
||||
#define AArch64PSBHint_PSB SysAlias
|
||||
|
||||
#define GET_PSB_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64PSBHint
|
||||
|
||||
// CS namespace begin: AArch64BTIHint
|
||||
|
||||
#define AArch64BTIHint_BTI SysAlias
|
||||
|
||||
#define GET_BTI_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64BTIHint
|
||||
|
||||
// CS namespace begin: AArch64SE
|
||||
|
||||
typedef enum ShiftExtSpecifiers {
|
||||
AArch64SE_Invalid = -1,
|
||||
AArch64SE_LSL,
|
||||
AArch64SE_MSL,
|
||||
AArch64SE_LSR,
|
||||
AArch64SE_ASR,
|
||||
AArch64SE_ROR,
|
||||
|
||||
AArch64SE_UXTB,
|
||||
AArch64SE_UXTH,
|
||||
AArch64SE_UXTW,
|
||||
AArch64SE_UXTX,
|
||||
|
||||
AArch64SE_SXTB,
|
||||
AArch64SE_SXTH,
|
||||
AArch64SE_SXTW,
|
||||
AArch64SE_SXTX
|
||||
} AArch64SE_ShiftExtSpecifiers;
|
||||
|
||||
// CS namespace end: AArch64SE
|
||||
|
||||
// CS namespace begin: AArch64Layout
|
||||
|
||||
// MOVE_NOTICE: AArch64Layout_VectorLayout - move to aarch64.h
|
||||
// MOVE_NOTICE: AArch64VectorLayoutToString - move to aarch64.h
|
||||
// MOVE_NOTICE: AArch64StringToVectorLayout - move to aarch64.h
|
||||
|
||||
// CS namespace end: AArch64Layout
|
||||
|
||||
// CS namespace begin: AArch64SysReg
|
||||
|
||||
typedef struct SysReg {
|
||||
const char *Name;
|
||||
aarch64_sysop_reg SysReg;
|
||||
const char *AltName;
|
||||
aarch64_sysop_reg AliasReg;
|
||||
unsigned Encoding;
|
||||
bool Readable;
|
||||
bool Writeable;
|
||||
aarch64_insn_group FeaturesRequired[3];
|
||||
} AArch64SysReg_SysReg;
|
||||
|
||||
#define GET_SYSREG_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
const AArch64SysReg_SysReg *AArch64SysReg_lookupSysRegByName(const char *Name);
|
||||
const AArch64SysReg_SysReg *
|
||||
AArch64SysReg_lookupSysRegByEncoding(uint16_t Encoding);
|
||||
#define AARCH64_GRS_LEN 128
|
||||
void AArch64SysReg_genericRegisterString(uint32_t Bits, char *result);
|
||||
|
||||
// CS namespace end: AArch64SysReg
|
||||
|
||||
// CS namespace begin: AArch64TLBI
|
||||
|
||||
#define AArch64TLBI_TLBI SysAliasReg
|
||||
|
||||
#define GET_TLBITable_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64TLBI
|
||||
|
||||
// CS namespace begin: AArch64PRCTX
|
||||
|
||||
#define AArch64PRCTX_PRCTX SysAliasReg
|
||||
|
||||
#define GET_PRCTX_DECL
|
||||
|
||||
#include "AArch64GenSystemOperands.inc"
|
||||
|
||||
// CS namespace end: AArch64PRCTX
|
||||
|
||||
// CS namespace begin: AArch64II
|
||||
|
||||
/// Target Operand Flag enum.
|
||||
typedef enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// AArch64 Specific MachineOperand flags.
|
||||
|
||||
AArch64II_MO_NO_FLAG,
|
||||
|
||||
AArch64II_MO_FRAGMENT = 0x7,
|
||||
|
||||
/// MO_PAGE - A symbol operand with this flag represents the pc-relative
|
||||
/// offset of the 4K page containing the symbol. This is used with the
|
||||
/// ADRP instruction.
|
||||
AArch64II_MO_PAGE = 1,
|
||||
|
||||
/// MO_PAGEOFF - A symbol operand with this flag represents the offset of
|
||||
/// that symbol within a 4K page. This offset is added to the page address
|
||||
/// to produce the complete address.
|
||||
AArch64II_MO_PAGEOFF = 2,
|
||||
|
||||
/// MO_G3 - A symbol operand with this flag (granule 3) represents the high
|
||||
/// 16-bits of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
AArch64II_MO_G3 = 3,
|
||||
|
||||
/// MO_G2 - A symbol operand with this flag (granule 2) represents the bits
|
||||
/// 32-47 of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
AArch64II_MO_G2 = 4,
|
||||
|
||||
/// MO_G1 - A symbol operand with this flag (granule 1) represents the bits
|
||||
/// 16-31 of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
AArch64II_MO_G1 = 5,
|
||||
|
||||
/// MO_G0 - A symbol operand with this flag (granule 0) represents the bits
|
||||
/// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction
|
||||
AArch64II_MO_G0 = 6,
|
||||
|
||||
/// MO_HI12 - This flag indicates that a symbol operand represents the bits
|
||||
/// 13-24 of a 64-bit address, used in a arithmetic immediate-shifted-left-
|
||||
/// by-12-bits instruction.
|
||||
AArch64II_MO_HI12 = 7,
|
||||
|
||||
/// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the
|
||||
/// reference is actually to the ".refptr.FOO" symbol. This is used for
|
||||
/// stub symbols on windows.
|
||||
AArch64II_MO_COFFSTUB = 0x8,
|
||||
|
||||
/// MO_GOT - This flag indicates that a symbol operand represents the
|
||||
/// address of the GOT entry for the symbol, rather than the address of
|
||||
/// the symbol itself.
|
||||
AArch64II_MO_GOT = 0x10,
|
||||
|
||||
/// MO_NC - Indicates whether the linker is expected to check the symbol
|
||||
/// reference for overflow. For example in an ADRP/ADD pair of relocations
|
||||
/// the ADRP usually does check, but not the ADD.
|
||||
AArch64II_MO_NC = 0x20,
|
||||
|
||||
/// MO_TLS - Indicates that the operand being accessed is some kind of
|
||||
/// thread-local symbol. On Darwin, only one type of thread-local access
|
||||
/// exists (pre linker-relaxation), but on ELF the TLSModel used for the
|
||||
/// referee will affect interpretation.
|
||||
AArch64II_MO_TLS = 0x40,
|
||||
|
||||
/// MO_DLLIMPORT - On a symbol operand, this represents that the reference
|
||||
/// to the symbol is for an import stub. This is used for DLL import
|
||||
/// storage class indication on Windows.
|
||||
AArch64II_MO_DLLIMPORT = 0x80,
|
||||
|
||||
/// MO_S - Indicates that the bits of the symbol operand represented by
|
||||
/// MO_G0 etc are signed.
|
||||
AArch64II_MO_S = 0x100,
|
||||
|
||||
/// MO_PREL - Indicates that the bits of the symbol operand represented by
|
||||
/// MO_G0 etc are PC relative.
|
||||
AArch64II_MO_PREL = 0x200,
|
||||
|
||||
/// MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag
|
||||
/// in bits 56-63.
|
||||
/// On a FrameIndex operand, indicates that the underlying memory is tagged
|
||||
/// with an unknown tag value (MTE); this needs to be lowered either to an
|
||||
/// SP-relative load or store instruction (which do not check tags), or to
|
||||
/// an LDG instruction to obtain the tag value.
|
||||
AArch64II_MO_TAGGED = 0x400,
|
||||
|
||||
/// MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version
|
||||
/// of a symbol, not the original. For dllimport symbols, this means it
|
||||
/// uses "__imp_aux". For other symbols, this means it uses the mangled
|
||||
/// ("#" prefix for C) name.
|
||||
AArch64II_MO_ARM64EC_CALLMANGLE = 0x800,
|
||||
} AArch64II_TOF;
|
||||
|
||||
// CS namespace end: AArch64II
|
||||
|
||||
// end namespace AArch64II
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// v8.3a Pointer Authentication
|
||||
//
|
||||
|
||||
// CS namespace begin: AArch64PACKey
|
||||
|
||||
typedef enum ID {
|
||||
AArch64PACKey_IA = 0,
|
||||
AArch64PACKey_IB = 1,
|
||||
AArch64PACKey_DA = 2,
|
||||
AArch64PACKey_DB = 3,
|
||||
AArch64PACKey_LAST = AArch64PACKey_DB,
|
||||
AArch64PACKey_INVALID,
|
||||
} AArch64PACKey_ID;
|
||||
|
||||
// CS namespace end: AArch64PACKey
|
||||
|
||||
// namespace AArch64PACKey
|
||||
|
||||
/// Return 2-letter identifier string for numeric key ID.
|
||||
static inline const char *AArch64PACKeyIDToString(AArch64PACKey_ID KeyID)
|
||||
{
|
||||
switch (KeyID) {
|
||||
default:
|
||||
break;
|
||||
case AArch64PACKey_IA:
|
||||
return "ia";
|
||||
case AArch64PACKey_IB:
|
||||
return "ib";
|
||||
case AArch64PACKey_DA:
|
||||
return "da";
|
||||
case AArch64PACKey_DB:
|
||||
return "db";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Return numeric key ID for 2-letter identifier string.
|
||||
static inline AArch64PACKey_ID AArch64StringToPACKeyID(const char *Name)
|
||||
{
|
||||
if (strcmp(Name, "ia") == 0)
|
||||
return AArch64PACKey_IA;
|
||||
if (strcmp(Name, "ib") == 0)
|
||||
return AArch64PACKey_IB;
|
||||
if (strcmp(Name, "da") == 0)
|
||||
return AArch64PACKey_DA;
|
||||
if (strcmp(Name, "db") == 0)
|
||||
return AArch64PACKey_DB;
|
||||
CS_ASSERT_RET_VAL(0 && "Invalid PAC key", AArch64PACKey_INVALID);
|
||||
return AArch64PACKey_LAST;
|
||||
}
|
||||
|
||||
// CS namespace begin: AArch64
|
||||
|
||||
// The number of bits in a SVE register is architecturally defined
|
||||
// to be a multiple of this value. If <M x t> has this number of bits,
|
||||
// a <n x M x t> vector can be stored in a SVE register without any
|
||||
// redundant bits. If <M x t> has this number of bits divided by P,
|
||||
// a <n x M x t> vector is stored in a SVE register by placing index i
|
||||
// in index i*P of a <n x (M*P) x t> vector. The other elements of the
|
||||
// <n x (M*P) x t> vector (such as index 1) are undefined.
|
||||
static const unsigned SVEBitsPerBlock = 128;
|
||||
|
||||
static const unsigned SVEMaxBitsPerVector = 2048;
|
||||
|
||||
// CS namespace end: AArch64
|
||||
|
||||
// end namespace AArch64
|
||||
// end namespace llvm
|
||||
|
||||
#endif
|
||||
+2217
File diff suppressed because it is too large
Load Diff
+28
@@ -0,0 +1,28 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
||||
|
||||
#include "AArch64DisassemblerExtension.h"
|
||||
#include "AArch64BaseInfo.h"
|
||||
|
||||
bool AArch64_getFeatureBits(unsigned int mode, unsigned int feature)
|
||||
{
|
||||
if (feature == AArch64_FeatureAMX || feature == AArch64_FeatureMUL53 ||
|
||||
feature == AArch64_FeatureAppleSys) {
|
||||
return mode & CS_MODE_APPLE_PROPRIETARY;
|
||||
}
|
||||
// we support everything
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Tests a NULL terminated array of features if they are enabled.
|
||||
bool AArch64_testFeatureList(unsigned int mode, const unsigned int *features)
|
||||
{
|
||||
int i = 0;
|
||||
while (features[i]) {
|
||||
if (!AArch64_getFeatureBits(mode, features[i]))
|
||||
return false;
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
||||
|
||||
#ifndef CS_AARCH64_DISASSEMBLER_EXTENSION_H
|
||||
#define CS_AARCH64_DISASSEMBLER_EXTENSION_H
|
||||
|
||||
#include "../../MCDisassembler.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../MathExtras.h"
|
||||
#include "../../cs_priv.h"
|
||||
#include "AArch64AddressingModes.h"
|
||||
#include "capstone/aarch64.h"
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
bool AArch64_getFeatureBits(unsigned int mode, unsigned int feature);
|
||||
bool AArch64_testFeatureList(unsigned int mode, const unsigned int *features);
|
||||
|
||||
#endif // CS_AARCH64_DISASSEMBLER_EXTENSION_H
|
||||
+34894
File diff suppressed because it is too large
Load Diff
+375
@@ -0,0 +1,375 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
{ AARCH64_INS_ALIAS_ADDPT, "addpt" },
|
||||
{ AARCH64_INS_ALIAS_GCSB, "gcsb" },
|
||||
{ AARCH64_INS_ALIAS_GCSPOPM, "gcspopm" },
|
||||
{ AARCH64_INS_ALIAS_LDAPUR, "ldapur" },
|
||||
{ AARCH64_INS_ALIAS_STLLRB, "stllrb" },
|
||||
{ AARCH64_INS_ALIAS_STLLRH, "stllrh" },
|
||||
{ AARCH64_INS_ALIAS_STLLR, "stllr" },
|
||||
{ AARCH64_INS_ALIAS_STLRB, "stlrb" },
|
||||
{ AARCH64_INS_ALIAS_STLRH, "stlrh" },
|
||||
{ AARCH64_INS_ALIAS_STLR, "stlr" },
|
||||
{ AARCH64_INS_ALIAS_STLUR, "stlur" },
|
||||
{ AARCH64_INS_ALIAS_SUBPT, "subpt" },
|
||||
{ AARCH64_INS_ALIAS_LDRAA, "ldraa" },
|
||||
{ AARCH64_INS_ALIAS_ADD, "add" },
|
||||
{ AARCH64_INS_ALIAS_CMN, "cmn" },
|
||||
{ AARCH64_INS_ALIAS_ADDS, "adds" },
|
||||
{ AARCH64_INS_ALIAS_AND, "and" },
|
||||
{ AARCH64_INS_ALIAS_ANDS, "ands" },
|
||||
{ AARCH64_INS_ALIAS_LDR, "ldr" },
|
||||
{ AARCH64_INS_ALIAS_STR, "str" },
|
||||
{ AARCH64_INS_ALIAS_LDRB, "ldrb" },
|
||||
{ AARCH64_INS_ALIAS_STRB, "strb" },
|
||||
{ AARCH64_INS_ALIAS_LDRH, "ldrh" },
|
||||
{ AARCH64_INS_ALIAS_STRH, "strh" },
|
||||
{ AARCH64_INS_ALIAS_PRFM, "prfm" },
|
||||
{ AARCH64_INS_ALIAS_LDAPURB, "ldapurb" },
|
||||
{ AARCH64_INS_ALIAS_STLURB, "stlurb" },
|
||||
{ AARCH64_INS_ALIAS_LDUR, "ldur" },
|
||||
{ AARCH64_INS_ALIAS_STUR, "stur" },
|
||||
{ AARCH64_INS_ALIAS_PRFUM, "prfum" },
|
||||
{ AARCH64_INS_ALIAS_LDTR, "ldtr" },
|
||||
{ AARCH64_INS_ALIAS_STTR, "sttr" },
|
||||
{ AARCH64_INS_ALIAS_LDP, "ldp" },
|
||||
{ AARCH64_INS_ALIAS_STGP, "stgp" },
|
||||
{ AARCH64_INS_ALIAS_LDNP, "ldnp" },
|
||||
{ AARCH64_INS_ALIAS_STNP, "stnp" },
|
||||
{ AARCH64_INS_ALIAS_STG, "stg" },
|
||||
{ AARCH64_INS_ALIAS_MOV, "mov" },
|
||||
{ AARCH64_INS_ALIAS_LD1, "ld1" },
|
||||
{ AARCH64_INS_ALIAS_LD1R, "ld1r" },
|
||||
{ AARCH64_INS_ALIAS_STADDLB, "staddlb" },
|
||||
{ AARCH64_INS_ALIAS_STADDLH, "staddlh" },
|
||||
{ AARCH64_INS_ALIAS_STADDL, "staddl" },
|
||||
{ AARCH64_INS_ALIAS_STADDB, "staddb" },
|
||||
{ AARCH64_INS_ALIAS_STADDH, "staddh" },
|
||||
{ AARCH64_INS_ALIAS_STADD, "stadd" },
|
||||
{ AARCH64_INS_ALIAS_PTRUE, "ptrue" },
|
||||
{ AARCH64_INS_ALIAS_PTRUES, "ptrues" },
|
||||
{ AARCH64_INS_ALIAS_CNTB, "cntb" },
|
||||
{ AARCH64_INS_ALIAS_SQINCH, "sqinch" },
|
||||
{ AARCH64_INS_ALIAS_INCB, "incb" },
|
||||
{ AARCH64_INS_ALIAS_SQINCB, "sqincb" },
|
||||
{ AARCH64_INS_ALIAS_UQINCB, "uqincb" },
|
||||
{ AARCH64_INS_ALIAS_ORR, "orr" },
|
||||
{ AARCH64_INS_ALIAS_DUPM, "dupm" },
|
||||
{ AARCH64_INS_ALIAS_FMOV, "fmov" },
|
||||
{ AARCH64_INS_ALIAS_EOR3, "eor3" },
|
||||
{ AARCH64_INS_ALIAS_ST1B, "st1b" },
|
||||
{ AARCH64_INS_ALIAS_ST2B, "st2b" },
|
||||
{ AARCH64_INS_ALIAS_ST2Q, "st2q" },
|
||||
{ AARCH64_INS_ALIAS_STNT1B, "stnt1b" },
|
||||
{ AARCH64_INS_ALIAS_LD1B, "ld1b" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1B, "ldnt1b" },
|
||||
{ AARCH64_INS_ALIAS_LD1RQB, "ld1rqb" },
|
||||
{ AARCH64_INS_ALIAS_LD1RB, "ld1rb" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1B, "ldff1b" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1B, "ldnf1b" },
|
||||
{ AARCH64_INS_ALIAS_LD2B, "ld2b" },
|
||||
{ AARCH64_INS_ALIAS_LD1SB, "ld1sb" },
|
||||
{ AARCH64_INS_ALIAS_PRFB, "prfb" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1SB, "ldnt1sb" },
|
||||
{ AARCH64_INS_ALIAS_LD1ROB, "ld1rob" },
|
||||
{ AARCH64_INS_ALIAS_LD1Q, "ld1q" },
|
||||
{ AARCH64_INS_ALIAS_ST1Q, "st1q" },
|
||||
{ AARCH64_INS_ALIAS_LD1W, "ld1w" },
|
||||
{ AARCH64_INS_ALIAS_PMOV, "pmov" },
|
||||
{ AARCH64_INS_ALIAS_SMSTART, "smstart" },
|
||||
{ AARCH64_INS_ALIAS_SMSTOP, "smstop" },
|
||||
{ AARCH64_INS_ALIAS_ZERO, "zero" },
|
||||
{ AARCH64_INS_ALIAS_MOVT, "movt" },
|
||||
{ AARCH64_INS_ALIAS_NOP, "nop" },
|
||||
{ AARCH64_INS_ALIAS_YIELD, "yield" },
|
||||
{ AARCH64_INS_ALIAS_WFE, "wfe" },
|
||||
{ AARCH64_INS_ALIAS_WFI, "wfi" },
|
||||
{ AARCH64_INS_ALIAS_SEV, "sev" },
|
||||
{ AARCH64_INS_ALIAS_SEVL, "sevl" },
|
||||
{ AARCH64_INS_ALIAS_DGH, "dgh" },
|
||||
{ AARCH64_INS_ALIAS_ESB, "esb" },
|
||||
{ AARCH64_INS_ALIAS_CSDB, "csdb" },
|
||||
{ AARCH64_INS_ALIAS_BTI, "bti" },
|
||||
{ AARCH64_INS_ALIAS_PSB, "psb" },
|
||||
{ AARCH64_INS_ALIAS_CHKFEAT, "chkfeat" },
|
||||
{ AARCH64_INS_ALIAS_PACIAZ, "paciaz" },
|
||||
{ AARCH64_INS_ALIAS_PACIBZ, "pacibz" },
|
||||
{ AARCH64_INS_ALIAS_AUTIAZ, "autiaz" },
|
||||
{ AARCH64_INS_ALIAS_AUTIBZ, "autibz" },
|
||||
{ AARCH64_INS_ALIAS_PACIASP, "paciasp" },
|
||||
{ AARCH64_INS_ALIAS_PACIBSP, "pacibsp" },
|
||||
{ AARCH64_INS_ALIAS_AUTIASP, "autiasp" },
|
||||
{ AARCH64_INS_ALIAS_AUTIBSP, "autibsp" },
|
||||
{ AARCH64_INS_ALIAS_PACIA1716, "pacia1716" },
|
||||
{ AARCH64_INS_ALIAS_PACIB1716, "pacib1716" },
|
||||
{ AARCH64_INS_ALIAS_AUTIA1716, "autia1716" },
|
||||
{ AARCH64_INS_ALIAS_AUTIB1716, "autib1716" },
|
||||
{ AARCH64_INS_ALIAS_XPACLRI, "xpaclri" },
|
||||
{ AARCH64_INS_ALIAS_LDRAB, "ldrab" },
|
||||
{ AARCH64_INS_ALIAS_PACM, "pacm" },
|
||||
{ AARCH64_INS_ALIAS_CLREX, "clrex" },
|
||||
{ AARCH64_INS_ALIAS_ISB, "isb" },
|
||||
{ AARCH64_INS_ALIAS_SSBB, "ssbb" },
|
||||
{ AARCH64_INS_ALIAS_PSSBB, "pssbb" },
|
||||
{ AARCH64_INS_ALIAS_DFB, "dfb" },
|
||||
{ AARCH64_INS_ALIAS_SYS, "sys" },
|
||||
{ AARCH64_INS_ALIAS_MOVN, "movn" },
|
||||
{ AARCH64_INS_ALIAS_MOVZ, "movz" },
|
||||
{ AARCH64_INS_ALIAS_NGC, "ngc" },
|
||||
{ AARCH64_INS_ALIAS_NGCS, "ngcs" },
|
||||
{ AARCH64_INS_ALIAS_SUB, "sub" },
|
||||
{ AARCH64_INS_ALIAS_CMP, "cmp" },
|
||||
{ AARCH64_INS_ALIAS_SUBS, "subs" },
|
||||
{ AARCH64_INS_ALIAS_NEG, "neg" },
|
||||
{ AARCH64_INS_ALIAS_NEGS, "negs" },
|
||||
{ AARCH64_INS_ALIAS_MUL, "mul" },
|
||||
{ AARCH64_INS_ALIAS_MNEG, "mneg" },
|
||||
{ AARCH64_INS_ALIAS_SMULL, "smull" },
|
||||
{ AARCH64_INS_ALIAS_SMNEGL, "smnegl" },
|
||||
{ AARCH64_INS_ALIAS_UMULL, "umull" },
|
||||
{ AARCH64_INS_ALIAS_UMNEGL, "umnegl" },
|
||||
{ AARCH64_INS_ALIAS_STCLRLB, "stclrlb" },
|
||||
{ AARCH64_INS_ALIAS_STCLRLH, "stclrlh" },
|
||||
{ AARCH64_INS_ALIAS_STCLRL, "stclrl" },
|
||||
{ AARCH64_INS_ALIAS_STCLRB, "stclrb" },
|
||||
{ AARCH64_INS_ALIAS_STCLRH, "stclrh" },
|
||||
{ AARCH64_INS_ALIAS_STCLR, "stclr" },
|
||||
{ AARCH64_INS_ALIAS_STEORLB, "steorlb" },
|
||||
{ AARCH64_INS_ALIAS_STEORLH, "steorlh" },
|
||||
{ AARCH64_INS_ALIAS_STEORL, "steorl" },
|
||||
{ AARCH64_INS_ALIAS_STEORB, "steorb" },
|
||||
{ AARCH64_INS_ALIAS_STEORH, "steorh" },
|
||||
{ AARCH64_INS_ALIAS_STEOR, "steor" },
|
||||
{ AARCH64_INS_ALIAS_STSETLB, "stsetlb" },
|
||||
{ AARCH64_INS_ALIAS_STSETLH, "stsetlh" },
|
||||
{ AARCH64_INS_ALIAS_STSETL, "stsetl" },
|
||||
{ AARCH64_INS_ALIAS_STSETB, "stsetb" },
|
||||
{ AARCH64_INS_ALIAS_STSETH, "stseth" },
|
||||
{ AARCH64_INS_ALIAS_STSET, "stset" },
|
||||
{ AARCH64_INS_ALIAS_STSMAXLB, "stsmaxlb" },
|
||||
{ AARCH64_INS_ALIAS_STSMAXLH, "stsmaxlh" },
|
||||
{ AARCH64_INS_ALIAS_STSMAXL, "stsmaxl" },
|
||||
{ AARCH64_INS_ALIAS_STSMAXB, "stsmaxb" },
|
||||
{ AARCH64_INS_ALIAS_STSMAXH, "stsmaxh" },
|
||||
{ AARCH64_INS_ALIAS_STSMAX, "stsmax" },
|
||||
{ AARCH64_INS_ALIAS_STSMINLB, "stsminlb" },
|
||||
{ AARCH64_INS_ALIAS_STSMINLH, "stsminlh" },
|
||||
{ AARCH64_INS_ALIAS_STSMINL, "stsminl" },
|
||||
{ AARCH64_INS_ALIAS_STSMINB, "stsminb" },
|
||||
{ AARCH64_INS_ALIAS_STSMINH, "stsminh" },
|
||||
{ AARCH64_INS_ALIAS_STSMIN, "stsmin" },
|
||||
{ AARCH64_INS_ALIAS_STUMAXLB, "stumaxlb" },
|
||||
{ AARCH64_INS_ALIAS_STUMAXLH, "stumaxlh" },
|
||||
{ AARCH64_INS_ALIAS_STUMAXL, "stumaxl" },
|
||||
{ AARCH64_INS_ALIAS_STUMAXB, "stumaxb" },
|
||||
{ AARCH64_INS_ALIAS_STUMAXH, "stumaxh" },
|
||||
{ AARCH64_INS_ALIAS_STUMAX, "stumax" },
|
||||
{ AARCH64_INS_ALIAS_STUMINLB, "stuminlb" },
|
||||
{ AARCH64_INS_ALIAS_STUMINLH, "stuminlh" },
|
||||
{ AARCH64_INS_ALIAS_STUMINL, "stuminl" },
|
||||
{ AARCH64_INS_ALIAS_STUMINB, "stuminb" },
|
||||
{ AARCH64_INS_ALIAS_STUMINH, "stuminh" },
|
||||
{ AARCH64_INS_ALIAS_STUMIN, "stumin" },
|
||||
{ AARCH64_INS_ALIAS_IRG, "irg" },
|
||||
{ AARCH64_INS_ALIAS_LDG, "ldg" },
|
||||
{ AARCH64_INS_ALIAS_STZG, "stzg" },
|
||||
{ AARCH64_INS_ALIAS_ST2G, "st2g" },
|
||||
{ AARCH64_INS_ALIAS_STZ2G, "stz2g" },
|
||||
{ AARCH64_INS_ALIAS_BICS, "bics" },
|
||||
{ AARCH64_INS_ALIAS_BIC, "bic" },
|
||||
{ AARCH64_INS_ALIAS_EON, "eon" },
|
||||
{ AARCH64_INS_ALIAS_EOR, "eor" },
|
||||
{ AARCH64_INS_ALIAS_ORN, "orn" },
|
||||
{ AARCH64_INS_ALIAS_MVN, "mvn" },
|
||||
{ AARCH64_INS_ALIAS_TST, "tst" },
|
||||
{ AARCH64_INS_ALIAS_ROR, "ror" },
|
||||
{ AARCH64_INS_ALIAS_ASR, "asr" },
|
||||
{ AARCH64_INS_ALIAS_SXTB, "sxtb" },
|
||||
{ AARCH64_INS_ALIAS_SXTH, "sxth" },
|
||||
{ AARCH64_INS_ALIAS_SXTW, "sxtw" },
|
||||
{ AARCH64_INS_ALIAS_LSR, "lsr" },
|
||||
{ AARCH64_INS_ALIAS_UXTB, "uxtb" },
|
||||
{ AARCH64_INS_ALIAS_UXTH, "uxth" },
|
||||
{ AARCH64_INS_ALIAS_UXTW, "uxtw" },
|
||||
{ AARCH64_INS_ALIAS_CSET, "cset" },
|
||||
{ AARCH64_INS_ALIAS_CSETM, "csetm" },
|
||||
{ AARCH64_INS_ALIAS_CINC, "cinc" },
|
||||
{ AARCH64_INS_ALIAS_CINV, "cinv" },
|
||||
{ AARCH64_INS_ALIAS_CNEG, "cneg" },
|
||||
{ AARCH64_INS_ALIAS_RET, "ret" },
|
||||
{ AARCH64_INS_ALIAS_DCPS1, "dcps1" },
|
||||
{ AARCH64_INS_ALIAS_DCPS2, "dcps2" },
|
||||
{ AARCH64_INS_ALIAS_DCPS3, "dcps3" },
|
||||
{ AARCH64_INS_ALIAS_LDPSW, "ldpsw" },
|
||||
{ AARCH64_INS_ALIAS_LDRSH, "ldrsh" },
|
||||
{ AARCH64_INS_ALIAS_LDRSB, "ldrsb" },
|
||||
{ AARCH64_INS_ALIAS_LDRSW, "ldrsw" },
|
||||
{ AARCH64_INS_ALIAS_LDURH, "ldurh" },
|
||||
{ AARCH64_INS_ALIAS_LDURB, "ldurb" },
|
||||
{ AARCH64_INS_ALIAS_LDURSH, "ldursh" },
|
||||
{ AARCH64_INS_ALIAS_LDURSB, "ldursb" },
|
||||
{ AARCH64_INS_ALIAS_LDURSW, "ldursw" },
|
||||
{ AARCH64_INS_ALIAS_LDTRH, "ldtrh" },
|
||||
{ AARCH64_INS_ALIAS_LDTRB, "ldtrb" },
|
||||
{ AARCH64_INS_ALIAS_LDTRSH, "ldtrsh" },
|
||||
{ AARCH64_INS_ALIAS_LDTRSB, "ldtrsb" },
|
||||
{ AARCH64_INS_ALIAS_LDTRSW, "ldtrsw" },
|
||||
{ AARCH64_INS_ALIAS_STP, "stp" },
|
||||
{ AARCH64_INS_ALIAS_STURH, "sturh" },
|
||||
{ AARCH64_INS_ALIAS_STURB, "sturb" },
|
||||
{ AARCH64_INS_ALIAS_STLURH, "stlurh" },
|
||||
{ AARCH64_INS_ALIAS_LDAPURSB, "ldapursb" },
|
||||
{ AARCH64_INS_ALIAS_LDAPURH, "ldapurh" },
|
||||
{ AARCH64_INS_ALIAS_LDAPURSH, "ldapursh" },
|
||||
{ AARCH64_INS_ALIAS_LDAPURSW, "ldapursw" },
|
||||
{ AARCH64_INS_ALIAS_STTRH, "sttrh" },
|
||||
{ AARCH64_INS_ALIAS_STTRB, "sttrb" },
|
||||
{ AARCH64_INS_ALIAS_BIC_4H, "bic_4h" },
|
||||
{ AARCH64_INS_ALIAS_BIC_8H, "bic_8h" },
|
||||
{ AARCH64_INS_ALIAS_BIC_2S, "bic_2s" },
|
||||
{ AARCH64_INS_ALIAS_BIC_4S, "bic_4s" },
|
||||
{ AARCH64_INS_ALIAS_ORR_4H, "orr_4h" },
|
||||
{ AARCH64_INS_ALIAS_ORR_8H, "orr_8h" },
|
||||
{ AARCH64_INS_ALIAS_ORR_2S, "orr_2s" },
|
||||
{ AARCH64_INS_ALIAS_ORR_4S, "orr_4s" },
|
||||
{ AARCH64_INS_ALIAS_SXTL_8H, "sxtl_8h" },
|
||||
{ AARCH64_INS_ALIAS_SXTL, "sxtl" },
|
||||
{ AARCH64_INS_ALIAS_SXTL_4S, "sxtl_4s" },
|
||||
{ AARCH64_INS_ALIAS_SXTL_2D, "sxtl_2d" },
|
||||
{ AARCH64_INS_ALIAS_SXTL2_8H, "sxtl2_8h" },
|
||||
{ AARCH64_INS_ALIAS_SXTL2, "sxtl2" },
|
||||
{ AARCH64_INS_ALIAS_SXTL2_4S, "sxtl2_4s" },
|
||||
{ AARCH64_INS_ALIAS_SXTL2_2D, "sxtl2_2d" },
|
||||
{ AARCH64_INS_ALIAS_UXTL_8H, "uxtl_8h" },
|
||||
{ AARCH64_INS_ALIAS_UXTL, "uxtl" },
|
||||
{ AARCH64_INS_ALIAS_UXTL_4S, "uxtl_4s" },
|
||||
{ AARCH64_INS_ALIAS_UXTL_2D, "uxtl_2d" },
|
||||
{ AARCH64_INS_ALIAS_UXTL2_8H, "uxtl2_8h" },
|
||||
{ AARCH64_INS_ALIAS_UXTL2, "uxtl2" },
|
||||
{ AARCH64_INS_ALIAS_UXTL2_4S, "uxtl2_4s" },
|
||||
{ AARCH64_INS_ALIAS_UXTL2_2D, "uxtl2_2d" },
|
||||
{ AARCH64_INS_ALIAS_LD2, "ld2" },
|
||||
{ AARCH64_INS_ALIAS_LD3, "ld3" },
|
||||
{ AARCH64_INS_ALIAS_LD4, "ld4" },
|
||||
{ AARCH64_INS_ALIAS_ST1, "st1" },
|
||||
{ AARCH64_INS_ALIAS_ST2, "st2" },
|
||||
{ AARCH64_INS_ALIAS_ST3, "st3" },
|
||||
{ AARCH64_INS_ALIAS_ST4, "st4" },
|
||||
{ AARCH64_INS_ALIAS_LD2R, "ld2r" },
|
||||
{ AARCH64_INS_ALIAS_LD3R, "ld3r" },
|
||||
{ AARCH64_INS_ALIAS_LD4R, "ld4r" },
|
||||
{ AARCH64_INS_ALIAS_CLRBHB, "clrbhb" },
|
||||
{ AARCH64_INS_ALIAS_STILP, "stilp" },
|
||||
{ AARCH64_INS_ALIAS_STL1, "stl1" },
|
||||
{ AARCH64_INS_ALIAS_SYSP, "sysp" },
|
||||
{ AARCH64_INS_ALIAS_LD1SW, "ld1sw" },
|
||||
{ AARCH64_INS_ALIAS_LD1H, "ld1h" },
|
||||
{ AARCH64_INS_ALIAS_LD1SH, "ld1sh" },
|
||||
{ AARCH64_INS_ALIAS_LD1D, "ld1d" },
|
||||
{ AARCH64_INS_ALIAS_LD1RSW, "ld1rsw" },
|
||||
{ AARCH64_INS_ALIAS_LD1RH, "ld1rh" },
|
||||
{ AARCH64_INS_ALIAS_LD1RSH, "ld1rsh" },
|
||||
{ AARCH64_INS_ALIAS_LD1RW, "ld1rw" },
|
||||
{ AARCH64_INS_ALIAS_LD1RSB, "ld1rsb" },
|
||||
{ AARCH64_INS_ALIAS_LD1RD, "ld1rd" },
|
||||
{ AARCH64_INS_ALIAS_LD1RQH, "ld1rqh" },
|
||||
{ AARCH64_INS_ALIAS_LD1RQW, "ld1rqw" },
|
||||
{ AARCH64_INS_ALIAS_LD1RQD, "ld1rqd" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1SW, "ldnf1sw" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1H, "ldnf1h" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1SH, "ldnf1sh" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1W, "ldnf1w" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1SB, "ldnf1sb" },
|
||||
{ AARCH64_INS_ALIAS_LDNF1D, "ldnf1d" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1SW, "ldff1sw" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1H, "ldff1h" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1SH, "ldff1sh" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1W, "ldff1w" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1SB, "ldff1sb" },
|
||||
{ AARCH64_INS_ALIAS_LDFF1D, "ldff1d" },
|
||||
{ AARCH64_INS_ALIAS_LD3B, "ld3b" },
|
||||
{ AARCH64_INS_ALIAS_LD4B, "ld4b" },
|
||||
{ AARCH64_INS_ALIAS_LD2H, "ld2h" },
|
||||
{ AARCH64_INS_ALIAS_LD3H, "ld3h" },
|
||||
{ AARCH64_INS_ALIAS_LD4H, "ld4h" },
|
||||
{ AARCH64_INS_ALIAS_LD2W, "ld2w" },
|
||||
{ AARCH64_INS_ALIAS_LD3W, "ld3w" },
|
||||
{ AARCH64_INS_ALIAS_LD4W, "ld4w" },
|
||||
{ AARCH64_INS_ALIAS_LD2D, "ld2d" },
|
||||
{ AARCH64_INS_ALIAS_LD3D, "ld3d" },
|
||||
{ AARCH64_INS_ALIAS_LD4D, "ld4d" },
|
||||
{ AARCH64_INS_ALIAS_LD2Q, "ld2q" },
|
||||
{ AARCH64_INS_ALIAS_LD3Q, "ld3q" },
|
||||
{ AARCH64_INS_ALIAS_LD4Q, "ld4q" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1H, "ldnt1h" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1W, "ldnt1w" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1D, "ldnt1d" },
|
||||
{ AARCH64_INS_ALIAS_ST1H, "st1h" },
|
||||
{ AARCH64_INS_ALIAS_ST1W, "st1w" },
|
||||
{ AARCH64_INS_ALIAS_ST1D, "st1d" },
|
||||
{ AARCH64_INS_ALIAS_ST3B, "st3b" },
|
||||
{ AARCH64_INS_ALIAS_ST4B, "st4b" },
|
||||
{ AARCH64_INS_ALIAS_ST2H, "st2h" },
|
||||
{ AARCH64_INS_ALIAS_ST3H, "st3h" },
|
||||
{ AARCH64_INS_ALIAS_ST4H, "st4h" },
|
||||
{ AARCH64_INS_ALIAS_ST2W, "st2w" },
|
||||
{ AARCH64_INS_ALIAS_ST3W, "st3w" },
|
||||
{ AARCH64_INS_ALIAS_ST4W, "st4w" },
|
||||
{ AARCH64_INS_ALIAS_ST2D, "st2d" },
|
||||
{ AARCH64_INS_ALIAS_ST3D, "st3d" },
|
||||
{ AARCH64_INS_ALIAS_ST4D, "st4d" },
|
||||
{ AARCH64_INS_ALIAS_ST3Q, "st3q" },
|
||||
{ AARCH64_INS_ALIAS_ST4Q, "st4q" },
|
||||
{ AARCH64_INS_ALIAS_STNT1H, "stnt1h" },
|
||||
{ AARCH64_INS_ALIAS_STNT1W, "stnt1w" },
|
||||
{ AARCH64_INS_ALIAS_STNT1D, "stnt1d" },
|
||||
{ AARCH64_INS_ALIAS_PRFH, "prfh" },
|
||||
{ AARCH64_INS_ALIAS_PRFW, "prfw" },
|
||||
{ AARCH64_INS_ALIAS_PRFD, "prfd" },
|
||||
{ AARCH64_INS_ALIAS_CNTH, "cnth" },
|
||||
{ AARCH64_INS_ALIAS_CNTW, "cntw" },
|
||||
{ AARCH64_INS_ALIAS_CNTD, "cntd" },
|
||||
{ AARCH64_INS_ALIAS_DECB, "decb" },
|
||||
{ AARCH64_INS_ALIAS_INCH, "inch" },
|
||||
{ AARCH64_INS_ALIAS_DECH, "dech" },
|
||||
{ AARCH64_INS_ALIAS_INCW, "incw" },
|
||||
{ AARCH64_INS_ALIAS_DECW, "decw" },
|
||||
{ AARCH64_INS_ALIAS_INCD, "incd" },
|
||||
{ AARCH64_INS_ALIAS_DECD, "decd" },
|
||||
{ AARCH64_INS_ALIAS_SQDECB, "sqdecb" },
|
||||
{ AARCH64_INS_ALIAS_UQDECB, "uqdecb" },
|
||||
{ AARCH64_INS_ALIAS_UQINCH, "uqinch" },
|
||||
{ AARCH64_INS_ALIAS_SQDECH, "sqdech" },
|
||||
{ AARCH64_INS_ALIAS_UQDECH, "uqdech" },
|
||||
{ AARCH64_INS_ALIAS_SQINCW, "sqincw" },
|
||||
{ AARCH64_INS_ALIAS_UQINCW, "uqincw" },
|
||||
{ AARCH64_INS_ALIAS_SQDECW, "sqdecw" },
|
||||
{ AARCH64_INS_ALIAS_UQDECW, "uqdecw" },
|
||||
{ AARCH64_INS_ALIAS_SQINCD, "sqincd" },
|
||||
{ AARCH64_INS_ALIAS_UQINCD, "uqincd" },
|
||||
{ AARCH64_INS_ALIAS_SQDECD, "sqdecd" },
|
||||
{ AARCH64_INS_ALIAS_UQDECD, "uqdecd" },
|
||||
{ AARCH64_INS_ALIAS_MOVS, "movs" },
|
||||
{ AARCH64_INS_ALIAS_NOT, "not" },
|
||||
{ AARCH64_INS_ALIAS_NOTS, "nots" },
|
||||
{ AARCH64_INS_ALIAS_LD1ROH, "ld1roh" },
|
||||
{ AARCH64_INS_ALIAS_LD1ROW, "ld1row" },
|
||||
{ AARCH64_INS_ALIAS_LD1ROD, "ld1rod" },
|
||||
{ AARCH64_INS_ALIAS_BCAX, "bcax" },
|
||||
{ AARCH64_INS_ALIAS_BSL, "bsl" },
|
||||
{ AARCH64_INS_ALIAS_BSL1N, "bsl1n" },
|
||||
{ AARCH64_INS_ALIAS_BSL2N, "bsl2n" },
|
||||
{ AARCH64_INS_ALIAS_NBSL, "nbsl" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1SH, "ldnt1sh" },
|
||||
{ AARCH64_INS_ALIAS_LDNT1SW, "ldnt1sw" },
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
{ AARCH64_FEATURE_HASV8_0A, "HasV8_0a" },
|
||||
{ AARCH64_FEATURE_HASV8_1A, "HasV8_1a" },
|
||||
{ AARCH64_FEATURE_HASV8_2A, "HasV8_2a" },
|
||||
{ AARCH64_FEATURE_HASV8_3A, "HasV8_3a" },
|
||||
{ AARCH64_FEATURE_HASV8_4A, "HasV8_4a" },
|
||||
{ AARCH64_FEATURE_HASV8_5A, "HasV8_5a" },
|
||||
{ AARCH64_FEATURE_HASV8_6A, "HasV8_6a" },
|
||||
{ AARCH64_FEATURE_HASV8_7A, "HasV8_7a" },
|
||||
{ AARCH64_FEATURE_HASV8_8A, "HasV8_8a" },
|
||||
{ AARCH64_FEATURE_HASV8_9A, "HasV8_9a" },
|
||||
{ AARCH64_FEATURE_HASV9_0A, "HasV9_0a" },
|
||||
{ AARCH64_FEATURE_HASV9_1A, "HasV9_1a" },
|
||||
{ AARCH64_FEATURE_HASV9_2A, "HasV9_2a" },
|
||||
{ AARCH64_FEATURE_HASV9_3A, "HasV9_3a" },
|
||||
{ AARCH64_FEATURE_HASV9_4A, "HasV9_4a" },
|
||||
{ AARCH64_FEATURE_HASV8_0R, "HasV8_0r" },
|
||||
{ AARCH64_FEATURE_HASEL2VMSA, "HasEL2VMSA" },
|
||||
{ AARCH64_FEATURE_HASEL3, "HasEL3" },
|
||||
{ AARCH64_FEATURE_HASVH, "HasVH" },
|
||||
{ AARCH64_FEATURE_HASLOR, "HasLOR" },
|
||||
{ AARCH64_FEATURE_HASPAUTH, "HasPAuth" },
|
||||
{ AARCH64_FEATURE_HASPAUTHLR, "HasPAuthLR" },
|
||||
{ AARCH64_FEATURE_HASJS, "HasJS" },
|
||||
{ AARCH64_FEATURE_HASCCIDX, "HasCCIDX" },
|
||||
{ AARCH64_FEATURE_HASCOMPLXNUM, "HasComplxNum" },
|
||||
{ AARCH64_FEATURE_HASNV, "HasNV" },
|
||||
{ AARCH64_FEATURE_HASMPAM, "HasMPAM" },
|
||||
{ AARCH64_FEATURE_HASDIT, "HasDIT" },
|
||||
{ AARCH64_FEATURE_HASTRACEV8_4, "HasTRACEV8_4" },
|
||||
{ AARCH64_FEATURE_HASAM, "HasAM" },
|
||||
{ AARCH64_FEATURE_HASSEL2, "HasSEL2" },
|
||||
{ AARCH64_FEATURE_HASTLB_RMI, "HasTLB_RMI" },
|
||||
{ AARCH64_FEATURE_HASFLAGM, "HasFlagM" },
|
||||
{ AARCH64_FEATURE_HASRCPC_IMMO, "HasRCPC_IMMO" },
|
||||
{ AARCH64_FEATURE_HASFPARMV8, "HasFPARMv8" },
|
||||
{ AARCH64_FEATURE_HASNEON, "HasNEON" },
|
||||
{ AARCH64_FEATURE_HASSM4, "HasSM4" },
|
||||
{ AARCH64_FEATURE_HASSHA3, "HasSHA3" },
|
||||
{ AARCH64_FEATURE_HASSHA2, "HasSHA2" },
|
||||
{ AARCH64_FEATURE_HASAES, "HasAES" },
|
||||
{ AARCH64_FEATURE_HASDOTPROD, "HasDotProd" },
|
||||
{ AARCH64_FEATURE_HASCRC, "HasCRC" },
|
||||
{ AARCH64_FEATURE_HASCSSC, "HasCSSC" },
|
||||
{ AARCH64_FEATURE_HASLSE, "HasLSE" },
|
||||
{ AARCH64_FEATURE_HASRAS, "HasRAS" },
|
||||
{ AARCH64_FEATURE_HASRDM, "HasRDM" },
|
||||
{ AARCH64_FEATURE_HASFULLFP16, "HasFullFP16" },
|
||||
{ AARCH64_FEATURE_HASFP16FML, "HasFP16FML" },
|
||||
{ AARCH64_FEATURE_HASSPE, "HasSPE" },
|
||||
{ AARCH64_FEATURE_HASFUSEAES, "HasFuseAES" },
|
||||
{ AARCH64_FEATURE_HASSVE, "HasSVE" },
|
||||
{ AARCH64_FEATURE_HASSVE2, "HasSVE2" },
|
||||
{ AARCH64_FEATURE_HASSVE2P1, "HasSVE2p1" },
|
||||
{ AARCH64_FEATURE_HASSVE2AES, "HasSVE2AES" },
|
||||
{ AARCH64_FEATURE_HASSVE2SM4, "HasSVE2SM4" },
|
||||
{ AARCH64_FEATURE_HASSVE2SHA3, "HasSVE2SHA3" },
|
||||
{ AARCH64_FEATURE_HASSVE2BITPERM, "HasSVE2BitPerm" },
|
||||
{ AARCH64_FEATURE_HASB16B16, "HasB16B16" },
|
||||
{ AARCH64_FEATURE_HASSME, "HasSME" },
|
||||
{ AARCH64_FEATURE_HASSMEF64F64, "HasSMEF64F64" },
|
||||
{ AARCH64_FEATURE_HASSMEF16F16, "HasSMEF16F16" },
|
||||
{ AARCH64_FEATURE_HASSMEFA64, "HasSMEFA64" },
|
||||
{ AARCH64_FEATURE_HASSMEI16I64, "HasSMEI16I64" },
|
||||
{ AARCH64_FEATURE_HASSME2, "HasSME2" },
|
||||
{ AARCH64_FEATURE_HASSME2P1, "HasSME2p1" },
|
||||
{ AARCH64_FEATURE_HASFPMR, "HasFPMR" },
|
||||
{ AARCH64_FEATURE_HASFP8, "HasFP8" },
|
||||
{ AARCH64_FEATURE_HASFAMINMAX, "HasFAMINMAX" },
|
||||
{ AARCH64_FEATURE_HASFP8FMA, "HasFP8FMA" },
|
||||
{ AARCH64_FEATURE_HASSSVE_FP8FMA, "HasSSVE_FP8FMA" },
|
||||
{ AARCH64_FEATURE_HASFP8DOT2, "HasFP8DOT2" },
|
||||
{ AARCH64_FEATURE_HASSSVE_FP8DOT2, "HasSSVE_FP8DOT2" },
|
||||
{ AARCH64_FEATURE_HASFP8DOT4, "HasFP8DOT4" },
|
||||
{ AARCH64_FEATURE_HASSSVE_FP8DOT4, "HasSSVE_FP8DOT4" },
|
||||
{ AARCH64_FEATURE_HASLUT, "HasLUT" },
|
||||
{ AARCH64_FEATURE_HASSME_LUTV2, "HasSME_LUTv2" },
|
||||
{ AARCH64_FEATURE_HASSMEF8F16, "HasSMEF8F16" },
|
||||
{ AARCH64_FEATURE_HASSMEF8F32, "HasSMEF8F32" },
|
||||
{ AARCH64_FEATURE_HASSVEORSME, "HasSVEorSME" },
|
||||
{ AARCH64_FEATURE_HASSVE2ORSME, "HasSVE2orSME" },
|
||||
{ AARCH64_FEATURE_HASSVE2ORSME2, "HasSVE2orSME2" },
|
||||
{ AARCH64_FEATURE_HASSVE2P1_OR_HASSME, "HasSVE2p1_or_HasSME" },
|
||||
{ AARCH64_FEATURE_HASSVE2P1_OR_HASSME2, "HasSVE2p1_or_HasSME2" },
|
||||
{ AARCH64_FEATURE_HASSVE2P1_OR_HASSME2P1, "HasSVE2p1_or_HasSME2p1" },
|
||||
{ AARCH64_FEATURE_HASNEONORSME, "HasNEONorSME" },
|
||||
{ AARCH64_FEATURE_HASRCPC, "HasRCPC" },
|
||||
{ AARCH64_FEATURE_HASALTNZCV, "HasAltNZCV" },
|
||||
{ AARCH64_FEATURE_HASFRINT3264, "HasFRInt3264" },
|
||||
{ AARCH64_FEATURE_HASSB, "HasSB" },
|
||||
{ AARCH64_FEATURE_HASPREDRES, "HasPredRes" },
|
||||
{ AARCH64_FEATURE_HASCCDP, "HasCCDP" },
|
||||
{ AARCH64_FEATURE_HASBTI, "HasBTI" },
|
||||
{ AARCH64_FEATURE_HASMTE, "HasMTE" },
|
||||
{ AARCH64_FEATURE_HASTME, "HasTME" },
|
||||
{ AARCH64_FEATURE_HASETE, "HasETE" },
|
||||
{ AARCH64_FEATURE_HASTRBE, "HasTRBE" },
|
||||
{ AARCH64_FEATURE_HASBF16, "HasBF16" },
|
||||
{ AARCH64_FEATURE_HASMATMULINT8, "HasMatMulInt8" },
|
||||
{ AARCH64_FEATURE_HASMATMULFP32, "HasMatMulFP32" },
|
||||
{ AARCH64_FEATURE_HASMATMULFP64, "HasMatMulFP64" },
|
||||
{ AARCH64_FEATURE_HASXS, "HasXS" },
|
||||
{ AARCH64_FEATURE_HASWFXT, "HasWFxT" },
|
||||
{ AARCH64_FEATURE_HASLS64, "HasLS64" },
|
||||
{ AARCH64_FEATURE_HASBRBE, "HasBRBE" },
|
||||
{ AARCH64_FEATURE_HASSPE_EEF, "HasSPE_EEF" },
|
||||
{ AARCH64_FEATURE_HASHBC, "HasHBC" },
|
||||
{ AARCH64_FEATURE_HASMOPS, "HasMOPS" },
|
||||
{ AARCH64_FEATURE_HASCLRBHB, "HasCLRBHB" },
|
||||
{ AARCH64_FEATURE_HASSPECRES2, "HasSPECRES2" },
|
||||
{ AARCH64_FEATURE_HASITE, "HasITE" },
|
||||
{ AARCH64_FEATURE_HASTHE, "HasTHE" },
|
||||
{ AARCH64_FEATURE_HASRCPC3, "HasRCPC3" },
|
||||
{ AARCH64_FEATURE_HASLSE128, "HasLSE128" },
|
||||
{ AARCH64_FEATURE_HASD128, "HasD128" },
|
||||
{ AARCH64_FEATURE_HASCHK, "HasCHK" },
|
||||
{ AARCH64_FEATURE_HASGCS, "HasGCS" },
|
||||
{ AARCH64_FEATURE_HASCPA, "HasCPA" },
|
||||
{ AARCH64_FEATURE_USENEGATIVEIMMEDIATES, "UseNegativeImmediates" },
|
||||
{ AARCH64_FEATURE_HASAMX, "HasAMX" },
|
||||
{ AARCH64_FEATURE_HASMUL53, "HasMUL53" },
|
||||
{ AARCH64_FEATURE_HASAPPLESYS, "HasAppleSys" },
|
||||
{ AARCH64_FEATURE_HASCCPP, "HasCCPP" },
|
||||
{ AARCH64_FEATURE_HASPAN, "HasPAN" },
|
||||
{ AARCH64_FEATURE_HASPSUAO, "HasPsUAO" },
|
||||
{ AARCH64_FEATURE_HASPAN_RWV, "HasPAN_RWV" },
|
||||
{ AARCH64_FEATURE_HASCONTEXTIDREL2, "HasCONTEXTIDREL2" },
|
||||
+64676
File diff suppressed because it is too large
Load Diff
+1435
File diff suppressed because it is too large
Load Diff
+55762
File diff suppressed because it is too large
Load Diff
+181
@@ -0,0 +1,181 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
AArch64_OP_GROUP_AMNoIndex = 0,
|
||||
AArch64_OP_GROUP_AdrLabel = 1,
|
||||
AArch64_OP_GROUP_AdrpLabel = 2,
|
||||
AArch64_OP_GROUP_BTIHintOp = 3,
|
||||
AArch64_OP_GROUP_ImplicitlyTypedVectorList = 4,
|
||||
AArch64_OP_GROUP_InverseCondCode = 5,
|
||||
AArch64_OP_GROUP_LogicalImm_int16_t = 6,
|
||||
AArch64_OP_GROUP_LogicalImm_int8_t = 7,
|
||||
AArch64_OP_GROUP_MatrixIndex_0 = 8,
|
||||
AArch64_OP_GROUP_MatrixIndex_1 = 9,
|
||||
AArch64_OP_GROUP_MatrixIndex_8 = 10,
|
||||
AArch64_OP_GROUP_PSBHintOp = 11,
|
||||
AArch64_OP_GROUP_PrefetchOp_1 = 12,
|
||||
AArch64_OP_GROUP_SVELogicalImm_int16_t = 13,
|
||||
AArch64_OP_GROUP_SVELogicalImm_int32_t = 14,
|
||||
AArch64_OP_GROUP_SVELogicalImm_int64_t = 15,
|
||||
AArch64_OP_GROUP_SVERegOp_0 = 16,
|
||||
AArch64_OP_GROUP_VectorIndex_8 = 17,
|
||||
AArch64_OP_GROUP_ZPRasFPR_128 = 18,
|
||||
AArch64_OP_GROUP_Operand = 19,
|
||||
AArch64_OP_GROUP_SVERegOp_b = 20,
|
||||
AArch64_OP_GROUP_SVERegOp_d = 21,
|
||||
AArch64_OP_GROUP_SVERegOp_h = 22,
|
||||
AArch64_OP_GROUP_SVERegOp_s = 23,
|
||||
AArch64_OP_GROUP_TypedVectorList_0_d = 24,
|
||||
AArch64_OP_GROUP_TypedVectorList_0_s = 25,
|
||||
AArch64_OP_GROUP_VRegOperand = 26,
|
||||
AArch64_OP_GROUP_TypedVectorList_0_h = 27,
|
||||
AArch64_OP_GROUP_VectorIndex_1 = 28,
|
||||
AArch64_OP_GROUP_ImmRangeScale_2_1 = 29,
|
||||
AArch64_OP_GROUP_AlignedLabel = 30,
|
||||
AArch64_OP_GROUP_CondCode = 31,
|
||||
AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_one = 32,
|
||||
AArch64_OP_GROUP_TypedVectorList_0_b = 33,
|
||||
AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_zero_AArch64ExactFPImm_one = 34,
|
||||
AArch64_OP_GROUP_ImmRangeScale_4_3 = 35,
|
||||
AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_two = 36,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_d = 37,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_d = 38,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_d = 39,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_s = 40,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_s = 41,
|
||||
AArch64_OP_GROUP_ImmScale_8 = 42,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_d = 43,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_d = 44,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_d = 45,
|
||||
AArch64_OP_GROUP_ImmScale_2 = 46,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_d = 47,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_d = 48,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_d = 49,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_s = 50,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_s = 51,
|
||||
AArch64_OP_GROUP_ImmScale_4 = 52,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_d = 53,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_d = 54,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_d = 55,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_s = 56,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_s = 57,
|
||||
AArch64_OP_GROUP_PredicateAsCounter_0 = 58,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_0 = 59,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_0 = 60,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_0 = 61,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_0 = 62,
|
||||
AArch64_OP_GROUP_SVCROp = 63,
|
||||
AArch64_OP_GROUP_ImmScale_16 = 64,
|
||||
AArch64_OP_GROUP_MatrixTile = 65,
|
||||
AArch64_OP_GROUP_Shifter = 66,
|
||||
AArch64_OP_GROUP_AddSubImm = 67,
|
||||
AArch64_OP_GROUP_ShiftedRegister = 68,
|
||||
AArch64_OP_GROUP_ExtendedRegister = 69,
|
||||
AArch64_OP_GROUP_ArithExtend = 70,
|
||||
AArch64_OP_GROUP_Matrix_64 = 71,
|
||||
AArch64_OP_GROUP_Matrix_32 = 72,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_uint8_t = 73,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_uint64_t = 74,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_uint16_t = 75,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_uint32_t = 76,
|
||||
AArch64_OP_GROUP_AdrAdrpLabel = 77,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_s = 78,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_s = 79,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_s = 80,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_s = 81,
|
||||
AArch64_OP_GROUP_LogicalImm_int32_t = 82,
|
||||
AArch64_OP_GROUP_LogicalImm_int64_t = 83,
|
||||
AArch64_OP_GROUP_ZPRasFPR_8 = 84,
|
||||
AArch64_OP_GROUP_ZPRasFPR_64 = 85,
|
||||
AArch64_OP_GROUP_ZPRasFPR_16 = 86,
|
||||
AArch64_OP_GROUP_ZPRasFPR_32 = 87,
|
||||
AArch64_OP_GROUP_Matrix_16 = 88,
|
||||
AArch64_OP_GROUP_Imm = 89,
|
||||
AArch64_OP_GROUP_ImmHex = 90,
|
||||
AArch64_OP_GROUP_ComplexRotationOp_180_90 = 91,
|
||||
AArch64_OP_GROUP_GPRSeqPairsClassOperand_32 = 92,
|
||||
AArch64_OP_GROUP_GPRSeqPairsClassOperand_64 = 93,
|
||||
AArch64_OP_GROUP_ComplexRotationOp_90_0 = 94,
|
||||
AArch64_OP_GROUP_SVEPattern = 95,
|
||||
AArch64_OP_GROUP_PredicateAsCounter_8 = 96,
|
||||
AArch64_OP_GROUP_SVEVecLenSpecifier = 97,
|
||||
AArch64_OP_GROUP_PredicateAsCounter_64 = 98,
|
||||
AArch64_OP_GROUP_PredicateAsCounter_16 = 99,
|
||||
AArch64_OP_GROUP_PredicateAsCounter_32 = 100,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_int8_t = 101,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_int64_t = 102,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_int16_t = 103,
|
||||
AArch64_OP_GROUP_Imm8OptLsl_int32_t = 104,
|
||||
AArch64_OP_GROUP_BarrierOption = 105,
|
||||
AArch64_OP_GROUP_BarriernXSOption = 106,
|
||||
AArch64_OP_GROUP_SVERegOp_q = 107,
|
||||
AArch64_OP_GROUP_MatrixTileVector_0 = 108,
|
||||
AArch64_OP_GROUP_MatrixTileVector_1 = 109,
|
||||
AArch64_OP_GROUP_FPImmOperand = 110,
|
||||
AArch64_OP_GROUP_TypedVectorList_0_q = 111,
|
||||
AArch64_OP_GROUP_SImm_8 = 112,
|
||||
AArch64_OP_GROUP_SImm_16 = 113,
|
||||
AArch64_OP_GROUP_TypedVectorList_16_b = 114,
|
||||
AArch64_OP_GROUP_PostIncOperand_64 = 115,
|
||||
AArch64_OP_GROUP_TypedVectorList_1_d = 116,
|
||||
AArch64_OP_GROUP_PostIncOperand_32 = 117,
|
||||
AArch64_OP_GROUP_TypedVectorList_2_d = 118,
|
||||
AArch64_OP_GROUP_TypedVectorList_2_s = 119,
|
||||
AArch64_OP_GROUP_TypedVectorList_4_h = 120,
|
||||
AArch64_OP_GROUP_TypedVectorList_4_s = 121,
|
||||
AArch64_OP_GROUP_TypedVectorList_8_b = 122,
|
||||
AArch64_OP_GROUP_TypedVectorList_8_h = 123,
|
||||
AArch64_OP_GROUP_PostIncOperand_16 = 124,
|
||||
AArch64_OP_GROUP_PostIncOperand_8 = 125,
|
||||
AArch64_OP_GROUP_ImmScale_32 = 126,
|
||||
AArch64_OP_GROUP_PostIncOperand_1 = 127,
|
||||
AArch64_OP_GROUP_PostIncOperand_4 = 128,
|
||||
AArch64_OP_GROUP_PostIncOperand_2 = 129,
|
||||
AArch64_OP_GROUP_PostIncOperand_48 = 130,
|
||||
AArch64_OP_GROUP_PostIncOperand_24 = 131,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_128_x_0 = 132,
|
||||
AArch64_OP_GROUP_ImmScale_3 = 133,
|
||||
AArch64_OP_GROUP_PostIncOperand_3 = 134,
|
||||
AArch64_OP_GROUP_PostIncOperand_12 = 135,
|
||||
AArch64_OP_GROUP_PostIncOperand_6 = 136,
|
||||
AArch64_OP_GROUP_GPR64x8 = 137,
|
||||
AArch64_OP_GROUP_MemExtend_w_8 = 138,
|
||||
AArch64_OP_GROUP_MemExtend_x_8 = 139,
|
||||
AArch64_OP_GROUP_UImm12Offset_1 = 140,
|
||||
AArch64_OP_GROUP_MemExtend_w_64 = 141,
|
||||
AArch64_OP_GROUP_MemExtend_x_64 = 142,
|
||||
AArch64_OP_GROUP_UImm12Offset_8 = 143,
|
||||
AArch64_OP_GROUP_MemExtend_w_16 = 144,
|
||||
AArch64_OP_GROUP_MemExtend_x_16 = 145,
|
||||
AArch64_OP_GROUP_UImm12Offset_2 = 146,
|
||||
AArch64_OP_GROUP_MemExtend_w_128 = 147,
|
||||
AArch64_OP_GROUP_MemExtend_x_128 = 148,
|
||||
AArch64_OP_GROUP_UImm12Offset_16 = 149,
|
||||
AArch64_OP_GROUP_MemExtend_w_32 = 150,
|
||||
AArch64_OP_GROUP_MemExtend_x_32 = 151,
|
||||
AArch64_OP_GROUP_UImm12Offset_4 = 152,
|
||||
AArch64_OP_GROUP_Matrix_0 = 153,
|
||||
AArch64_OP_GROUP_TypedVectorList_0_0 = 154,
|
||||
AArch64_OP_GROUP_SIMDType10Operand = 155,
|
||||
AArch64_OP_GROUP_MRSSystemRegister = 156,
|
||||
AArch64_OP_GROUP_MSRSystemRegister = 157,
|
||||
AArch64_OP_GROUP_SystemPStateField = 158,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_s = 159,
|
||||
AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_s = 160,
|
||||
AArch64_OP_GROUP_PrefetchOp_0 = 161,
|
||||
AArch64_OP_GROUP_RPRFMOperand = 162,
|
||||
AArch64_OP_GROUP_AppleSysBarrierOption = 163,
|
||||
AArch64_OP_GROUP_GPR64as32 = 164,
|
||||
AArch64_OP_GROUP_SysCROperand = 165,
|
||||
AArch64_OP_GROUP_SyspXzrPair = 166,
|
||||
AArch64_OP_GROUP_MatrixTileList = 167,
|
||||
+35685
File diff suppressed because it is too large
Load Diff
+18301
File diff suppressed because it is too large
Load Diff
+6169
File diff suppressed because it is too large
Load Diff
+301
@@ -0,0 +1,301 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
#ifdef GET_SUBTARGETINFO_ENUM
|
||||
#undef GET_SUBTARGETINFO_ENUM
|
||||
|
||||
enum {
|
||||
AArch64_FeatureAES = 0,
|
||||
AArch64_FeatureALULSLFast = 1,
|
||||
AArch64_FeatureAM = 2,
|
||||
AArch64_FeatureAMVS = 3,
|
||||
AArch64_FeatureAMX = 4,
|
||||
AArch64_FeatureAddrLSLFast = 5,
|
||||
AArch64_FeatureAggressiveFMA = 6,
|
||||
AArch64_FeatureAll = 7,
|
||||
AArch64_FeatureAltFPCmp = 8,
|
||||
AArch64_FeatureAlternateSExtLoadCVTF32Pattern = 9,
|
||||
AArch64_FeatureAppleA7SysReg = 10,
|
||||
AArch64_FeatureAppleSys = 11,
|
||||
AArch64_FeatureArithmeticBccFusion = 12,
|
||||
AArch64_FeatureArithmeticCbzFusion = 13,
|
||||
AArch64_FeatureAscendStoreAddress = 14,
|
||||
AArch64_FeatureB16B16 = 15,
|
||||
AArch64_FeatureBF16 = 16,
|
||||
AArch64_FeatureBRBE = 17,
|
||||
AArch64_FeatureBalanceFPOps = 18,
|
||||
AArch64_FeatureBranchTargetId = 19,
|
||||
AArch64_FeatureCCIDX = 20,
|
||||
AArch64_FeatureCCPP = 21,
|
||||
AArch64_FeatureCHK = 22,
|
||||
AArch64_FeatureCLRBHB = 23,
|
||||
AArch64_FeatureCONTEXTIDREL2 = 24,
|
||||
AArch64_FeatureCPA = 25,
|
||||
AArch64_FeatureCRC = 26,
|
||||
AArch64_FeatureCSSC = 27,
|
||||
AArch64_FeatureCacheDeepPersist = 28,
|
||||
AArch64_FeatureCallSavedX8 = 29,
|
||||
AArch64_FeatureCallSavedX9 = 30,
|
||||
AArch64_FeatureCallSavedX10 = 31,
|
||||
AArch64_FeatureCallSavedX11 = 32,
|
||||
AArch64_FeatureCallSavedX12 = 33,
|
||||
AArch64_FeatureCallSavedX13 = 34,
|
||||
AArch64_FeatureCallSavedX14 = 35,
|
||||
AArch64_FeatureCallSavedX15 = 36,
|
||||
AArch64_FeatureCallSavedX18 = 37,
|
||||
AArch64_FeatureCmpBccFusion = 38,
|
||||
AArch64_FeatureComplxNum = 39,
|
||||
AArch64_FeatureCrypto = 40,
|
||||
AArch64_FeatureD128 = 41,
|
||||
AArch64_FeatureDIT = 42,
|
||||
AArch64_FeatureDisableLatencySchedHeuristic = 43,
|
||||
AArch64_FeatureDisableLdp = 44,
|
||||
AArch64_FeatureDisableStp = 45,
|
||||
AArch64_FeatureDotProd = 46,
|
||||
AArch64_FeatureEL2VMSA = 47,
|
||||
AArch64_FeatureEL3 = 48,
|
||||
AArch64_FeatureETE = 49,
|
||||
AArch64_FeatureEnableSelectOptimize = 50,
|
||||
AArch64_FeatureEnhancedCounterVirtualization = 51,
|
||||
AArch64_FeatureExperimentalZeroingPseudos = 52,
|
||||
AArch64_FeatureExynosCheapAsMoveHandling = 53,
|
||||
AArch64_FeatureFAMINMAX = 54,
|
||||
AArch64_FeatureFMV = 55,
|
||||
AArch64_FeatureFP8 = 56,
|
||||
AArch64_FeatureFP8DOT2 = 57,
|
||||
AArch64_FeatureFP8DOT4 = 58,
|
||||
AArch64_FeatureFP8FMA = 59,
|
||||
AArch64_FeatureFP16FML = 60,
|
||||
AArch64_FeatureFPARMv8 = 61,
|
||||
AArch64_FeatureFPMR = 62,
|
||||
AArch64_FeatureFRInt3264 = 63,
|
||||
AArch64_FeatureFineGrainedTraps = 64,
|
||||
AArch64_FeatureFixCortexA53_835769 = 65,
|
||||
AArch64_FeatureFlagM = 66,
|
||||
AArch64_FeatureForce32BitJumpTables = 67,
|
||||
AArch64_FeatureFullFP16 = 68,
|
||||
AArch64_FeatureFuseAES = 69,
|
||||
AArch64_FeatureFuseAddSub2RegAndConstOne = 70,
|
||||
AArch64_FeatureFuseAddress = 71,
|
||||
AArch64_FeatureFuseAdrpAdd = 72,
|
||||
AArch64_FeatureFuseArithmeticLogic = 73,
|
||||
AArch64_FeatureFuseCCSelect = 74,
|
||||
AArch64_FeatureFuseCryptoEOR = 75,
|
||||
AArch64_FeatureFuseLiterals = 76,
|
||||
AArch64_FeatureGCS = 77,
|
||||
AArch64_FeatureHBC = 78,
|
||||
AArch64_FeatureHCX = 79,
|
||||
AArch64_FeatureHardenSlsBlr = 80,
|
||||
AArch64_FeatureHardenSlsNoComdat = 81,
|
||||
AArch64_FeatureHardenSlsRetBr = 82,
|
||||
AArch64_FeatureITE = 83,
|
||||
AArch64_FeatureJS = 84,
|
||||
AArch64_FeatureLOR = 85,
|
||||
AArch64_FeatureLS64 = 86,
|
||||
AArch64_FeatureLSE = 87,
|
||||
AArch64_FeatureLSE2 = 88,
|
||||
AArch64_FeatureLSE128 = 89,
|
||||
AArch64_FeatureLUT = 90,
|
||||
AArch64_FeatureLdpAlignedOnly = 91,
|
||||
AArch64_FeatureMEC = 92,
|
||||
AArch64_FeatureMOPS = 93,
|
||||
AArch64_FeatureMPAM = 94,
|
||||
AArch64_FeatureMTE = 95,
|
||||
AArch64_FeatureMUL53 = 96,
|
||||
AArch64_FeatureMatMulFP32 = 97,
|
||||
AArch64_FeatureMatMulFP64 = 98,
|
||||
AArch64_FeatureMatMulInt8 = 99,
|
||||
AArch64_FeatureNEON = 100,
|
||||
AArch64_FeatureNMI = 101,
|
||||
AArch64_FeatureNV = 102,
|
||||
AArch64_FeatureNoBTIAtReturnTwice = 103,
|
||||
AArch64_FeatureNoNegativeImmediates = 104,
|
||||
AArch64_FeatureNoSVEFPLD1R = 105,
|
||||
AArch64_FeatureNoZCZeroingFP = 106,
|
||||
AArch64_FeatureOutlineAtomics = 107,
|
||||
AArch64_FeaturePAN = 108,
|
||||
AArch64_FeaturePAN_RWV = 109,
|
||||
AArch64_FeaturePAuth = 110,
|
||||
AArch64_FeaturePAuthLR = 111,
|
||||
AArch64_FeaturePRFM_SLC = 112,
|
||||
AArch64_FeaturePerfMon = 113,
|
||||
AArch64_FeaturePostRAScheduler = 114,
|
||||
AArch64_FeaturePredRes = 115,
|
||||
AArch64_FeaturePredictableSelectIsExpensive = 116,
|
||||
AArch64_FeaturePsUAO = 117,
|
||||
AArch64_FeatureRAS = 118,
|
||||
AArch64_FeatureRASv2 = 119,
|
||||
AArch64_FeatureRCPC = 120,
|
||||
AArch64_FeatureRCPC3 = 121,
|
||||
AArch64_FeatureRCPC_IMMO = 122,
|
||||
AArch64_FeatureRDM = 123,
|
||||
AArch64_FeatureRME = 124,
|
||||
AArch64_FeatureRandGen = 125,
|
||||
AArch64_FeatureReserveX1 = 126,
|
||||
AArch64_FeatureReserveX2 = 127,
|
||||
AArch64_FeatureReserveX3 = 128,
|
||||
AArch64_FeatureReserveX4 = 129,
|
||||
AArch64_FeatureReserveX5 = 130,
|
||||
AArch64_FeatureReserveX6 = 131,
|
||||
AArch64_FeatureReserveX7 = 132,
|
||||
AArch64_FeatureReserveX9 = 133,
|
||||
AArch64_FeatureReserveX10 = 134,
|
||||
AArch64_FeatureReserveX11 = 135,
|
||||
AArch64_FeatureReserveX12 = 136,
|
||||
AArch64_FeatureReserveX13 = 137,
|
||||
AArch64_FeatureReserveX14 = 138,
|
||||
AArch64_FeatureReserveX15 = 139,
|
||||
AArch64_FeatureReserveX18 = 140,
|
||||
AArch64_FeatureReserveX20 = 141,
|
||||
AArch64_FeatureReserveX21 = 142,
|
||||
AArch64_FeatureReserveX22 = 143,
|
||||
AArch64_FeatureReserveX23 = 144,
|
||||
AArch64_FeatureReserveX24 = 145,
|
||||
AArch64_FeatureReserveX25 = 146,
|
||||
AArch64_FeatureReserveX26 = 147,
|
||||
AArch64_FeatureReserveX27 = 148,
|
||||
AArch64_FeatureReserveX28 = 149,
|
||||
AArch64_FeatureReserveX30 = 150,
|
||||
AArch64_FeatureSB = 151,
|
||||
AArch64_FeatureSEL2 = 152,
|
||||
AArch64_FeatureSHA2 = 153,
|
||||
AArch64_FeatureSHA3 = 154,
|
||||
AArch64_FeatureSM4 = 155,
|
||||
AArch64_FeatureSME = 156,
|
||||
AArch64_FeatureSME2 = 157,
|
||||
AArch64_FeatureSME2p1 = 158,
|
||||
AArch64_FeatureSMEF8F16 = 159,
|
||||
AArch64_FeatureSMEF8F32 = 160,
|
||||
AArch64_FeatureSMEF16F16 = 161,
|
||||
AArch64_FeatureSMEF64F64 = 162,
|
||||
AArch64_FeatureSMEFA64 = 163,
|
||||
AArch64_FeatureSMEI16I64 = 164,
|
||||
AArch64_FeatureSME_LUTv2 = 165,
|
||||
AArch64_FeatureSPE = 166,
|
||||
AArch64_FeatureSPECRES2 = 167,
|
||||
AArch64_FeatureSPE_EEF = 168,
|
||||
AArch64_FeatureSSBS = 169,
|
||||
AArch64_FeatureSSVE_FP8DOT2 = 170,
|
||||
AArch64_FeatureSSVE_FP8DOT4 = 171,
|
||||
AArch64_FeatureSSVE_FP8FMA = 172,
|
||||
AArch64_FeatureSVE = 173,
|
||||
AArch64_FeatureSVE2 = 174,
|
||||
AArch64_FeatureSVE2AES = 175,
|
||||
AArch64_FeatureSVE2BitPerm = 176,
|
||||
AArch64_FeatureSVE2SHA3 = 177,
|
||||
AArch64_FeatureSVE2SM4 = 178,
|
||||
AArch64_FeatureSVE2p1 = 179,
|
||||
AArch64_FeatureSlowMisaligned128Store = 180,
|
||||
AArch64_FeatureSlowPaired128 = 181,
|
||||
AArch64_FeatureSlowSTRQro = 182,
|
||||
AArch64_FeatureSpecRestrict = 183,
|
||||
AArch64_FeatureStorePairSuppress = 184,
|
||||
AArch64_FeatureStpAlignedOnly = 185,
|
||||
AArch64_FeatureStrictAlign = 186,
|
||||
AArch64_FeatureTHE = 187,
|
||||
AArch64_FeatureTLBIW = 188,
|
||||
AArch64_FeatureTLB_RMI = 189,
|
||||
AArch64_FeatureTME = 190,
|
||||
AArch64_FeatureTRACEV8_4 = 191,
|
||||
AArch64_FeatureTRBE = 192,
|
||||
AArch64_FeatureTaggedGlobals = 193,
|
||||
AArch64_FeatureUseEL1ForTP = 194,
|
||||
AArch64_FeatureUseEL2ForTP = 195,
|
||||
AArch64_FeatureUseEL3ForTP = 196,
|
||||
AArch64_FeatureUseROEL0ForTP = 197,
|
||||
AArch64_FeatureUseRSqrt = 198,
|
||||
AArch64_FeatureUseScalarIncVL = 199,
|
||||
AArch64_FeatureVH = 200,
|
||||
AArch64_FeatureWFxT = 201,
|
||||
AArch64_FeatureXS = 202,
|
||||
AArch64_FeatureZCRegMove = 203,
|
||||
AArch64_FeatureZCZeroing = 204,
|
||||
AArch64_FeatureZCZeroingFPWorkaround = 205,
|
||||
AArch64_FeatureZCZeroingGP = 206,
|
||||
AArch64_HasV8_0aOps = 207,
|
||||
AArch64_HasV8_0rOps = 208,
|
||||
AArch64_HasV8_1aOps = 209,
|
||||
AArch64_HasV8_2aOps = 210,
|
||||
AArch64_HasV8_3aOps = 211,
|
||||
AArch64_HasV8_4aOps = 212,
|
||||
AArch64_HasV8_5aOps = 213,
|
||||
AArch64_HasV8_6aOps = 214,
|
||||
AArch64_HasV8_7aOps = 215,
|
||||
AArch64_HasV8_8aOps = 216,
|
||||
AArch64_HasV8_9aOps = 217,
|
||||
AArch64_HasV9_0aOps = 218,
|
||||
AArch64_HasV9_1aOps = 219,
|
||||
AArch64_HasV9_2aOps = 220,
|
||||
AArch64_HasV9_3aOps = 221,
|
||||
AArch64_HasV9_4aOps = 222,
|
||||
AArch64_HasV9_5aOps = 223,
|
||||
AArch64_TuneA35 = 224,
|
||||
AArch64_TuneA53 = 225,
|
||||
AArch64_TuneA55 = 226,
|
||||
AArch64_TuneA57 = 227,
|
||||
AArch64_TuneA64FX = 228,
|
||||
AArch64_TuneA65 = 229,
|
||||
AArch64_TuneA72 = 230,
|
||||
AArch64_TuneA73 = 231,
|
||||
AArch64_TuneA75 = 232,
|
||||
AArch64_TuneA76 = 233,
|
||||
AArch64_TuneA77 = 234,
|
||||
AArch64_TuneA78 = 235,
|
||||
AArch64_TuneA78C = 236,
|
||||
AArch64_TuneA510 = 237,
|
||||
AArch64_TuneA520 = 238,
|
||||
AArch64_TuneA710 = 239,
|
||||
AArch64_TuneA715 = 240,
|
||||
AArch64_TuneA720 = 241,
|
||||
AArch64_TuneAmpere1 = 242,
|
||||
AArch64_TuneAmpere1A = 243,
|
||||
AArch64_TuneAmpere1B = 244,
|
||||
AArch64_TuneAppleA7 = 245,
|
||||
AArch64_TuneAppleA10 = 246,
|
||||
AArch64_TuneAppleA11 = 247,
|
||||
AArch64_TuneAppleA12 = 248,
|
||||
AArch64_TuneAppleA13 = 249,
|
||||
AArch64_TuneAppleA14 = 250,
|
||||
AArch64_TuneAppleA15 = 251,
|
||||
AArch64_TuneAppleA16 = 252,
|
||||
AArch64_TuneAppleA17 = 253,
|
||||
AArch64_TuneCarmel = 254,
|
||||
AArch64_TuneExynosM3 = 255,
|
||||
AArch64_TuneExynosM4 = 256,
|
||||
AArch64_TuneFalkor = 257,
|
||||
AArch64_TuneKryo = 258,
|
||||
AArch64_TuneNeoverse512TVB = 259,
|
||||
AArch64_TuneNeoverseE1 = 260,
|
||||
AArch64_TuneNeoverseN1 = 261,
|
||||
AArch64_TuneNeoverseN2 = 262,
|
||||
AArch64_TuneNeoverseV1 = 263,
|
||||
AArch64_TuneNeoverseV2 = 264,
|
||||
AArch64_TuneR82 = 265,
|
||||
AArch64_TuneSaphira = 266,
|
||||
AArch64_TuneTSV110 = 267,
|
||||
AArch64_TuneThunderX = 268,
|
||||
AArch64_TuneThunderX2T99 = 269,
|
||||
AArch64_TuneThunderX3T110 = 270,
|
||||
AArch64_TuneThunderXT81 = 271,
|
||||
AArch64_TuneThunderXT83 = 272,
|
||||
AArch64_TuneThunderXT88 = 273,
|
||||
AArch64_TuneX1 = 274,
|
||||
AArch64_TuneX2 = 275,
|
||||
AArch64_TuneX3 = 276,
|
||||
AArch64_TuneX4 = 277,
|
||||
AArch64_NumSubtargetFeatures = 278
|
||||
};
|
||||
#endif // GET_SUBTARGETINFO_ENUM
|
||||
|
||||
|
||||
|
||||
+5379
File diff suppressed because it is too large
Load Diff
+5379
File diff suppressed because it is too large
Load Diff
+2611
File diff suppressed because it is too large
Load Diff
+351
@@ -0,0 +1,351 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===-- AArch64InstPrinter.h - Convert AArch64 MCInst to assembly syntax --===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an AArch64 MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64INSTPRINTER_H
|
||||
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64INSTPRINTER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "AArch64Mapping.h"
|
||||
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../MCInstPrinter.h"
|
||||
#include "../../SStream.h"
|
||||
#include "../../utils.h"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
#define CHAR(c) #c[0]
|
||||
|
||||
void printInst(MCInst *MI, uint64_t Address, const char *Annot, SStream *O);
|
||||
void printRegName(SStream *OS, unsigned Reg);
|
||||
void printRegNameAlt(SStream *OS, unsigned Reg, unsigned AltIdx);
|
||||
// Autogenerated by tblgen.
|
||||
const char *getRegName(unsigned Reg);
|
||||
bool printSysAlias(MCInst *MI, SStream *O);
|
||||
bool printSyspAlias(MCInst *MI, SStream *O);
|
||||
bool printRangePrefetchAlias(MCInst *MI, SStream *O, const char *Annot);
|
||||
// Operand printers
|
||||
void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
|
||||
void printImm(MCInst *MI, unsigned OpNo, SStream *O);
|
||||
void printImmHex(MCInst *MI, unsigned OpNo, SStream *O);
|
||||
#define DECLARE_printSImm(Size) \
|
||||
void CONCAT(printSImm, Size)(MCInst * MI, unsigned OpNo, SStream *O);
|
||||
DECLARE_printSImm(16);
|
||||
DECLARE_printSImm(8);
|
||||
|
||||
#define DECLARE_printImmSVE(T) void CONCAT(printImmSVE, T)(T Val, SStream * O);
|
||||
DECLARE_printImmSVE(int16_t);
|
||||
DECLARE_printImmSVE(int8_t);
|
||||
DECLARE_printImmSVE(int64_t);
|
||||
DECLARE_printImmSVE(int32_t);
|
||||
DECLARE_printImmSVE(uint16_t);
|
||||
DECLARE_printImmSVE(uint8_t);
|
||||
DECLARE_printImmSVE(uint64_t);
|
||||
DECLARE_printImmSVE(uint32_t);
|
||||
|
||||
void printPostIncOperand(MCInst *MI, unsigned OpNo, unsigned Imm, SStream *O);
|
||||
#define DEFINE_printPostIncOperand(Amount) \
|
||||
static inline void CONCAT(printPostIncOperand, Amount)( \
|
||||
MCInst * MI, unsigned OpNo, SStream *O) \
|
||||
{ \
|
||||
AArch64_add_cs_detail_1( \
|
||||
MI, CONCAT(AArch64_OP_GROUP_PostIncOperand, Amount), \
|
||||
OpNo, Amount); \
|
||||
printPostIncOperand(MI, OpNo, Amount, O); \
|
||||
}
|
||||
DEFINE_printPostIncOperand(64);
|
||||
DEFINE_printPostIncOperand(32);
|
||||
DEFINE_printPostIncOperand(16);
|
||||
DEFINE_printPostIncOperand(8);
|
||||
DEFINE_printPostIncOperand(1);
|
||||
DEFINE_printPostIncOperand(4);
|
||||
DEFINE_printPostIncOperand(2);
|
||||
DEFINE_printPostIncOperand(48);
|
||||
DEFINE_printPostIncOperand(24);
|
||||
DEFINE_printPostIncOperand(3);
|
||||
DEFINE_printPostIncOperand(12);
|
||||
DEFINE_printPostIncOperand(6);
|
||||
|
||||
void printVRegOperand(MCInst *MI, unsigned OpNo, SStream *O);
|
||||
void printSysCROperand(MCInst *MI, unsigned OpNo, SStream *O);
|
||||
void printAddSubImm(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printLogicalImm(T) \
|
||||
void CONCAT(printLogicalImm, T)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printLogicalImm(int64_t);
|
||||
DECLARE_printLogicalImm(int32_t);
|
||||
DECLARE_printLogicalImm(int8_t);
|
||||
DECLARE_printLogicalImm(int16_t);
|
||||
|
||||
void printShifter(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printShiftedRegister(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printExtendedRegister(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printArithExtend(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
|
||||
void printMemExtend(MCInst *MI, unsigned OpNum, SStream *O, char SrcRegKind,
|
||||
unsigned Width);
|
||||
void printMemExtend(MCInst *MI, unsigned OpNum, SStream *O, char SrcRegKind,
|
||||
unsigned Width);
|
||||
#define DEFINE_printMemExtend(SrcRegKind, Width) \
|
||||
static inline void CONCAT(printMemExtend, CONCAT(SrcRegKind, Width))( \
|
||||
MCInst * MI, unsigned OpNum, SStream *O) \
|
||||
{ \
|
||||
AArch64_add_cs_detail_2( \
|
||||
MI, \
|
||||
CONCAT(CONCAT(AArch64_OP_GROUP_MemExtend, SrcRegKind), \
|
||||
Width), \
|
||||
OpNum, CHAR(SrcRegKind), Width); \
|
||||
printMemExtend(MI, OpNum, O, CHAR(SrcRegKind), Width); \
|
||||
}
|
||||
DEFINE_printMemExtend(w, 8);
|
||||
DEFINE_printMemExtend(x, 8);
|
||||
DEFINE_printMemExtend(w, 64);
|
||||
DEFINE_printMemExtend(x, 64);
|
||||
DEFINE_printMemExtend(w, 16);
|
||||
DEFINE_printMemExtend(x, 16);
|
||||
DEFINE_printMemExtend(w, 128);
|
||||
DEFINE_printMemExtend(x, 128);
|
||||
DEFINE_printMemExtend(w, 32);
|
||||
DEFINE_printMemExtend(x, 32);
|
||||
|
||||
#define DECLARE_printRegWithShiftExtend(SignedExtend, ExtWidth, SrcRegKind, \
|
||||
Suffix) \
|
||||
void CONCAT(printRegWithShiftExtend, \
|
||||
CONCAT(SignedExtend, \
|
||||
CONCAT(ExtWidth, CONCAT(SrcRegKind, Suffix))))( \
|
||||
MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printRegWithShiftExtend(false, 8, x, d);
|
||||
DECLARE_printRegWithShiftExtend(true, 8, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 8, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 8, x, 0);
|
||||
DECLARE_printRegWithShiftExtend(true, 8, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 8, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 64, x, d);
|
||||
DECLARE_printRegWithShiftExtend(true, 64, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 64, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 64, x, 0);
|
||||
DECLARE_printRegWithShiftExtend(true, 64, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 64, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 16, x, d);
|
||||
DECLARE_printRegWithShiftExtend(true, 16, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 16, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 16, x, 0);
|
||||
DECLARE_printRegWithShiftExtend(true, 16, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 16, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 32, x, d);
|
||||
DECLARE_printRegWithShiftExtend(true, 32, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 32, w, d);
|
||||
DECLARE_printRegWithShiftExtend(false, 32, x, 0);
|
||||
DECLARE_printRegWithShiftExtend(true, 32, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 32, w, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 8, x, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 16, x, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 32, x, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 64, x, s);
|
||||
DECLARE_printRegWithShiftExtend(false, 128, x, 0);
|
||||
|
||||
void printCondCode(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printInverseCondCode(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printAlignedLabel(MCInst *MI, uint64_t Address, unsigned OpNum,
|
||||
SStream *O);
|
||||
void printUImm12Offset(MCInst *MI, unsigned OpNum, unsigned Scale, SStream *O);
|
||||
void printAMIndexedWB(MCInst *MI, unsigned OpNum, unsigned Scale, SStream *O);
|
||||
#define DEFINE_printUImm12Offset(Scale) \
|
||||
static inline void CONCAT(printUImm12Offset, Scale)( \
|
||||
MCInst * MI, unsigned OpNum, SStream *O) \
|
||||
{ \
|
||||
AArch64_add_cs_detail_1( \
|
||||
MI, CONCAT(AArch64_OP_GROUP_UImm12Offset, Scale), \
|
||||
OpNum, Scale); \
|
||||
printUImm12Offset(MI, OpNum, Scale, O); \
|
||||
}
|
||||
DEFINE_printUImm12Offset(1);
|
||||
DEFINE_printUImm12Offset(8);
|
||||
DEFINE_printUImm12Offset(2);
|
||||
DEFINE_printUImm12Offset(16);
|
||||
DEFINE_printUImm12Offset(4);
|
||||
|
||||
void printAMNoIndex(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printImmScale(Scale) \
|
||||
void CONCAT(printImmScale, Scale)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printImmScale(8);
|
||||
DECLARE_printImmScale(2);
|
||||
DECLARE_printImmScale(4);
|
||||
DECLARE_printImmScale(16);
|
||||
DECLARE_printImmScale(32);
|
||||
DECLARE_printImmScale(3);
|
||||
|
||||
#define DECLARE_printImmRangeScale(Scale, Offset) \
|
||||
void CONCAT(printImmRangeScale, CONCAT(Scale, Offset))( \
|
||||
MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printImmRangeScale(2, 1);
|
||||
DECLARE_printImmRangeScale(4, 3);
|
||||
|
||||
#define DECLARE_printPrefetchOp(IsSVEPrefetch) \
|
||||
void CONCAT(printPrefetchOp, \
|
||||
IsSVEPrefetch)(MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printPrefetchOp(true);
|
||||
DECLARE_printPrefetchOp(false);
|
||||
|
||||
void printRPRFMOperand(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printPSBHintOp(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printBTIHintOp(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printVectorList(MCInst *MI, unsigned OpNum, SStream *O,
|
||||
const char *LayoutSuffix);
|
||||
void printMatrixTileList(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
/// (i.e. attached to the instruction rather than the registers).
|
||||
/// Print a list of vector registers where the type suffix is implicit
|
||||
void printImplicitlyTypedVectorList(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printTypedVectorList(NumLanes, LaneKind) \
|
||||
void CONCAT(printTypedVectorList, CONCAT(NumLanes, LaneKind))( \
|
||||
MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printTypedVectorList(0, b);
|
||||
DECLARE_printTypedVectorList(0, d);
|
||||
DECLARE_printTypedVectorList(0, h);
|
||||
DECLARE_printTypedVectorList(0, s);
|
||||
DECLARE_printTypedVectorList(0, q);
|
||||
DECLARE_printTypedVectorList(16, b);
|
||||
DECLARE_printTypedVectorList(1, d);
|
||||
DECLARE_printTypedVectorList(2, d);
|
||||
DECLARE_printTypedVectorList(2, s);
|
||||
DECLARE_printTypedVectorList(4, h);
|
||||
DECLARE_printTypedVectorList(4, s);
|
||||
DECLARE_printTypedVectorList(8, b);
|
||||
DECLARE_printTypedVectorList(8, h);
|
||||
DECLARE_printTypedVectorList(0, 0);
|
||||
|
||||
#define DECLARE_printVectorIndex(Scale) \
|
||||
void CONCAT(printVectorIndex, Scale)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printVectorIndex(1);
|
||||
DECLARE_printVectorIndex(8);
|
||||
|
||||
void printAdrAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum,
|
||||
SStream *O);
|
||||
void printAppleSysBarrierOption(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printBarrierOption(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printBarriernXSOption(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printMSRSystemRegister(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printMRSSystemRegister(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printSystemPStateField(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printSIMDType10Operand(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printPredicateAsCounter(EltSize) \
|
||||
void CONCAT(printPredicateAsCounter, \
|
||||
EltSize)(MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printPredicateAsCounter(8);
|
||||
DECLARE_printPredicateAsCounter(64);
|
||||
DECLARE_printPredicateAsCounter(16);
|
||||
DECLARE_printPredicateAsCounter(32);
|
||||
DECLARE_printPredicateAsCounter(0);
|
||||
|
||||
#define DECLARE_printGPRSeqPairsClassOperand(size) \
|
||||
void CONCAT(printGPRSeqPairsClassOperand, \
|
||||
size)(MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printGPRSeqPairsClassOperand(32);
|
||||
DECLARE_printGPRSeqPairsClassOperand(64);
|
||||
|
||||
#define DECLARE_printImm8OptLsl(T) \
|
||||
void CONCAT(printImm8OptLsl, T)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printImm8OptLsl(int16_t);
|
||||
DECLARE_printImm8OptLsl(int8_t);
|
||||
DECLARE_printImm8OptLsl(int64_t);
|
||||
DECLARE_printImm8OptLsl(int32_t);
|
||||
DECLARE_printImm8OptLsl(uint16_t);
|
||||
DECLARE_printImm8OptLsl(uint8_t);
|
||||
DECLARE_printImm8OptLsl(uint64_t);
|
||||
DECLARE_printImm8OptLsl(uint32_t);
|
||||
|
||||
#define DECLARE_printSVELogicalImm(T) \
|
||||
void CONCAT(printSVELogicalImm, T)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printSVELogicalImm(int16_t);
|
||||
DECLARE_printSVELogicalImm(int32_t);
|
||||
DECLARE_printSVELogicalImm(int64_t);
|
||||
|
||||
void printSVEPattern(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printSVEVecLenSpecifier(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printMatrixTileVector(IsVertical) \
|
||||
void CONCAT(printMatrixTileVector, \
|
||||
IsVertical)(MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printMatrixTileVector(0);
|
||||
DECLARE_printMatrixTileVector(1);
|
||||
|
||||
void printMatrixTile(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printMatrix(EltSize) \
|
||||
void CONCAT(printMatrix, EltSize)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printMatrix(64);
|
||||
DECLARE_printMatrix(32);
|
||||
DECLARE_printMatrix(16);
|
||||
DECLARE_printMatrix(0);
|
||||
|
||||
void printSVCROp(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printSVERegOp(char) \
|
||||
void CONCAT(printSVERegOp, char)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printSVERegOp(b);
|
||||
DECLARE_printSVERegOp(d);
|
||||
DECLARE_printSVERegOp(h);
|
||||
DECLARE_printSVERegOp(s);
|
||||
DECLARE_printSVERegOp(0);
|
||||
DECLARE_printSVERegOp(q);
|
||||
|
||||
void printGPR64as32(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printGPR64x8(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
void printSyspXzrPair(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
#define DECLARE_printZPRasFPR(Width) \
|
||||
void CONCAT(printZPRasFPR, Width)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printZPRasFPR(8);
|
||||
DECLARE_printZPRasFPR(64);
|
||||
DECLARE_printZPRasFPR(16);
|
||||
DECLARE_printZPRasFPR(32);
|
||||
DECLARE_printZPRasFPR(128);
|
||||
|
||||
#define DECLARE_printExactFPImm(ImmIs0, ImmIs1) \
|
||||
void CONCAT(printExactFPImm, CONCAT(ImmIs0, ImmIs1))( \
|
||||
MCInst * MI, unsigned OpNum, SStream *O);
|
||||
DECLARE_printExactFPImm(AArch64ExactFPImm_half, AArch64ExactFPImm_one);
|
||||
DECLARE_printExactFPImm(AArch64ExactFPImm_zero, AArch64ExactFPImm_one);
|
||||
DECLARE_printExactFPImm(AArch64ExactFPImm_half, AArch64ExactFPImm_two);
|
||||
|
||||
#define DECLARE_printMatrixIndex(Scale) \
|
||||
void CONCAT(printMatrixIndex, Scale)(MCInst * MI, unsigned OpNum, \
|
||||
SStream *O);
|
||||
DECLARE_printMatrixIndex(8);
|
||||
DECLARE_printMatrixIndex(0);
|
||||
DECLARE_printMatrixIndex(1);
|
||||
|
||||
// end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64INSTPRINTER_H
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
|
||||
#ifndef CS_AARCH64_LINKAGE_H
|
||||
#define CS_AARCH64_LINKAGE_H
|
||||
|
||||
// Function definitions to call static LLVM functions.
|
||||
|
||||
#include "../../MCDisassembler.h"
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../SStream.h"
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
DecodeStatus AArch64_LLVM_getInstruction(csh handle, const uint8_t *Bytes,
|
||||
size_t ByteLen, MCInst *MI,
|
||||
uint16_t *Size, uint64_t Address,
|
||||
void *Info);
|
||||
const char *AArch64_LLVM_getRegisterName(unsigned RegNo, unsigned AltIdx);
|
||||
void AArch64_LLVM_printInstruction(MCInst *MI, SStream *O,
|
||||
void * /* MCRegisterInfo* */ info);
|
||||
|
||||
#endif // CS_AARCH64_LINKAGE_H
|
||||
+2909
File diff suppressed because it is too large
Load Diff
+92
@@ -0,0 +1,92 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
||||
|
||||
#ifndef CS_AARCH64_MAP_H
|
||||
#define CS_AARCH64_MAP_H
|
||||
|
||||
#include "capstone/capstone.h"
|
||||
#include "../../MCInst.h"
|
||||
#include "../../SStream.h"
|
||||
|
||||
typedef enum {
|
||||
#include "AArch64GenCSOpGroup.inc"
|
||||
} aarch64_op_group;
|
||||
|
||||
/// Components of an SME matrix.
|
||||
/// Used when an sme operand is set to signal which part should be set.
|
||||
typedef enum {
|
||||
AARCH64_SME_MATRIX_TILE,
|
||||
AARCH64_SME_MATRIX_TILE_LIST,
|
||||
AARCH64_SME_MATRIX_SLICE_REG,
|
||||
AARCH64_SME_MATRIX_SLICE_OFF,
|
||||
AARCH64_SME_MATRIX_SLICE_OFF_RANGE,
|
||||
} aarch64_sme_op_part;
|
||||
|
||||
// return name of register in friendly string
|
||||
const char *AArch64_reg_name(csh handle, unsigned int reg);
|
||||
|
||||
// given internal insn id, return public instruction info
|
||||
void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
|
||||
const char *AArch64_insn_name(csh handle, unsigned int id);
|
||||
|
||||
const char *AArch64_group_name(csh handle, unsigned int id);
|
||||
|
||||
void AArch64_reg_access(const cs_insn *insn, cs_regs regs_read,
|
||||
uint8_t *regs_read_count, cs_regs regs_write,
|
||||
uint8_t *regs_write_count);
|
||||
|
||||
void AArch64_add_cs_detail_0(MCInst *MI, aarch64_op_group op_group,
|
||||
unsigned OpNum);
|
||||
void AArch64_add_cs_detail_1(MCInst *MI, aarch64_op_group op_group,
|
||||
unsigned OpNum, uint64_t temp_arg_0);
|
||||
void AArch64_add_cs_detail_2(MCInst *MI, aarch64_op_group op_group,
|
||||
unsigned OpNum, uint64_t temp_arg_0,
|
||||
uint64_t temp_arg_1);
|
||||
void AArch64_add_cs_detail_4(MCInst *MI, aarch64_op_group op_group,
|
||||
unsigned OpNum, uint64_t temp_arg_0,
|
||||
uint64_t temp_arg_1, uint64_t temp_arg_2,
|
||||
uint64_t temp_arg_3);
|
||||
|
||||
void AArch64_init_mri(MCRegisterInfo *MRI);
|
||||
|
||||
void AArch64_init_cs_detail(MCInst *MI);
|
||||
|
||||
void AArch64_set_instr_map_data(MCInst *MI);
|
||||
|
||||
bool AArch64_getInstruction(csh handle, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address,
|
||||
void *info);
|
||||
|
||||
void AArch64_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info);
|
||||
|
||||
void AArch64_set_detail_op_reg(MCInst *MI, unsigned OpNum, aarch64_reg Reg);
|
||||
void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,
|
||||
aarch64_op_type ImmType, int64_t Imm);
|
||||
void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,
|
||||
uint32_t FirstImm, uint32_t offset);
|
||||
void AArch64_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val);
|
||||
void AArch64_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val);
|
||||
void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,
|
||||
bool DoShift, unsigned ExtWidth,
|
||||
char SrcRegKind);
|
||||
void AArch64_set_detail_op_float(MCInst *MI, unsigned OpNum, float Val);
|
||||
void AArch64_set_detail_op_sys(MCInst *MI, unsigned OpNum, aarch64_sysop sys_op,
|
||||
aarch64_op_type type);
|
||||
void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,
|
||||
aarch64_sme_op_part part,
|
||||
AArch64Layout_VectorLayout vas, uint64_t arg_0,
|
||||
uint64_t arg_1);
|
||||
void AArch64_set_detail_op_pred(MCInst *MI, unsigned OpNum);
|
||||
void AArch64_insert_detail_op_reg_at(MCInst *MI, unsigned index,
|
||||
aarch64_reg Reg, cs_ac_type access);
|
||||
void AArch64_insert_detail_op_float_at(MCInst *MI, unsigned index, double val,
|
||||
cs_ac_type access);
|
||||
void AArch64_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Imm);
|
||||
void AArch64_insert_detail_op_sys(MCInst *MI, unsigned index,
|
||||
aarch64_sysop sys_op, aarch64_op_type type);
|
||||
void AArch64_insert_detail_op_sme(MCInst *MI, unsigned index,
|
||||
aarch64_op_sme sme_op);
|
||||
void AArch64_add_vas(MCInst *MI, const SStream *OS);
|
||||
|
||||
#endif
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dang Hoang Vu <danghvu@gmail.com> 2013 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_AARCH64
|
||||
|
||||
#include "../../utils.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "AArch64InstPrinter.h"
|
||||
#include "AArch64Mapping.h"
|
||||
#include "AArch64Module.h"
|
||||
|
||||
cs_err AArch64_global_init(cs_struct *ud)
|
||||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
AArch64_init_mri(mri);
|
||||
ud->printer = AArch64_printer;
|
||||
ud->printer_info = mri;
|
||||
ud->getinsn_info = mri;
|
||||
ud->disasm = AArch64_getInstruction;
|
||||
ud->reg_name = AArch64_reg_name;
|
||||
ud->insn_id = AArch64_get_insn_id;
|
||||
ud->insn_name = AArch64_insn_name;
|
||||
ud->group_name = AArch64_group_name;
|
||||
ud->post_printer = NULL;
|
||||
#ifndef CAPSTONE_DIET
|
||||
ud->reg_access = AArch64_reg_access;
|
||||
#endif
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
cs_err AArch64_option(cs_struct *handle, cs_opt_type type, size_t value)
|
||||
{
|
||||
if (type == CS_OPT_SYNTAX)
|
||||
handle->syntax |= (int)value;
|
||||
|
||||
if (type == CS_OPT_MODE) {
|
||||
handle->mode |= (cs_mode)value;
|
||||
}
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
|
||||
|
||||
#ifndef CS_AARCH64_MODULE_H
|
||||
#define CS_AARCH64_MODULE_H
|
||||
|
||||
#include "../../utils.h"
|
||||
|
||||
cs_err AArch64_global_init(cs_struct *ud);
|
||||
cs_err AArch64_option(cs_struct *handle, cs_opt_type type, size_t value);
|
||||
|
||||
#endif
|
||||
+480
@@ -0,0 +1,480 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file is part of the ARC Disassembler.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "../../MCInst.h"
|
||||
#include "../../SStream.h"
|
||||
#include "../../MCDisassembler.h"
|
||||
#include "../../MCFixedLenDisassembler.h"
|
||||
#include "../../MathExtras.h"
|
||||
#include "../../utils.h"
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
#define DEBUG_TYPE "arc-disassembler"
|
||||
|
||||
/// A disassembler class for ARC.
|
||||
static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size,
|
||||
const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, SStream *CStream);
|
||||
|
||||
// end anonymous namespace
|
||||
|
||||
static bool readInstruction32(const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, uint64_t *Size, uint32_t *Insn)
|
||||
{
|
||||
*Size = 4;
|
||||
// Read 2 16-bit values, but swap hi/lo parts.
|
||||
*Insn = (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) |
|
||||
(Bytes[3] << 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readInstruction64(const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, uint64_t *Size, uint64_t *Insn)
|
||||
{
|
||||
*Size = 8;
|
||||
*Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
|
||||
((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
|
||||
((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
|
||||
((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readInstruction48(const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, uint64_t *Size, uint64_t *Insn)
|
||||
{
|
||||
*Size = 6;
|
||||
*Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
|
||||
((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
|
||||
((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readInstruction16(const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, uint64_t *Size, uint32_t *Insn)
|
||||
{
|
||||
*Size = 2;
|
||||
*Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DECLARE_DecodeSignedOperand(B) \
|
||||
static DecodeStatus CONCAT(DecodeSignedOperand, \
|
||||
B)(MCInst * Inst, unsigned InsnS, \
|
||||
uint64_t Address, const void *Decoder);
|
||||
DECLARE_DecodeSignedOperand(11);
|
||||
DECLARE_DecodeSignedOperand(9);
|
||||
DECLARE_DecodeSignedOperand(10);
|
||||
DECLARE_DecodeSignedOperand(12);
|
||||
|
||||
#define DECLARE_DecodeFromCyclicRange(B) \
|
||||
static DecodeStatus CONCAT(DecodeFromCyclicRange, \
|
||||
B)(MCInst * Inst, unsigned InsnS, \
|
||||
uint64_t Address, const void *Decoder);
|
||||
DECLARE_DecodeFromCyclicRange(3);
|
||||
|
||||
#define DECLARE_DecodeBranchTargetS(B) \
|
||||
static DecodeStatus CONCAT(DecodeBranchTargetS, \
|
||||
B)(MCInst * Inst, unsigned InsnS, \
|
||||
uint64_t Address, const void *Decoder);
|
||||
DECLARE_DecodeBranchTargetS(8);
|
||||
DECLARE_DecodeBranchTargetS(10);
|
||||
DECLARE_DecodeBranchTargetS(7);
|
||||
DECLARE_DecodeBranchTargetS(13);
|
||||
DECLARE_DecodeBranchTargetS(21);
|
||||
DECLARE_DecodeBranchTargetS(25);
|
||||
DECLARE_DecodeBranchTargetS(9);
|
||||
|
||||
static DecodeStatus DecodeMEMrs9(MCInst *, unsigned, uint64_t, const void *);
|
||||
|
||||
static DecodeStatus DecodeLdLImmInstruction(MCInst *, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static DecodeStatus DecodeStLImmInstruction(MCInst *, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static DecodeStatus DecodeLdRLImmInstruction(MCInst *, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static DecodeStatus DecodeSOPwithRS12(MCInst *, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static DecodeStatus DecodeSOPwithRU6(MCInst *, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static DecodeStatus DecodeCCRU6Instruction(MCInst *, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static DecodeStatus DecodeMoveHRegInstruction(MCInst *Inst, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "ARCGenRegisterInfo.inc"
|
||||
|
||||
static const uint16_t GPR32DecoderTable[] = {
|
||||
ARC_R0, ARC_R1, ARC_R2, ARC_R3, ARC_R4, ARC_R5, ARC_R6,
|
||||
ARC_R7, ARC_R8, ARC_R9, ARC_R10, ARC_R11, ARC_R12, ARC_R13,
|
||||
ARC_R14, ARC_R15, ARC_R16, ARC_R17, ARC_R18, ARC_R19, ARC_R20,
|
||||
ARC_R21, ARC_R22, ARC_R23, ARC_R24, ARC_R25, ARC_GP, ARC_FP,
|
||||
ARC_SP, ARC_ILINK, ARC_R30, ARC_BLINK
|
||||
};
|
||||
|
||||
static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
if (RegNo >= 32) {
|
||||
;
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
|
||||
unsigned Reg = GPR32DecoderTable[RegNo];
|
||||
MCOperand_CreateReg0(Inst, (Reg));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeGBR32ShortRegister(MCInst *Inst, unsigned RegNo,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
// Enumerates registers from ranges [r0-r3],[r12-r15].
|
||||
if (RegNo > 3)
|
||||
RegNo += 8; // 4 for r12, etc...
|
||||
|
||||
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
|
||||
}
|
||||
|
||||
#include "ARCGenDisassemblerTables.inc"
|
||||
|
||||
static unsigned decodeCField(unsigned Insn)
|
||||
{
|
||||
return fieldFromInstruction_4(Insn, 6, 6);
|
||||
}
|
||||
|
||||
static unsigned decodeBField(unsigned Insn)
|
||||
{
|
||||
return (fieldFromInstruction_4(Insn, 12, 3) << 3) |
|
||||
fieldFromInstruction_4(Insn, 24, 3);
|
||||
}
|
||||
|
||||
static unsigned decodeAField(unsigned Insn)
|
||||
{
|
||||
return fieldFromInstruction_4(Insn, 0, 6);
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeMEMrs9(MCInst *Inst, unsigned Insn, uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
// We have the 9-bit immediate in the low bits, 6-bit register in high bits.
|
||||
unsigned S9 = Insn & 0x1ff;
|
||||
unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
|
||||
if (DecodeGPR32RegisterClass(Inst, R, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
MCOperand_CreateImm0(Inst, (SignExtend32((S9), 9)));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static void DecodeSymbolicOperandOff(MCInst *Inst, uint64_t Address,
|
||||
uint64_t Offset, const void *Decoder)
|
||||
{
|
||||
uint64_t NextAddress = Address + Offset;
|
||||
|
||||
MCOperand_CreateImm0(Inst, (NextAddress));
|
||||
}
|
||||
|
||||
#define DEFINE_DecodeBranchTargetS(B) \
|
||||
static DecodeStatus CONCAT(DecodeBranchTargetS, \
|
||||
B)(MCInst * Inst, unsigned InsnS, \
|
||||
uint64_t Address, const void *Decoder) \
|
||||
{ \
|
||||
CS_ASSERT(B > 0 && "field is empty"); \
|
||||
DecodeSymbolicOperandOff(Inst, Address, \
|
||||
SignExtend32((InsnS), B), Decoder); \
|
||||
return MCDisassembler_Success; \
|
||||
}
|
||||
DEFINE_DecodeBranchTargetS(8);
|
||||
DEFINE_DecodeBranchTargetS(10);
|
||||
DEFINE_DecodeBranchTargetS(7);
|
||||
DEFINE_DecodeBranchTargetS(13);
|
||||
DEFINE_DecodeBranchTargetS(21);
|
||||
DEFINE_DecodeBranchTargetS(25);
|
||||
DEFINE_DecodeBranchTargetS(9);
|
||||
|
||||
#define DEFINE_DecodeSignedOperand(B) \
|
||||
static DecodeStatus CONCAT(DecodeSignedOperand, \
|
||||
B)(MCInst * Inst, unsigned InsnS, \
|
||||
uint64_t Address, const void *Decoder) \
|
||||
{ \
|
||||
CS_ASSERT(B > 0 && "field is empty"); \
|
||||
MCOperand_CreateImm0( \
|
||||
Inst, SignExtend32(maskTrailingOnes32(B) & InsnS, B)); \
|
||||
return MCDisassembler_Success; \
|
||||
}
|
||||
DEFINE_DecodeSignedOperand(11);
|
||||
DEFINE_DecodeSignedOperand(9);
|
||||
DEFINE_DecodeSignedOperand(10);
|
||||
DEFINE_DecodeSignedOperand(12);
|
||||
|
||||
#define DEFINE_DecodeFromCyclicRange(B) \
|
||||
static DecodeStatus CONCAT(DecodeFromCyclicRange, \
|
||||
B)(MCInst * Inst, unsigned InsnS, \
|
||||
uint64_t Address, const void *Decoder) \
|
||||
{ \
|
||||
CS_ASSERT(B > 0 && "field is empty"); \
|
||||
const unsigned max = (1u << B) - 1; \
|
||||
MCOperand_CreateImm0(Inst, (InsnS < max ? (int)(InsnS) : -1)); \
|
||||
return MCDisassembler_Success; \
|
||||
}
|
||||
DEFINE_DecodeFromCyclicRange(3);
|
||||
|
||||
static DecodeStatus DecodeStLImmInstruction(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
unsigned SrcC, DstB, LImm;
|
||||
DstB = decodeBField(Insn);
|
||||
if (DstB != 62) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
SrcC = decodeCField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
LImm = (Insn >> 32);
|
||||
MCOperand_CreateImm0(Inst, (LImm));
|
||||
MCOperand_CreateImm0(Inst, (0));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeLdLImmInstruction(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
unsigned DstA, SrcB, LImm;
|
||||
;
|
||||
SrcB = decodeBField(Insn);
|
||||
if (SrcB != 62) {
|
||||
;
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
DstA = decodeAField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
LImm = (Insn >> 32);
|
||||
MCOperand_CreateImm0(Inst, (LImm));
|
||||
MCOperand_CreateImm0(Inst, (0));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeLdRLImmInstruction(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
unsigned DstA, SrcB;
|
||||
;
|
||||
DstA = decodeAField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
SrcB = decodeBField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
if (decodeCField(Insn) != 62) {
|
||||
;
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
MCOperand_CreateImm0(Inst, ((uint32_t)(Insn >> 32)));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeRegisterOrImm(MCInst *Inst, uint64_t Address,
|
||||
const void *Decoder, uint64_t RegNum,
|
||||
uint64_t Value)
|
||||
{
|
||||
if (30 == RegNum) {
|
||||
MCOperand_CreateImm0(Inst, (Value));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeMoveHRegInstruction(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
;
|
||||
|
||||
uint64_t H = fieldFromInstruction_8(Insn, 5, 3) |
|
||||
(fieldFromInstruction_8(Insn, 0, 2) << 3);
|
||||
uint64_t G = fieldFromInstruction_8(Insn, 8, 3) |
|
||||
(fieldFromInstruction_8(Insn, 3, 2) << 3);
|
||||
|
||||
if (MCDisassembler_Success !=
|
||||
DecodeRegisterOrImm(Inst, Address, Decoder, G, 0))
|
||||
return MCDisassembler_Fail;
|
||||
|
||||
return DecodeRegisterOrImm(Inst, Address, Decoder, H, Insn >> 16u);
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeCCRU6Instruction(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder)
|
||||
{
|
||||
unsigned DstB;
|
||||
;
|
||||
DstB = decodeBField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
|
||||
uint64_t U6Field = fieldFromInstruction_8(Insn, 6, 6);
|
||||
MCOperand_CreateImm0(Inst, (U6Field));
|
||||
uint64_t CCField = fieldFromInstruction_8(Insn, 0, 4);
|
||||
MCOperand_CreateImm0(Inst, (CCField));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeSOPwithRU6(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address, const void *Decoder)
|
||||
{
|
||||
unsigned DstB = decodeBField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
|
||||
uint64_t U6 = fieldFromInstruction_8(Insn, 6, 6);
|
||||
MCOperand_CreateImm0(Inst, (U6));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeSOPwithRS12(MCInst *Inst, uint64_t Insn,
|
||||
uint64_t Address, const void *Decoder)
|
||||
{
|
||||
unsigned DstB = decodeBField(Insn);
|
||||
if (DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder) ==
|
||||
MCDisassembler_Fail) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
|
||||
uint64_t Lower = fieldFromInstruction_8(Insn, 6, 6);
|
||||
uint64_t Upper = fieldFromInstruction_8(Insn, 0, 5);
|
||||
uint64_t Sign = fieldFromInstruction_8(Insn, 5, 1) ? -1 : 1;
|
||||
uint64_t Result = Sign * ((Upper << 6) + Lower);
|
||||
MCOperand_CreateImm0(Inst, (Result));
|
||||
return MCDisassembler_Success;
|
||||
}
|
||||
|
||||
static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size,
|
||||
const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, SStream *cStream)
|
||||
{
|
||||
DecodeStatus Result;
|
||||
if (BytesLen < 2) {
|
||||
*Size = 0;
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
|
||||
// 0x00 -> 0x07 are 32-bit instructions.
|
||||
// 0x08 -> 0x1F are 16-bit instructions.
|
||||
if (DecodeByte < 0x08) {
|
||||
// 32-bit instruction.
|
||||
if (BytesLen < 4) {
|
||||
// Did we decode garbage?
|
||||
*Size = 0;
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
if (BytesLen >= 8) {
|
||||
// Attempt to decode 64-bit instruction.
|
||||
uint64_t Insn64;
|
||||
if (!readInstruction64(Bytes, BytesLen, Address, Size,
|
||||
&Insn64))
|
||||
return MCDisassembler_Fail;
|
||||
Result = decodeInstruction_8(DecoderTable64, Instr,
|
||||
Insn64, Address, NULL);
|
||||
if (MCDisassembler_Success == Result) {
|
||||
;
|
||||
return Result;
|
||||
};
|
||||
}
|
||||
uint32_t Insn32;
|
||||
if (!readInstruction32(Bytes, BytesLen, Address, Size,
|
||||
&Insn32)) {
|
||||
return MCDisassembler_Fail;
|
||||
}
|
||||
// Calling the auto-generated decoder function.
|
||||
return decodeInstruction_4(DecoderTable32, Instr, Insn32,
|
||||
Address, NULL);
|
||||
} else {
|
||||
if (BytesLen >= 6) {
|
||||
// Attempt to treat as instr. with limm data.
|
||||
uint64_t Insn48;
|
||||
if (!readInstruction48(Bytes, BytesLen, Address, Size,
|
||||
&Insn48))
|
||||
return MCDisassembler_Fail;
|
||||
Result = decodeInstruction_8(DecoderTable48, Instr,
|
||||
Insn48, Address, NULL);
|
||||
if (MCDisassembler_Success == Result) {
|
||||
;
|
||||
return Result;
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t Insn16;
|
||||
if (!readInstruction16(Bytes, BytesLen, Address, Size, &Insn16))
|
||||
return MCDisassembler_Fail;
|
||||
|
||||
// Calling the auto-generated decoder function.
|
||||
return decodeInstruction_2(DecoderTable16, Instr, Insn16,
|
||||
Address, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
DecodeStatus ARC_LLVM_getInstruction(MCInst *MI, uint64_t *Size,
|
||||
const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, SStream *CS)
|
||||
{
|
||||
return getInstruction(MI, Size, Bytes, BytesLen, Address, CS);
|
||||
}
|
||||
|
||||
#endif
|
||||
+1324
File diff suppressed because it is too large
Load Diff
+204
@@ -0,0 +1,204 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
ARC_INS_INVALID,
|
||||
ARC_INS_h,
|
||||
ARC_INS_PBR,
|
||||
ARC_INS_ERROR_FLS,
|
||||
ARC_INS_ERROR_FFS,
|
||||
ARC_INS_PLDFI,
|
||||
ARC_INS_STB_FAR,
|
||||
ARC_INS_STH_FAR,
|
||||
ARC_INS_ST_FAR,
|
||||
ARC_INS_ADC,
|
||||
ARC_INS_ADC_F,
|
||||
ARC_INS_ADD_S,
|
||||
ARC_INS_ADD,
|
||||
ARC_INS_ADD_F,
|
||||
ARC_INS_AND,
|
||||
ARC_INS_AND_F,
|
||||
ARC_INS_ASL_S,
|
||||
ARC_INS_ASL,
|
||||
ARC_INS_ASL_F,
|
||||
ARC_INS_ASR_S,
|
||||
ARC_INS_ASR,
|
||||
ARC_INS_ASR_F,
|
||||
ARC_INS_BCLR_S,
|
||||
ARC_INS_BEQ_S,
|
||||
ARC_INS_BGE_S,
|
||||
ARC_INS_BGT_S,
|
||||
ARC_INS_BHI_S,
|
||||
ARC_INS_BHS_S,
|
||||
ARC_INS_BL,
|
||||
ARC_INS_BLE_S,
|
||||
ARC_INS_BLO_S,
|
||||
ARC_INS_BLS_S,
|
||||
ARC_INS_BLT_S,
|
||||
ARC_INS_BL_S,
|
||||
ARC_INS_BMSK_S,
|
||||
ARC_INS_BNE_S,
|
||||
ARC_INS_B,
|
||||
ARC_INS_BREQ_S,
|
||||
ARC_INS_BRNE_S,
|
||||
ARC_INS_BR,
|
||||
ARC_INS_BSET_S,
|
||||
ARC_INS_BTST_S,
|
||||
ARC_INS_B_S,
|
||||
ARC_INS_CMP_S,
|
||||
ARC_INS_CMP,
|
||||
ARC_INS_LD_S,
|
||||
ARC_INS_MOV_S,
|
||||
ARC_INS_EI_S,
|
||||
ARC_INS_ENTER_S,
|
||||
ARC_INS_FFS_F,
|
||||
ARC_INS_FFS,
|
||||
ARC_INS_FLS_F,
|
||||
ARC_INS_FLS,
|
||||
ARC_INS_ABS_S,
|
||||
ARC_INS_ADD1_S,
|
||||
ARC_INS_ADD2_S,
|
||||
ARC_INS_ADD3_S,
|
||||
ARC_INS_AND_S,
|
||||
ARC_INS_BIC_S,
|
||||
ARC_INS_BRK_S,
|
||||
ARC_INS_EXTB_S,
|
||||
ARC_INS_EXTH_S,
|
||||
ARC_INS_JEQ_S,
|
||||
ARC_INS_JL_S,
|
||||
ARC_INS_JL_S_D,
|
||||
ARC_INS_JNE_S,
|
||||
ARC_INS_J_S,
|
||||
ARC_INS_J_S_D,
|
||||
ARC_INS_LSR_S,
|
||||
ARC_INS_MPYUW_S,
|
||||
ARC_INS_MPYW_S,
|
||||
ARC_INS_MPY_S,
|
||||
ARC_INS_NEG_S,
|
||||
ARC_INS_NOP_S,
|
||||
ARC_INS_NOT_S,
|
||||
ARC_INS_OR_S,
|
||||
ARC_INS_SEXB_S,
|
||||
ARC_INS_SEXH_S,
|
||||
ARC_INS_SUB_S,
|
||||
ARC_INS_SUB_S_NE,
|
||||
ARC_INS_SWI_S,
|
||||
ARC_INS_TRAP_S,
|
||||
ARC_INS_TST_S,
|
||||
ARC_INS_UNIMP_S,
|
||||
ARC_INS_XOR_S,
|
||||
ARC_INS_LDB_S,
|
||||
ARC_INS_LDH_S,
|
||||
ARC_INS_J,
|
||||
ARC_INS_JL,
|
||||
ARC_INS_JLI_S,
|
||||
ARC_INS_LDB_AB,
|
||||
ARC_INS_LDB_AW,
|
||||
ARC_INS_LDB_DI_AB,
|
||||
ARC_INS_LDB_DI_AW,
|
||||
ARC_INS_LDB_DI,
|
||||
ARC_INS_LDB_X_AB,
|
||||
ARC_INS_LDB_X_AW,
|
||||
ARC_INS_LDB_X_DI_AB,
|
||||
ARC_INS_LDB_X_DI_AW,
|
||||
ARC_INS_LDB_X_DI,
|
||||
ARC_INS_LDB_X,
|
||||
ARC_INS_LDB,
|
||||
ARC_INS_LDH_AB,
|
||||
ARC_INS_LDH_AW,
|
||||
ARC_INS_LDH_DI_AB,
|
||||
ARC_INS_LDH_DI_AW,
|
||||
ARC_INS_LDH_DI,
|
||||
ARC_INS_LDH_S_X,
|
||||
ARC_INS_LDH_X_AB,
|
||||
ARC_INS_LDH_X_AW,
|
||||
ARC_INS_LDH_X_DI_AB,
|
||||
ARC_INS_LDH_X_DI_AW,
|
||||
ARC_INS_LDH_X_DI,
|
||||
ARC_INS_LDH_X,
|
||||
ARC_INS_LDH,
|
||||
ARC_INS_LDI_S,
|
||||
ARC_INS_LD_AB,
|
||||
ARC_INS_LD_AW,
|
||||
ARC_INS_LD_DI_AB,
|
||||
ARC_INS_LD_DI_AW,
|
||||
ARC_INS_LD_DI,
|
||||
ARC_INS_LD_S_AS,
|
||||
ARC_INS_LD,
|
||||
ARC_INS_LEAVE_S,
|
||||
ARC_INS_LR,
|
||||
ARC_INS_LSR,
|
||||
ARC_INS_LSR_F,
|
||||
ARC_INS_MAX,
|
||||
ARC_INS_MAX_F,
|
||||
ARC_INS_MIN,
|
||||
ARC_INS_MIN_F,
|
||||
ARC_INS_MOV_S_NE,
|
||||
ARC_INS_MOV,
|
||||
ARC_INS_MOV_F,
|
||||
ARC_INS_MPYMU,
|
||||
ARC_INS_MPYMU_F,
|
||||
ARC_INS_MPYM,
|
||||
ARC_INS_MPYM_F,
|
||||
ARC_INS_MPY,
|
||||
ARC_INS_MPY_F,
|
||||
ARC_INS_NORMH_F,
|
||||
ARC_INS_NORMH,
|
||||
ARC_INS_NORM_F,
|
||||
ARC_INS_NORM,
|
||||
ARC_INS_OR,
|
||||
ARC_INS_OR_F,
|
||||
ARC_INS_POP_S,
|
||||
ARC_INS_PUSH_S,
|
||||
ARC_INS_ROR,
|
||||
ARC_INS_ROR_F,
|
||||
ARC_INS_RSUB,
|
||||
ARC_INS_RSUB_F,
|
||||
ARC_INS_SBC,
|
||||
ARC_INS_SBC_F,
|
||||
ARC_INS_SETEQ,
|
||||
ARC_INS_SETEQ_F,
|
||||
ARC_INS_SEXB_F,
|
||||
ARC_INS_SEXB,
|
||||
ARC_INS_SEXH_F,
|
||||
ARC_INS_SEXH,
|
||||
ARC_INS_STB_S,
|
||||
ARC_INS_ST_S,
|
||||
ARC_INS_STB_AB,
|
||||
ARC_INS_STB_AW,
|
||||
ARC_INS_STB_DI_AB,
|
||||
ARC_INS_STB_DI_AW,
|
||||
ARC_INS_STB_DI,
|
||||
ARC_INS_STB,
|
||||
ARC_INS_STH_AB,
|
||||
ARC_INS_STH_AW,
|
||||
ARC_INS_STH_DI_AB,
|
||||
ARC_INS_STH_DI_AW,
|
||||
ARC_INS_STH_DI,
|
||||
ARC_INS_STH_S,
|
||||
ARC_INS_STH,
|
||||
ARC_INS_ST_AB,
|
||||
ARC_INS_ST_AW,
|
||||
ARC_INS_ST_DI_AB,
|
||||
ARC_INS_ST_DI_AW,
|
||||
ARC_INS_ST_DI,
|
||||
ARC_INS_ST,
|
||||
ARC_INS_SUB1,
|
||||
ARC_INS_SUB1_F,
|
||||
ARC_INS_SUB2,
|
||||
ARC_INS_SUB2_F,
|
||||
ARC_INS_SUB3,
|
||||
ARC_INS_SUB3_F,
|
||||
ARC_INS_SUB,
|
||||
ARC_INS_SUB_F,
|
||||
ARC_INS_XOR,
|
||||
ARC_INS_XOR_F,
|
||||
+5494
File diff suppressed because it is too large
Load Diff
+204
@@ -0,0 +1,204 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
"invalid", // ARC_INS_INVALID
|
||||
"h", // ARC_INS_h
|
||||
"pbr", // ARC_INS_PBR
|
||||
"error_fls", // ARC_INS_ERROR_FLS
|
||||
"error_ffs", // ARC_INS_ERROR_FFS
|
||||
"pldfi", // ARC_INS_PLDFI
|
||||
"STB_FAR", // ARC_INS_STB_FAR
|
||||
"STH_FAR", // ARC_INS_STH_FAR
|
||||
"ST_FAR", // ARC_INS_ST_FAR
|
||||
"adc", // ARC_INS_ADC
|
||||
"adc_f", // ARC_INS_ADC_F
|
||||
"add_s", // ARC_INS_ADD_S
|
||||
"add", // ARC_INS_ADD
|
||||
"add_f", // ARC_INS_ADD_F
|
||||
"and", // ARC_INS_AND
|
||||
"and_f", // ARC_INS_AND_F
|
||||
"asl_s", // ARC_INS_ASL_S
|
||||
"asl", // ARC_INS_ASL
|
||||
"asl_f", // ARC_INS_ASL_F
|
||||
"asr_s", // ARC_INS_ASR_S
|
||||
"asr", // ARC_INS_ASR
|
||||
"asr_f", // ARC_INS_ASR_F
|
||||
"bclr_s", // ARC_INS_BCLR_S
|
||||
"beq_s", // ARC_INS_BEQ_S
|
||||
"bge_s", // ARC_INS_BGE_S
|
||||
"bgt_s", // ARC_INS_BGT_S
|
||||
"bhi_s", // ARC_INS_BHI_S
|
||||
"bhs_s", // ARC_INS_BHS_S
|
||||
"bl", // ARC_INS_BL
|
||||
"ble_s", // ARC_INS_BLE_S
|
||||
"blo_s", // ARC_INS_BLO_S
|
||||
"bls_s", // ARC_INS_BLS_S
|
||||
"blt_s", // ARC_INS_BLT_S
|
||||
"bl_s", // ARC_INS_BL_S
|
||||
"bmsk_s", // ARC_INS_BMSK_S
|
||||
"bne_s", // ARC_INS_BNE_S
|
||||
"b", // ARC_INS_B
|
||||
"breq_s", // ARC_INS_BREQ_S
|
||||
"brne_s", // ARC_INS_BRNE_S
|
||||
"br", // ARC_INS_BR
|
||||
"bset_s", // ARC_INS_BSET_S
|
||||
"btst_s", // ARC_INS_BTST_S
|
||||
"b_s", // ARC_INS_B_S
|
||||
"cmp_s", // ARC_INS_CMP_S
|
||||
"cmp", // ARC_INS_CMP
|
||||
"ld_s", // ARC_INS_LD_S
|
||||
"mov_s", // ARC_INS_MOV_S
|
||||
"ei_s", // ARC_INS_EI_S
|
||||
"enter_s", // ARC_INS_ENTER_S
|
||||
"ffs_f", // ARC_INS_FFS_F
|
||||
"ffs", // ARC_INS_FFS
|
||||
"fls_f", // ARC_INS_FLS_F
|
||||
"fls", // ARC_INS_FLS
|
||||
"abs_s", // ARC_INS_ABS_S
|
||||
"add1_s", // ARC_INS_ADD1_S
|
||||
"add2_s", // ARC_INS_ADD2_S
|
||||
"add3_s", // ARC_INS_ADD3_S
|
||||
"and_s", // ARC_INS_AND_S
|
||||
"bic_s", // ARC_INS_BIC_S
|
||||
"brk_s", // ARC_INS_BRK_S
|
||||
"extb_s", // ARC_INS_EXTB_S
|
||||
"exth_s", // ARC_INS_EXTH_S
|
||||
"jeq_s", // ARC_INS_JEQ_S
|
||||
"jl_s", // ARC_INS_JL_S
|
||||
"jl_s_d", // ARC_INS_JL_S_D
|
||||
"jne_s", // ARC_INS_JNE_S
|
||||
"j_s", // ARC_INS_J_S
|
||||
"j_s_d", // ARC_INS_J_S_D
|
||||
"lsr_s", // ARC_INS_LSR_S
|
||||
"mpyuw_s", // ARC_INS_MPYUW_S
|
||||
"mpyw_s", // ARC_INS_MPYW_S
|
||||
"mpy_s", // ARC_INS_MPY_S
|
||||
"neg_s", // ARC_INS_NEG_S
|
||||
"nop_s", // ARC_INS_NOP_S
|
||||
"not_s", // ARC_INS_NOT_S
|
||||
"or_s", // ARC_INS_OR_S
|
||||
"sexb_s", // ARC_INS_SEXB_S
|
||||
"sexh_s", // ARC_INS_SEXH_S
|
||||
"sub_s", // ARC_INS_SUB_S
|
||||
"sub_s_ne", // ARC_INS_SUB_S_NE
|
||||
"swi_s", // ARC_INS_SWI_S
|
||||
"trap_s", // ARC_INS_TRAP_S
|
||||
"tst_s", // ARC_INS_TST_S
|
||||
"unimp_s", // ARC_INS_UNIMP_S
|
||||
"xor_s", // ARC_INS_XOR_S
|
||||
"ldb_s", // ARC_INS_LDB_S
|
||||
"ldh_s", // ARC_INS_LDH_S
|
||||
"j", // ARC_INS_J
|
||||
"jl", // ARC_INS_JL
|
||||
"jli_s", // ARC_INS_JLI_S
|
||||
"ldb_ab", // ARC_INS_LDB_AB
|
||||
"ldb_aw", // ARC_INS_LDB_AW
|
||||
"ldb_di_ab", // ARC_INS_LDB_DI_AB
|
||||
"ldb_di_aw", // ARC_INS_LDB_DI_AW
|
||||
"ldb_di", // ARC_INS_LDB_DI
|
||||
"ldb_x_ab", // ARC_INS_LDB_X_AB
|
||||
"ldb_x_aw", // ARC_INS_LDB_X_AW
|
||||
"ldb_x_di_ab", // ARC_INS_LDB_X_DI_AB
|
||||
"ldb_x_di_aw", // ARC_INS_LDB_X_DI_AW
|
||||
"ldb_x_di", // ARC_INS_LDB_X_DI
|
||||
"ldb_x", // ARC_INS_LDB_X
|
||||
"ldb", // ARC_INS_LDB
|
||||
"ldh_ab", // ARC_INS_LDH_AB
|
||||
"ldh_aw", // ARC_INS_LDH_AW
|
||||
"ldh_di_ab", // ARC_INS_LDH_DI_AB
|
||||
"ldh_di_aw", // ARC_INS_LDH_DI_AW
|
||||
"ldh_di", // ARC_INS_LDH_DI
|
||||
"ldh_s_x", // ARC_INS_LDH_S_X
|
||||
"ldh_x_ab", // ARC_INS_LDH_X_AB
|
||||
"ldh_x_aw", // ARC_INS_LDH_X_AW
|
||||
"ldh_x_di_ab", // ARC_INS_LDH_X_DI_AB
|
||||
"ldh_x_di_aw", // ARC_INS_LDH_X_DI_AW
|
||||
"ldh_x_di", // ARC_INS_LDH_X_DI
|
||||
"ldh_x", // ARC_INS_LDH_X
|
||||
"ldh", // ARC_INS_LDH
|
||||
"ldi_s", // ARC_INS_LDI_S
|
||||
"ld_ab", // ARC_INS_LD_AB
|
||||
"ld_aw", // ARC_INS_LD_AW
|
||||
"ld_di_ab", // ARC_INS_LD_DI_AB
|
||||
"ld_di_aw", // ARC_INS_LD_DI_AW
|
||||
"ld_di", // ARC_INS_LD_DI
|
||||
"ld_s_as", // ARC_INS_LD_S_AS
|
||||
"ld", // ARC_INS_LD
|
||||
"leave_s", // ARC_INS_LEAVE_S
|
||||
"lr", // ARC_INS_LR
|
||||
"lsr", // ARC_INS_LSR
|
||||
"lsr_f", // ARC_INS_LSR_F
|
||||
"max", // ARC_INS_MAX
|
||||
"max_f", // ARC_INS_MAX_F
|
||||
"min", // ARC_INS_MIN
|
||||
"min_f", // ARC_INS_MIN_F
|
||||
"mov_s_ne", // ARC_INS_MOV_S_NE
|
||||
"mov", // ARC_INS_MOV
|
||||
"mov_f", // ARC_INS_MOV_F
|
||||
"mpymu", // ARC_INS_MPYMU
|
||||
"mpymu_f", // ARC_INS_MPYMU_F
|
||||
"mpym", // ARC_INS_MPYM
|
||||
"mpym_f", // ARC_INS_MPYM_F
|
||||
"mpy", // ARC_INS_MPY
|
||||
"mpy_f", // ARC_INS_MPY_F
|
||||
"normh_f", // ARC_INS_NORMH_F
|
||||
"normh", // ARC_INS_NORMH
|
||||
"norm_f", // ARC_INS_NORM_F
|
||||
"norm", // ARC_INS_NORM
|
||||
"or", // ARC_INS_OR
|
||||
"or_f", // ARC_INS_OR_F
|
||||
"pop_s", // ARC_INS_POP_S
|
||||
"push_s", // ARC_INS_PUSH_S
|
||||
"ror", // ARC_INS_ROR
|
||||
"ror_f", // ARC_INS_ROR_F
|
||||
"rsub", // ARC_INS_RSUB
|
||||
"rsub_f", // ARC_INS_RSUB_F
|
||||
"sbc", // ARC_INS_SBC
|
||||
"sbc_f", // ARC_INS_SBC_F
|
||||
"seteq", // ARC_INS_SETEQ
|
||||
"seteq_f", // ARC_INS_SETEQ_F
|
||||
"sexb_f", // ARC_INS_SEXB_F
|
||||
"sexb", // ARC_INS_SEXB
|
||||
"sexh_f", // ARC_INS_SEXH_F
|
||||
"sexh", // ARC_INS_SEXH
|
||||
"stb_s", // ARC_INS_STB_S
|
||||
"st_s", // ARC_INS_ST_S
|
||||
"stb_ab", // ARC_INS_STB_AB
|
||||
"stb_aw", // ARC_INS_STB_AW
|
||||
"stb_di_ab", // ARC_INS_STB_DI_AB
|
||||
"stb_di_aw", // ARC_INS_STB_DI_AW
|
||||
"stb_di", // ARC_INS_STB_DI
|
||||
"stb", // ARC_INS_STB
|
||||
"sth_ab", // ARC_INS_STH_AB
|
||||
"sth_aw", // ARC_INS_STH_AW
|
||||
"sth_di_ab", // ARC_INS_STH_DI_AB
|
||||
"sth_di_aw", // ARC_INS_STH_DI_AW
|
||||
"sth_di", // ARC_INS_STH_DI
|
||||
"sth_s", // ARC_INS_STH_S
|
||||
"sth", // ARC_INS_STH
|
||||
"st_ab", // ARC_INS_ST_AB
|
||||
"st_aw", // ARC_INS_ST_AW
|
||||
"st_di_ab", // ARC_INS_ST_DI_AB
|
||||
"st_di_aw", // ARC_INS_ST_DI_AW
|
||||
"st_di", // ARC_INS_ST_DI
|
||||
"st", // ARC_INS_ST
|
||||
"sub1", // ARC_INS_SUB1
|
||||
"sub1_f", // ARC_INS_SUB1_F
|
||||
"sub2", // ARC_INS_SUB2
|
||||
"sub2_f", // ARC_INS_SUB2_F
|
||||
"sub3", // ARC_INS_SUB3
|
||||
"sub3_f", // ARC_INS_SUB3_F
|
||||
"sub", // ARC_INS_SUB
|
||||
"sub_f", // ARC_INS_SUB_F
|
||||
"xor", // ARC_INS_XOR
|
||||
"xor_f", // ARC_INS_XOR_F
|
||||
+3850
File diff suppressed because it is too large
Load Diff
+19
@@ -0,0 +1,19 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
ARC_OP_GROUP_Operand = 0,
|
||||
ARC_OP_GROUP_PredicateOperand = 1,
|
||||
ARC_OP_GROUP_MemOperandRI = 2,
|
||||
ARC_OP_GROUP_BRCCPredicateOperand = 3,
|
||||
ARC_OP_GROUP_CCOperand = 4,
|
||||
ARC_OP_GROUP_U6 = 5,
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
ARC_REG_INVALID = 0,
|
||||
ARC_REG_BLINK = 1,
|
||||
ARC_REG_FP = 2,
|
||||
ARC_REG_GP = 3,
|
||||
ARC_REG_ILINK = 4,
|
||||
ARC_REG_SP = 5,
|
||||
ARC_REG_R0 = 6,
|
||||
ARC_REG_R1 = 7,
|
||||
ARC_REG_R2 = 8,
|
||||
ARC_REG_R3 = 9,
|
||||
ARC_REG_R4 = 10,
|
||||
ARC_REG_R5 = 11,
|
||||
ARC_REG_R6 = 12,
|
||||
ARC_REG_R7 = 13,
|
||||
ARC_REG_R8 = 14,
|
||||
ARC_REG_R9 = 15,
|
||||
ARC_REG_R10 = 16,
|
||||
ARC_REG_R11 = 17,
|
||||
ARC_REG_R12 = 18,
|
||||
ARC_REG_R13 = 19,
|
||||
ARC_REG_R14 = 20,
|
||||
ARC_REG_R15 = 21,
|
||||
ARC_REG_R16 = 22,
|
||||
ARC_REG_R17 = 23,
|
||||
ARC_REG_R18 = 24,
|
||||
ARC_REG_R19 = 25,
|
||||
ARC_REG_R20 = 26,
|
||||
ARC_REG_R21 = 27,
|
||||
ARC_REG_R22 = 28,
|
||||
ARC_REG_R23 = 29,
|
||||
ARC_REG_R24 = 30,
|
||||
ARC_REG_R25 = 31,
|
||||
ARC_REG_R30 = 32,
|
||||
ARC_REG_R32 = 33,
|
||||
ARC_REG_R33 = 34,
|
||||
ARC_REG_R34 = 35,
|
||||
ARC_REG_R35 = 36,
|
||||
ARC_REG_R36 = 37,
|
||||
ARC_REG_R37 = 38,
|
||||
ARC_REG_R38 = 39,
|
||||
ARC_REG_R39 = 40,
|
||||
ARC_REG_R40 = 41,
|
||||
ARC_REG_R41 = 42,
|
||||
ARC_REG_R42 = 43,
|
||||
ARC_REG_R43 = 44,
|
||||
ARC_REG_R44 = 45,
|
||||
ARC_REG_R45 = 46,
|
||||
ARC_REG_R46 = 47,
|
||||
ARC_REG_R47 = 48,
|
||||
ARC_REG_R48 = 49,
|
||||
ARC_REG_R49 = 50,
|
||||
ARC_REG_R50 = 51,
|
||||
ARC_REG_R51 = 52,
|
||||
ARC_REG_R52 = 53,
|
||||
ARC_REG_R53 = 54,
|
||||
ARC_REG_R54 = 55,
|
||||
ARC_REG_R55 = 56,
|
||||
ARC_REG_R56 = 57,
|
||||
ARC_REG_R57 = 58,
|
||||
ARC_REG_R58 = 59,
|
||||
ARC_REG_R59 = 60,
|
||||
ARC_REG_R60 = 61,
|
||||
ARC_REG_R61 = 62,
|
||||
ARC_REG_R62 = 63,
|
||||
ARC_REG_R63 = 64,
|
||||
ARC_REG_STATUS32 = 65,
|
||||
ARC_REG_ENDING, // 66
|
||||
+1803
File diff suppressed because it is too large
Load Diff
+1616
File diff suppressed because it is too large
Load Diff
+296
@@ -0,0 +1,296 @@
|
||||
#ifdef GET_REGINFO_ENUM
|
||||
#undef GET_REGINFO_ENUM
|
||||
|
||||
enum {
|
||||
ARC_NoRegister,
|
||||
ARC_BLINK = 1,
|
||||
ARC_FP = 2,
|
||||
ARC_GP = 3,
|
||||
ARC_ILINK = 4,
|
||||
ARC_SP = 5,
|
||||
ARC_R0 = 6,
|
||||
ARC_R1 = 7,
|
||||
ARC_R2 = 8,
|
||||
ARC_R3 = 9,
|
||||
ARC_R4 = 10,
|
||||
ARC_R5 = 11,
|
||||
ARC_R6 = 12,
|
||||
ARC_R7 = 13,
|
||||
ARC_R8 = 14,
|
||||
ARC_R9 = 15,
|
||||
ARC_R10 = 16,
|
||||
ARC_R11 = 17,
|
||||
ARC_R12 = 18,
|
||||
ARC_R13 = 19,
|
||||
ARC_R14 = 20,
|
||||
ARC_R15 = 21,
|
||||
ARC_R16 = 22,
|
||||
ARC_R17 = 23,
|
||||
ARC_R18 = 24,
|
||||
ARC_R19 = 25,
|
||||
ARC_R20 = 26,
|
||||
ARC_R21 = 27,
|
||||
ARC_R22 = 28,
|
||||
ARC_R23 = 29,
|
||||
ARC_R24 = 30,
|
||||
ARC_R25 = 31,
|
||||
ARC_R30 = 32,
|
||||
ARC_R32 = 33,
|
||||
ARC_R33 = 34,
|
||||
ARC_R34 = 35,
|
||||
ARC_R35 = 36,
|
||||
ARC_R36 = 37,
|
||||
ARC_R37 = 38,
|
||||
ARC_R38 = 39,
|
||||
ARC_R39 = 40,
|
||||
ARC_R40 = 41,
|
||||
ARC_R41 = 42,
|
||||
ARC_R42 = 43,
|
||||
ARC_R43 = 44,
|
||||
ARC_R44 = 45,
|
||||
ARC_R45 = 46,
|
||||
ARC_R46 = 47,
|
||||
ARC_R47 = 48,
|
||||
ARC_R48 = 49,
|
||||
ARC_R49 = 50,
|
||||
ARC_R50 = 51,
|
||||
ARC_R51 = 52,
|
||||
ARC_R52 = 53,
|
||||
ARC_R53 = 54,
|
||||
ARC_R54 = 55,
|
||||
ARC_R55 = 56,
|
||||
ARC_R56 = 57,
|
||||
ARC_R57 = 58,
|
||||
ARC_R58 = 59,
|
||||
ARC_R59 = 60,
|
||||
ARC_R60 = 61,
|
||||
ARC_R61 = 62,
|
||||
ARC_R62 = 63,
|
||||
ARC_R63 = 64,
|
||||
ARC_STATUS32 = 65,
|
||||
NUM_TARGET_REGS // 66
|
||||
};
|
||||
|
||||
// Register classes
|
||||
|
||||
enum {
|
||||
ARC_SREGRegClassID = 0,
|
||||
ARC_GPR_SRegClassID = 1,
|
||||
ARC_GPR32RegClassID = 2,
|
||||
ARC_GPR32_and_GPR_SRegClassID = 3,
|
||||
|
||||
};
|
||||
#endif // GET_REGINFO_ENUM
|
||||
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
#ifdef GET_REGINFO_MC_DESC
|
||||
#undef GET_REGINFO_MC_DESC
|
||||
|
||||
static const MCPhysReg ARCRegDiffLists[] = {
|
||||
/* 0 */ 0,
|
||||
};
|
||||
|
||||
static const uint16_t ARCSubRegIdxLists[] = {
|
||||
/* 0 */ 0,
|
||||
};
|
||||
|
||||
static const MCRegisterDesc ARCRegDesc[] = { // Descriptors
|
||||
{ 3, 0, 0, 0, 0, 0 },
|
||||
{ 235, 0, 0, 0, 0, 0 },
|
||||
{ 247, 0, 0, 0, 1, 0 },
|
||||
{ 250, 0, 0, 0, 2, 0 },
|
||||
{ 241, 0, 0, 0, 3, 0 },
|
||||
{ 253, 0, 0, 0, 4, 0 },
|
||||
{ 24, 0, 0, 0, 5, 0 },
|
||||
{ 47, 0, 0, 0, 6, 0 },
|
||||
{ 83, 0, 0, 0, 7, 0 },
|
||||
{ 110, 0, 0, 0, 8, 0 },
|
||||
{ 133, 0, 0, 0, 9, 0 },
|
||||
{ 156, 0, 0, 0, 10, 0 },
|
||||
{ 175, 0, 0, 0, 11, 0 },
|
||||
{ 194, 0, 0, 0, 12, 0 },
|
||||
{ 213, 0, 0, 0, 13, 0 },
|
||||
{ 232, 0, 0, 0, 14, 0 },
|
||||
{ 0, 0, 0, 0, 15, 0 },
|
||||
{ 27, 0, 0, 0, 16, 0 },
|
||||
{ 50, 0, 0, 0, 17, 0 },
|
||||
{ 86, 0, 0, 0, 18, 0 },
|
||||
{ 113, 0, 0, 0, 19, 0 },
|
||||
{ 136, 0, 0, 0, 20, 0 },
|
||||
{ 159, 0, 0, 0, 21, 0 },
|
||||
{ 178, 0, 0, 0, 22, 0 },
|
||||
{ 197, 0, 0, 0, 23, 0 },
|
||||
{ 216, 0, 0, 0, 24, 0 },
|
||||
{ 4, 0, 0, 0, 25, 0 },
|
||||
{ 31, 0, 0, 0, 26, 0 },
|
||||
{ 54, 0, 0, 0, 27, 0 },
|
||||
{ 90, 0, 0, 0, 28, 0 },
|
||||
{ 117, 0, 0, 0, 29, 0 },
|
||||
{ 140, 0, 0, 0, 30, 0 },
|
||||
{ 8, 0, 0, 0, 31, 0 },
|
||||
{ 58, 0, 0, 0, 32, 0 },
|
||||
{ 94, 0, 0, 0, 33, 0 },
|
||||
{ 121, 0, 0, 0, 34, 0 },
|
||||
{ 144, 0, 0, 0, 35, 0 },
|
||||
{ 163, 0, 0, 0, 36, 0 },
|
||||
{ 182, 0, 0, 0, 37, 0 },
|
||||
{ 201, 0, 0, 0, 38, 0 },
|
||||
{ 220, 0, 0, 0, 39, 0 },
|
||||
{ 12, 0, 0, 0, 40, 0 },
|
||||
{ 35, 0, 0, 0, 41, 0 },
|
||||
{ 71, 0, 0, 0, 42, 0 },
|
||||
{ 98, 0, 0, 0, 43, 0 },
|
||||
{ 125, 0, 0, 0, 44, 0 },
|
||||
{ 148, 0, 0, 0, 45, 0 },
|
||||
{ 167, 0, 0, 0, 46, 0 },
|
||||
{ 186, 0, 0, 0, 47, 0 },
|
||||
{ 205, 0, 0, 0, 48, 0 },
|
||||
{ 224, 0, 0, 0, 49, 0 },
|
||||
{ 16, 0, 0, 0, 50, 0 },
|
||||
{ 39, 0, 0, 0, 51, 0 },
|
||||
{ 75, 0, 0, 0, 52, 0 },
|
||||
{ 102, 0, 0, 0, 53, 0 },
|
||||
{ 129, 0, 0, 0, 54, 0 },
|
||||
{ 152, 0, 0, 0, 55, 0 },
|
||||
{ 171, 0, 0, 0, 56, 0 },
|
||||
{ 190, 0, 0, 0, 57, 0 },
|
||||
{ 209, 0, 0, 0, 58, 0 },
|
||||
{ 228, 0, 0, 0, 59, 0 },
|
||||
{ 20, 0, 0, 0, 60, 0 },
|
||||
{ 43, 0, 0, 0, 61, 0 },
|
||||
{ 79, 0, 0, 0, 62, 0 },
|
||||
{ 106, 0, 0, 0, 63, 0 },
|
||||
{ 62, 0, 0, 0, 64, 0 },
|
||||
};
|
||||
|
||||
// SREG Register Class...
|
||||
static const MCPhysReg SREG[] = {
|
||||
ARC_STATUS32,
|
||||
};
|
||||
|
||||
// SREG Bit set.
|
||||
static const uint8_t SREGBits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
};
|
||||
|
||||
// GPR_S Register Class...
|
||||
static const MCPhysReg GPR_S[] = {
|
||||
ARC_R0, ARC_R1, ARC_R2, ARC_R3, ARC_R12, ARC_R13, ARC_R14, ARC_R15,
|
||||
};
|
||||
|
||||
// GPR_S Bit set.
|
||||
static const uint8_t GPR_SBits[] = {
|
||||
0xc0, 0x03, 0x3c,
|
||||
};
|
||||
|
||||
// GPR32 Register Class...
|
||||
static const MCPhysReg GPR32[] = {
|
||||
ARC_R0, ARC_R1, ARC_R2, ARC_R3, ARC_R4, ARC_R5, ARC_R6, ARC_R7, ARC_R8, ARC_R9, ARC_R10, ARC_R11, ARC_R12, ARC_R13, ARC_R14, ARC_R15, ARC_R16, ARC_R17, ARC_R18, ARC_R19, ARC_R20, ARC_R21, ARC_R22, ARC_R23, ARC_R24, ARC_R25, ARC_GP, ARC_FP, ARC_SP, ARC_ILINK, ARC_R30, ARC_BLINK, ARC_R32, ARC_R33, ARC_R34, ARC_R35, ARC_R36, ARC_R37, ARC_R38, ARC_R39, ARC_R40, ARC_R41, ARC_R42, ARC_R43, ARC_R44, ARC_R45, ARC_R46, ARC_R47, ARC_R48, ARC_R49, ARC_R50, ARC_R51, ARC_R52, ARC_R53, ARC_R54, ARC_R55, ARC_R56, ARC_R57, ARC_R58, ARC_R59, ARC_R60, ARC_R61, ARC_R62, ARC_R63,
|
||||
};
|
||||
|
||||
// GPR32 Bit set.
|
||||
static const uint8_t GPR32Bits[] = {
|
||||
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
|
||||
};
|
||||
|
||||
// GPR32_and_GPR_S Register Class...
|
||||
static const MCPhysReg GPR32_and_GPR_S[] = {
|
||||
ARC_R0, ARC_R1, ARC_R2, ARC_R3, ARC_R12, ARC_R13, ARC_R14, ARC_R15,
|
||||
};
|
||||
|
||||
// GPR32_and_GPR_S Bit set.
|
||||
static const uint8_t GPR32_and_GPR_SBits[] = {
|
||||
0xc0, 0x03, 0x3c,
|
||||
};
|
||||
|
||||
static const MCRegisterClass ARCMCRegisterClasses[] = {
|
||||
{ SREG, SREGBits, sizeof(SREGBits) },
|
||||
{ GPR_S, GPR_SBits, sizeof(GPR_SBits) },
|
||||
{ GPR32, GPR32Bits, sizeof(GPR32Bits) },
|
||||
{ GPR32_and_GPR_S, GPR32_and_GPR_SBits, sizeof(GPR32_and_GPR_SBits) },
|
||||
};
|
||||
|
||||
static const uint16_t ARCRegEncodingTable[] = {
|
||||
0,
|
||||
31,
|
||||
27,
|
||||
26,
|
||||
29,
|
||||
28,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
30,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
51,
|
||||
52,
|
||||
53,
|
||||
54,
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
59,
|
||||
60,
|
||||
61,
|
||||
62,
|
||||
63,
|
||||
10,
|
||||
};
|
||||
#endif // GET_REGINFO_MC_DESC
|
||||
|
||||
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/* Capstone Disassembly Engine, https://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2024 */
|
||||
/* Automatically generated file by Capstone's LLVM TableGen Disassembler Backend. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Do not edit. */
|
||||
|
||||
/* Capstone's LLVM TableGen Backends: */
|
||||
/* https://github.com/capstone-engine/llvm-capstone */
|
||||
|
||||
#ifdef GET_SUBTARGETINFO_ENUM
|
||||
#undef GET_SUBTARGETINFO_ENUM
|
||||
|
||||
enum {
|
||||
ARC_FeatureNORM = 0,
|
||||
ARC_NumSubtargetFeatures = 1
|
||||
};
|
||||
#endif // GET_SUBTARGETINFO_ENUM
|
||||
|
||||
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===- ARCInfo.h - Additional ARC Info --------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains small standalone helper functions and enum definitions for
|
||||
// the ARC target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCINFO_H
|
||||
#define LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCINFO_H
|
||||
|
||||
// Enums corresponding to ARC condition codes
|
||||
// CS namespace begin: ARCCC
|
||||
|
||||
typedef enum ARCCondCode {
|
||||
ARCCC_AL = 0x0,
|
||||
ARCCC_EQ = 0x1,
|
||||
ARCCC_NE = 0x2,
|
||||
ARCCC_P = 0x3,
|
||||
ARCCC_N = 0x4,
|
||||
ARCCC_LO = 0x5,
|
||||
ARCCC_HS = 0x6,
|
||||
ARCCC_VS = 0x7,
|
||||
ARCCC_VC = 0x8,
|
||||
ARCCC_GT = 0x9,
|
||||
ARCCC_GE = 0xa,
|
||||
ARCCC_LT = 0xb,
|
||||
ARCCC_LE = 0xc,
|
||||
ARCCC_HI = 0xd,
|
||||
ARCCC_LS = 0xe,
|
||||
ARCCC_PNZ = 0xf,
|
||||
ARCCC_Z = 0x11, // Low 4-bits = EQ
|
||||
ARCCC_NZ = 0x12 // Low 4-bits = NE
|
||||
} ARCCC_CondCode;
|
||||
|
||||
typedef enum BRCondCode {
|
||||
ARCCC_BREQ = 0x0,
|
||||
ARCCC_BRNE = 0x1,
|
||||
ARCCC_BRLT = 0x2,
|
||||
ARCCC_BRGE = 0x3,
|
||||
ARCCC_BRLO = 0x4,
|
||||
ARCCC_BRHS = 0x5
|
||||
} ARCCC_BRCondCode;
|
||||
|
||||
// CS namespace end: ARCCC
|
||||
|
||||
// end namespace ARCCC
|
||||
|
||||
// end namespace llvm
|
||||
|
||||
#endif
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===- ARCInstPrinter.cpp - ARC MCInst to assembly syntax -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an ARC MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "../../SStream.h"
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCInstPrinter.h"
|
||||
|
||||
#include "ARCInfo.h"
|
||||
#include "ARCInstPrinter.h"
|
||||
#include "ARCLinkage.h"
|
||||
#include "ARCMapping.h"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
|
||||
#include "ARCGenAsmWriter.inc"
|
||||
|
||||
static const char *ARCBRCondCodeToString(ARCCC_BRCondCode BRCC)
|
||||
{
|
||||
switch (BRCC) {
|
||||
case ARCCC_BREQ:
|
||||
return "eq";
|
||||
case ARCCC_BRNE:
|
||||
return "ne";
|
||||
case ARCCC_BRLT:
|
||||
return "lt";
|
||||
case ARCCC_BRGE:
|
||||
return "ge";
|
||||
case ARCCC_BRLO:
|
||||
return "lo";
|
||||
case ARCCC_BRHS:
|
||||
return "hs";
|
||||
}
|
||||
// CS_ASSERT(0 && "Unknown condition code passed");
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char *ARCCondCodeToString(ARCCC_CondCode CC)
|
||||
{
|
||||
switch (CC) {
|
||||
case ARCCC_EQ:
|
||||
return "eq";
|
||||
case ARCCC_NE:
|
||||
return "ne";
|
||||
case ARCCC_P:
|
||||
return "p";
|
||||
case ARCCC_N:
|
||||
return "n";
|
||||
case ARCCC_HS:
|
||||
return "hs";
|
||||
case ARCCC_LO:
|
||||
return "lo";
|
||||
case ARCCC_GT:
|
||||
return "gt";
|
||||
case ARCCC_GE:
|
||||
return "ge";
|
||||
case ARCCC_VS:
|
||||
return "vs";
|
||||
case ARCCC_VC:
|
||||
return "vc";
|
||||
case ARCCC_LT:
|
||||
return "lt";
|
||||
case ARCCC_LE:
|
||||
return "le";
|
||||
case ARCCC_HI:
|
||||
return "hi";
|
||||
case ARCCC_LS:
|
||||
return "ls";
|
||||
case ARCCC_PNZ:
|
||||
return "pnz";
|
||||
case ARCCC_AL:
|
||||
return "al";
|
||||
case ARCCC_NZ:
|
||||
return "nz";
|
||||
case ARCCC_Z:
|
||||
return "z";
|
||||
}
|
||||
// CS_ASSERT(0 && "Unknown condition code passed");
|
||||
return "";
|
||||
}
|
||||
|
||||
static void printRegName(SStream *OS, MCRegister Reg)
|
||||
{
|
||||
SStream_concat0(OS, getRegisterName(Reg));
|
||||
}
|
||||
|
||||
static void printInst(MCInst *MI, uint64_t Address, const char *Annot,
|
||||
SStream *O)
|
||||
{
|
||||
printInstruction(MI, Address, O);
|
||||
}
|
||||
|
||||
static void printOperand(MCInst *MI, unsigned OpNum, SStream *O)
|
||||
{
|
||||
ARC_add_cs_detail_0(MI, ARC_OP_GROUP_Operand, OpNum);
|
||||
MCOperand *Op = MCInst_getOperand(MI, (OpNum));
|
||||
if (MCOperand_isReg(Op)) {
|
||||
printRegName(O, MCOperand_getReg(Op));
|
||||
} else if (MCOperand_isImm(Op)) {
|
||||
SStream_concat(O, "%" PRId64, MCOperand_getImm(Op));
|
||||
} else if (MCOperand_isExpr(Op)) {
|
||||
printExpr(O, MCOperand_getExpr(Op));
|
||||
}
|
||||
}
|
||||
|
||||
static void printOperandAddr(MCInst *MI, uint64_t Address, unsigned OpNum,
|
||||
SStream *O)
|
||||
{
|
||||
printOperand(MI, OpNum, O);
|
||||
}
|
||||
|
||||
static void printMemOperandRI(MCInst *MI, unsigned OpNum, SStream *O)
|
||||
{
|
||||
ARC_add_cs_detail_0(MI, ARC_OP_GROUP_MemOperandRI, OpNum);
|
||||
MCOperand *base = MCInst_getOperand(MI, (OpNum));
|
||||
MCOperand *offset = MCInst_getOperand(MI, (OpNum + 1));
|
||||
CS_ASSERT((MCOperand_isReg(base) && "Base should be register."));
|
||||
CS_ASSERT((MCOperand_isImm(offset) && "Offset should be immediate."));
|
||||
printRegName(O, MCOperand_getReg(base));
|
||||
SStream_concat(O, "%s", ",");
|
||||
printInt64(O, MCOperand_getImm(offset));
|
||||
}
|
||||
|
||||
static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
|
||||
{
|
||||
ARC_add_cs_detail_0(MI, ARC_OP_GROUP_PredicateOperand, OpNum);
|
||||
|
||||
MCOperand *Op = MCInst_getOperand(MI, (OpNum));
|
||||
CS_ASSERT((MCOperand_isImm(Op) && "Predicate operand is immediate."));
|
||||
SStream_concat0(
|
||||
O, ARCCondCodeToString((ARCCC_CondCode)MCOperand_getImm(Op)));
|
||||
}
|
||||
|
||||
static void printBRCCPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
|
||||
{
|
||||
ARC_add_cs_detail_0(MI, ARC_OP_GROUP_BRCCPredicateOperand, OpNum);
|
||||
MCOperand *Op = MCInst_getOperand(MI, (OpNum));
|
||||
CS_ASSERT((MCOperand_isImm(Op) && "Predicate operand is immediate."));
|
||||
SStream_concat0(O, ARCBRCondCodeToString(
|
||||
(ARCCC_BRCondCode)MCOperand_getImm(Op)));
|
||||
}
|
||||
|
||||
static void printCCOperand(MCInst *MI, int OpNum, SStream *O)
|
||||
{
|
||||
ARC_add_cs_detail_0(MI, ARC_OP_GROUP_CCOperand, OpNum);
|
||||
SStream_concat0(O, ARCCondCodeToString((ARCCC_CondCode)MCOperand_getImm(
|
||||
MCInst_getOperand(MI, (OpNum)))));
|
||||
}
|
||||
|
||||
static void printU6ShiftedBy(unsigned ShiftBy, MCInst *MI, int OpNum,
|
||||
SStream *O)
|
||||
{
|
||||
MCOperand *MO = MCInst_getOperand(MI, (OpNum));
|
||||
if (MCOperand_isImm(MO)) {
|
||||
unsigned Value = MCOperand_getImm(MO);
|
||||
unsigned Value2 = Value >> ShiftBy;
|
||||
if (Value2 > 0x3F || (Value2 << ShiftBy != Value)) {
|
||||
CS_ASSERT((false && "instruction has wrong format"));
|
||||
}
|
||||
}
|
||||
printOperand(MI, OpNum, O);
|
||||
}
|
||||
|
||||
static void printU6(MCInst *MI, int OpNum, SStream *O)
|
||||
{
|
||||
ARC_add_cs_detail_0(MI, ARC_OP_GROUP_U6, OpNum);
|
||||
printU6ShiftedBy(0, MI, OpNum, O);
|
||||
}
|
||||
|
||||
void ARC_LLVM_printInst(MCInst *MI, uint64_t Address, const char *Annot,
|
||||
SStream *O)
|
||||
{
|
||||
printInst(MI, Address, Annot, O);
|
||||
}
|
||||
|
||||
const char *ARC_LLVM_getRegisterName(unsigned RegNo)
|
||||
{
|
||||
return getRegisterName(RegNo);
|
||||
}
|
||||
|
||||
#endif
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===- ARCInstPrinter.h - Convert ARC MCInst to assembly syntax -*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the declaration of the ARCInstPrinter class,
|
||||
/// which is used to print ARC MCInst to a .s file.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_ARC_INSTPRINTER_ARCINSTPRINTER_H
|
||||
#define LLVM_LIB_TARGET_ARC_INSTPRINTER_ARCINSTPRINTER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "../../SStream.h"
|
||||
#include "../../MCInst.h"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
// Autogenerated by tblgen.
|
||||
static void printInstruction(MCInst *MI, uint64_t Address, SStream *O);
|
||||
static void printRegName(SStream *OS, MCRegister Reg);
|
||||
static void printInst(MCInst *MI, uint64_t Address, const char *Annot,
|
||||
SStream *O);
|
||||
static void printCCOperand(MCInst *MI, int OpNum, SStream *O);
|
||||
static void printU6(MCInst *MI, int OpNum, SStream *O);
|
||||
static void printMemOperandRI(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
static void printOperand(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
static void printOperandAddr(MCInst *MI, uint64_t Address, unsigned OpNum,
|
||||
SStream *O);
|
||||
static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
static void printBRCCPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
|
||||
static void printU6ShiftedBy(unsigned ShiftBy, MCInst *MI, int OpNum,
|
||||
SStream *O);
|
||||
;
|
||||
// end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_ARC_INSTPRINTER_ARCINSTPRINTER_H
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dmitry Sibirtsev <sibirtsevdl@gmail.com>, 2024 */
|
||||
|
||||
#ifndef CS_ARC_LINKAGE_H
|
||||
#define CS_ARC_LINKAGE_H
|
||||
|
||||
// Function definitions to call static LLVM functions.
|
||||
|
||||
#include "../../MCDisassembler.h"
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../SStream.h"
|
||||
#include "capstone/capstone.h"
|
||||
|
||||
const char *ARC_LLVM_getRegisterName(unsigned RegNo);
|
||||
void ARC_LLVM_printInst(MCInst *MI, uint64_t Address, const char *Annot,
|
||||
SStream *O);
|
||||
DecodeStatus ARC_LLVM_getInstruction(MCInst *MI, uint64_t *Size,
|
||||
const uint8_t *Bytes, size_t BytesLen,
|
||||
uint64_t Address, SStream *CS);
|
||||
|
||||
#endif // CS_ARC_LINKAGE_H
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dmitry Sibirtsev <sibirtsevdl@gmail.com>, 2024 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/arc.h>
|
||||
|
||||
#include "../../Mapping.h"
|
||||
#include "../../MCDisassembler.h"
|
||||
#include "../../cs_priv.h"
|
||||
#include "../../cs_simple_types.h"
|
||||
|
||||
#include "ARCMapping.h"
|
||||
#include "ARCLinkage.h"
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "ARCGenRegisterInfo.inc"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "ARCGenInstrInfo.inc"
|
||||
|
||||
void ARC_init_mri(MCRegisterInfo *MRI)
|
||||
{
|
||||
MCRegisterInfo_InitMCRegisterInfo(MRI, ARCRegDesc, sizeof(ARCRegDesc),
|
||||
0, 0, ARCMCRegisterClasses,
|
||||
ARR_SIZE(ARCMCRegisterClasses), 0, 0,
|
||||
ARCRegDiffLists, 0, ARCSubRegIdxLists,
|
||||
ARR_SIZE(ARCSubRegIdxLists), 0);
|
||||
}
|
||||
|
||||
const char *ARC_reg_name(csh handle, unsigned int reg)
|
||||
{
|
||||
return ARC_LLVM_getRegisterName(reg);
|
||||
}
|
||||
|
||||
void ARC_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
// Not used by ARC. Information is set after disassembly.
|
||||
}
|
||||
|
||||
static const char *const insn_name_maps[] = {
|
||||
#include "ARCGenCSMappingInsnName.inc"
|
||||
};
|
||||
|
||||
const char *ARC_insn_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
if (id < ARR_SIZE(insn_name_maps))
|
||||
return insn_name_maps[id];
|
||||
// not found
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map group_name_maps[] = {
|
||||
{ ARC_GRP_INVALID, NULL },
|
||||
|
||||
{ ARC_GRP_JUMP, "jump" },
|
||||
{ ARC_GRP_CALL, "call" },
|
||||
{ ARC_GRP_RET, "return" },
|
||||
{ ARC_GRP_BRANCH_RELATIVE, "branch_relative" },
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *ARC_group_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ARC_reg_access(const cs_insn *insn, cs_regs regs_read,
|
||||
uint8_t *regs_read_count, cs_regs regs_write,
|
||||
uint8_t *regs_write_count)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t read_count, write_count;
|
||||
cs_arc *arc = &(insn->detail->arc);
|
||||
|
||||
read_count = insn->detail->regs_read_count;
|
||||
write_count = insn->detail->regs_write_count;
|
||||
|
||||
// implicit registers
|
||||
memcpy(regs_read, insn->detail->regs_read,
|
||||
read_count * sizeof(insn->detail->regs_read[0]));
|
||||
memcpy(regs_write, insn->detail->regs_write,
|
||||
write_count * sizeof(insn->detail->regs_write[0]));
|
||||
|
||||
// explicit registers
|
||||
for (i = 0; i < arc->op_count; i++) {
|
||||
cs_arc_op *op = &(arc->operands[i]);
|
||||
switch ((int)op->type) {
|
||||
case ARC_OP_REG:
|
||||
if ((op->access & CS_AC_READ) &&
|
||||
!arr_exist(regs_read, read_count, op->reg)) {
|
||||
regs_read[read_count] = (uint16_t)op->reg;
|
||||
read_count++;
|
||||
}
|
||||
if ((op->access & CS_AC_WRITE) &&
|
||||
!arr_exist(regs_write, write_count, op->reg)) {
|
||||
regs_write[write_count] = (uint16_t)op->reg;
|
||||
write_count++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*regs_read_count = read_count;
|
||||
*regs_write_count = write_count;
|
||||
}
|
||||
|
||||
const insn_map arc_insns[] = {
|
||||
#include "ARCGenCSMappingInsn.inc"
|
||||
};
|
||||
|
||||
void ARC_set_instr_map_data(MCInst *MI)
|
||||
{
|
||||
map_cs_id(MI, arc_insns, ARR_SIZE(arc_insns));
|
||||
map_implicit_reads(MI, arc_insns);
|
||||
map_implicit_writes(MI, arc_insns);
|
||||
map_groups(MI, arc_insns);
|
||||
}
|
||||
|
||||
bool ARC_getInstruction(csh handle, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address,
|
||||
void *info)
|
||||
{
|
||||
uint64_t temp_size;
|
||||
ARC_init_cs_detail(instr);
|
||||
DecodeStatus Result = ARC_LLVM_getInstruction(instr, &temp_size, code,
|
||||
code_len, address, info);
|
||||
ARC_set_instr_map_data(instr);
|
||||
*size = temp_size;
|
||||
if (Result == MCDisassembler_SoftFail) {
|
||||
MCInst_setSoftFail(instr);
|
||||
}
|
||||
return Result != MCDisassembler_Fail;
|
||||
}
|
||||
|
||||
void ARC_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
|
||||
{
|
||||
MCRegisterInfo *MRI = (MCRegisterInfo *)info;
|
||||
MI->MRI = MRI;
|
||||
|
||||
ARC_LLVM_printInst(MI, MI->address, "", O);
|
||||
}
|
||||
|
||||
void ARC_setup_op(cs_arc_op *op)
|
||||
{
|
||||
memset(op, 0, sizeof(cs_arc_op));
|
||||
op->type = ARC_OP_INVALID;
|
||||
}
|
||||
|
||||
void ARC_init_cs_detail(MCInst *MI)
|
||||
{
|
||||
if (!detail_is_set(MI)) {
|
||||
return;
|
||||
}
|
||||
unsigned int i;
|
||||
|
||||
memset(get_detail(MI), 0, offsetof(cs_detail, arc) + sizeof(cs_arc));
|
||||
|
||||
for (i = 0; i < ARR_SIZE(ARC_get_detail(MI)->operands); i++)
|
||||
ARC_setup_op(&ARC_get_detail(MI)->operands[i]);
|
||||
}
|
||||
|
||||
static const map_insn_ops insn_operands[] = {
|
||||
#include "ARCGenCSMappingInsnOp.inc"
|
||||
};
|
||||
|
||||
void ARC_set_detail_op_imm(MCInst *MI, unsigned OpNum, arc_op_type ImmType,
|
||||
int64_t Imm)
|
||||
{
|
||||
if (!detail_is_set(MI))
|
||||
return;
|
||||
ARC_check_safe_inc(MI);
|
||||
CS_ASSERT((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM);
|
||||
CS_ASSERT(ImmType == ARC_OP_IMM);
|
||||
|
||||
ARC_get_detail_op(MI, 0)->type = ImmType;
|
||||
ARC_get_detail_op(MI, 0)->imm = Imm;
|
||||
ARC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
|
||||
ARC_inc_op_count(MI);
|
||||
}
|
||||
|
||||
void ARC_set_detail_op_reg(MCInst *MI, unsigned OpNum, arc_reg Reg)
|
||||
{
|
||||
if (!detail_is_set(MI))
|
||||
return;
|
||||
ARC_check_safe_inc(MI);
|
||||
CS_ASSERT((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG);
|
||||
|
||||
ARC_get_detail_op(MI, 0)->type = ARC_OP_REG;
|
||||
ARC_get_detail_op(MI, 0)->reg = Reg;
|
||||
ARC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
|
||||
ARC_inc_op_count(MI);
|
||||
}
|
||||
|
||||
void ARC_add_cs_detail_0(MCInst *MI, int op_group, size_t OpNum)
|
||||
{
|
||||
if (!detail_is_set(MI))
|
||||
return;
|
||||
|
||||
cs_op_type op_type = map_get_op_type(MI, OpNum);
|
||||
cs_op_type base_op_type = op_type;
|
||||
cs_op_type offset_op_type;
|
||||
// Fill cs_detail
|
||||
switch (op_group) {
|
||||
default:
|
||||
printf("ERROR: Operand group %d not handled!\n", op_group);
|
||||
CS_ASSERT_RET(0);
|
||||
case ARC_OP_GROUP_Operand:
|
||||
if (op_type == CS_OP_IMM) {
|
||||
ARC_set_detail_op_imm(MI, OpNum, ARC_OP_IMM,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else if (op_type == CS_OP_REG) {
|
||||
ARC_set_detail_op_reg(MI, OpNum,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else {
|
||||
// Expression
|
||||
ARC_set_detail_op_imm(
|
||||
MI, OpNum, ARC_OP_IMM,
|
||||
MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
|
||||
}
|
||||
break;
|
||||
case ARC_OP_GROUP_PredicateOperand:
|
||||
if (op_type == CS_OP_IMM) {
|
||||
ARC_set_detail_op_imm(MI, OpNum, ARC_OP_IMM,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else
|
||||
CS_ASSERT(0 && "Op type not handled.");
|
||||
break;
|
||||
case ARC_OP_GROUP_MemOperandRI:
|
||||
if (base_op_type == CS_OP_REG) {
|
||||
ARC_set_detail_op_reg(MI, OpNum,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else
|
||||
CS_ASSERT(0 && "Op type not handled.");
|
||||
offset_op_type = map_get_op_type(MI, OpNum + 1);
|
||||
if (offset_op_type == CS_OP_IMM) {
|
||||
ARC_set_detail_op_imm(MI, OpNum + 1, ARC_OP_IMM,
|
||||
MCInst_getOpVal(MI, OpNum + 1));
|
||||
} else
|
||||
CS_ASSERT(0 && "Op type not handled.");
|
||||
break;
|
||||
case ARC_OP_GROUP_BRCCPredicateOperand:
|
||||
if (op_type == CS_OP_IMM) {
|
||||
ARC_set_detail_op_imm(MI, OpNum, ARC_OP_IMM,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else
|
||||
CS_ASSERT(0 && "Op type not handled.");
|
||||
break;
|
||||
case ARC_OP_GROUP_CCOperand:
|
||||
if (op_type == CS_OP_IMM) {
|
||||
ARC_set_detail_op_imm(MI, OpNum, ARC_OP_IMM,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else
|
||||
CS_ASSERT(0 && "Op type not handled.");
|
||||
break;
|
||||
case ARC_OP_GROUP_U6:
|
||||
if (op_type == CS_OP_IMM) {
|
||||
ARC_set_detail_op_imm(MI, OpNum, ARC_OP_IMM,
|
||||
MCInst_getOpVal(MI, OpNum));
|
||||
} else
|
||||
CS_ASSERT(0 && "Op type not handled.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dmitry Sibirtsev <sibirtsevdl@gmail.com>, 2024 */
|
||||
|
||||
#ifndef CS_ARC_MAP_H
|
||||
#define CS_ARC_MAP_H
|
||||
|
||||
#include "../../Mapping.h"
|
||||
#include "../../include/capstone/capstone.h"
|
||||
#include "../../utils.h"
|
||||
|
||||
typedef enum {
|
||||
#include "ARCGenCSOpGroup.inc"
|
||||
} arc_op_group;
|
||||
|
||||
void ARC_init_mri(MCRegisterInfo *MRI);
|
||||
|
||||
// return name of register in friendly string
|
||||
const char *ARC_reg_name(csh handle, unsigned int reg);
|
||||
|
||||
void ARC_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info);
|
||||
|
||||
// given internal insn id, return public instruction ID
|
||||
void ARC_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
|
||||
const char *ARC_insn_name(csh handle, unsigned int id);
|
||||
|
||||
const char *ARC_group_name(csh handle, unsigned int id);
|
||||
|
||||
void ARC_reg_access(const cs_insn *insn, cs_regs regs_read,
|
||||
uint8_t *regs_read_count, cs_regs regs_write,
|
||||
uint8_t *regs_write_count);
|
||||
|
||||
bool ARC_getInstruction(csh handle, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address,
|
||||
void *info);
|
||||
|
||||
// cs_detail related functions
|
||||
void ARC_init_cs_detail(MCInst *MI);
|
||||
void ARC_set_detail_op_imm(MCInst *MI, unsigned OpNum, arc_op_type ImmType,
|
||||
int64_t Imm);
|
||||
void ARC_add_cs_detail_0(MCInst *MI, int /* arc_op_group */ op_group,
|
||||
size_t op_num);
|
||||
|
||||
#endif
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dmitry Sibirtsev <sibirtsevdl@gmail.com>, 2024 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_ARC
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
|
||||
#include "ARCModule.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../cs_priv.h"
|
||||
#include "ARCMapping.h"
|
||||
|
||||
cs_err ARC_global_init(cs_struct *ud)
|
||||
{
|
||||
MCRegisterInfo *mri;
|
||||
mri = cs_mem_malloc(sizeof(*mri));
|
||||
if (!mri)
|
||||
return CS_ERR_MEM;
|
||||
|
||||
ARC_init_mri(mri);
|
||||
|
||||
ud->printer = ARC_printer;
|
||||
ud->printer_info = mri;
|
||||
ud->reg_name = ARC_reg_name;
|
||||
ud->insn_id = ARC_get_insn_id;
|
||||
ud->insn_name = ARC_insn_name;
|
||||
ud->group_name = ARC_group_name;
|
||||
ud->post_printer = NULL;
|
||||
#ifndef CAPSTONE_DIET
|
||||
ud->reg_access = ARC_reg_access;
|
||||
#endif
|
||||
|
||||
ud->disasm = ARC_getInstruction;
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
cs_err ARC_option(cs_struct *handle, cs_opt_type type, size_t value)
|
||||
{
|
||||
switch (type) {
|
||||
case CS_OPT_MODE:
|
||||
handle->mode = (cs_mode)value;
|
||||
break;
|
||||
case CS_OPT_SYNTAX:
|
||||
handle->syntax |= (int)value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Dmitry Sibirtsev <sibirtsevdl@gmail.com>, 2024 */
|
||||
|
||||
#ifndef CS_ARC_MODULE_H
|
||||
#define CS_ARC_MODULE_H
|
||||
|
||||
#include "../../utils.h"
|
||||
|
||||
cs_err ARC_global_init(cs_struct *ud);
|
||||
cs_err ARC_option(cs_struct *handle, cs_opt_type type, size_t value);
|
||||
|
||||
#endif
|
||||
+792
@@ -0,0 +1,792 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the ARM addressing mode implementation stuff.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CS_ARM_ADDRESSINGMODES_H
|
||||
#define CS_ARM_ADDRESSINGMODES_H
|
||||
|
||||
#include "../../cs_priv.h"
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include "../../MathExtras.h"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
/// ARM_AM - ARM Addressing Mode Stuff
|
||||
// CS namespace begin: ARM_AM
|
||||
|
||||
typedef enum ShiftOpc {
|
||||
ARM_AM_no_shift = 0,
|
||||
ARM_AM_asr,
|
||||
ARM_AM_lsl,
|
||||
ARM_AM_lsr,
|
||||
ARM_AM_ror,
|
||||
ARM_AM_rrx,
|
||||
ARM_AM_uxtw
|
||||
} ARM_AM_ShiftOpc;
|
||||
|
||||
typedef enum AddrOpc { ARM_AM_sub = 0, ARM_AM_add } ARM_AM_AddrOpc;
|
||||
|
||||
static inline const char *ARM_AM_getAddrOpcStr(ARM_AM_AddrOpc Op)
|
||||
{
|
||||
return Op == ARM_AM_sub ? "-" : "";
|
||||
}
|
||||
|
||||
static inline const char *ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op)
|
||||
{
|
||||
switch (Op) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", NULL);
|
||||
case ARM_AM_asr:
|
||||
return "asr";
|
||||
case ARM_AM_lsl:
|
||||
return "lsl";
|
||||
case ARM_AM_lsr:
|
||||
return "lsr";
|
||||
case ARM_AM_ror:
|
||||
return "ror";
|
||||
case ARM_AM_rrx:
|
||||
return "rrx";
|
||||
case ARM_AM_uxtw:
|
||||
return "uxtw";
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getShiftOpcEncoding(ARM_AM_ShiftOpc Op)
|
||||
{
|
||||
switch (Op) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", 0);
|
||||
case ARM_AM_asr:
|
||||
return 2;
|
||||
case ARM_AM_lsl:
|
||||
return 0;
|
||||
case ARM_AM_lsr:
|
||||
return 1;
|
||||
case ARM_AM_ror:
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum AMSubMode {
|
||||
ARM_AM_bad_am_submode = 0,
|
||||
ARM_AM_ia,
|
||||
ARM_AM_ib,
|
||||
ARM_AM_da,
|
||||
ARM_AM_db
|
||||
} ARM_AM_SubMode;
|
||||
|
||||
static inline const char *ARM_AM_getAMSubModeStr(ARM_AM_SubMode Mode)
|
||||
{
|
||||
switch (Mode) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL(0 && "Unknown addressing sub-mode!", NULL);
|
||||
case ARM_AM_ia:
|
||||
return "ia";
|
||||
case ARM_AM_ib:
|
||||
return "ib";
|
||||
case ARM_AM_da:
|
||||
return "da";
|
||||
case ARM_AM_db:
|
||||
return "db";
|
||||
}
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #1: shift_operand with registers
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This 'addressing mode' is used for arithmetic instructions. It can
|
||||
// represent things like:
|
||||
// reg
|
||||
// reg [asr|lsl|lsr|ror|rrx] reg
|
||||
// reg [asr|lsl|lsr|ror|rrx] imm
|
||||
//
|
||||
// This is stored three operands [rega, regb, opc]. The first is the base
|
||||
// reg, the second is the shift amount (or reg0 if not present or imm). The
|
||||
// third operand encodes the shift opcode and the imm if a reg isn't present.
|
||||
static inline unsigned ARM_AM_rotr32(unsigned Val, unsigned Amt)
|
||||
{
|
||||
CS_ASSERT(Amt <= 32);
|
||||
if (Amt == 32) {
|
||||
return Val;
|
||||
}
|
||||
// NOLINTBEGIN(clang-analyzer-core.BitwiseShift)
|
||||
return (Val >> Amt) | (Val << ((32 - Amt) & 31));
|
||||
// NOLINTEND(clang-analyzer-core.BitwiseShift)
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_rotl32(unsigned Val, unsigned Amt)
|
||||
{
|
||||
return (Val << Amt) | (Val >> ((32 - Amt) & 31));
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getSORegOpc(ARM_AM_ShiftOpc ShOp, unsigned Imm)
|
||||
{
|
||||
return ShOp | (Imm << 3);
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getSORegOffset(unsigned Op)
|
||||
{
|
||||
return Op >> 3;
|
||||
}
|
||||
|
||||
static inline ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op)
|
||||
{
|
||||
return (ARM_AM_ShiftOpc)(Op & 7);
|
||||
}
|
||||
|
||||
/// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
|
||||
/// the 8-bit imm value.
|
||||
static inline unsigned ARM_AM_getSOImmValImm(unsigned Imm)
|
||||
{
|
||||
return Imm & 0xFF;
|
||||
}
|
||||
|
||||
/// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
|
||||
/// the rotate amount.
|
||||
static inline unsigned ARM_AM_getSOImmValRot(unsigned Imm)
|
||||
{
|
||||
return (Imm >> 8) * 2;
|
||||
}
|
||||
|
||||
/// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
|
||||
/// computing the rotate amount to use. If this immediate value cannot be
|
||||
/// handled with a single shifter-op, determine a good rotate amount that will
|
||||
/// take a maximal chunk of bits out of the immediate.
|
||||
static inline unsigned ARM_AM_getSOImmValRotate(unsigned Imm)
|
||||
{
|
||||
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
|
||||
// of zero.
|
||||
if ((Imm & ~255U) == 0)
|
||||
return 0;
|
||||
|
||||
// Use CTZ to compute the rotate amount.
|
||||
unsigned TZ = CountTrailingZeros_32(Imm);
|
||||
|
||||
// Rotate amount must be even. Something like 0x200 must be rotated 8 bits,
|
||||
// not 9.
|
||||
unsigned RotAmt = TZ & ~1;
|
||||
|
||||
// If we can handle this spread, return it.
|
||||
if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0)
|
||||
return (32 - RotAmt) & 31; // HW rotates right, not left.
|
||||
|
||||
// For values like 0xF000000F, we should ignore the low 6 bits, then
|
||||
// retry the hunt.
|
||||
if (Imm & 63U) {
|
||||
unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);
|
||||
unsigned RotAmt2 = TZ2 & ~1;
|
||||
if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0)
|
||||
return (32 - RotAmt2) &
|
||||
31; // HW rotates right, not left.
|
||||
}
|
||||
|
||||
// Otherwise, we have no way to cover this span of bits with a single
|
||||
// shifter_op immediate. Return a chunk of bits that will be useful to
|
||||
// handle.
|
||||
return (32 - RotAmt) & 31; // HW rotates right, not left.
|
||||
}
|
||||
|
||||
/// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
|
||||
/// into an shifter_operand immediate operand, return the 12-bit encoding for
|
||||
/// it. If not, return -1.
|
||||
static inline int ARM_AM_getSOImmVal(unsigned Arg)
|
||||
{
|
||||
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
|
||||
// of zero.
|
||||
if ((Arg & ~255U) == 0)
|
||||
return Arg;
|
||||
|
||||
unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg);
|
||||
|
||||
// If this cannot be handled with a single shifter_op, bail out.
|
||||
if (ARM_AM_rotr32(~255U, RotAmt) & Arg)
|
||||
return -1;
|
||||
|
||||
// Encode this correctly.
|
||||
return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8);
|
||||
}
|
||||
|
||||
/// isSOImmTwoPartVal - Return true if the specified value can be obtained by
|
||||
/// or'ing together two SOImmVal's.
|
||||
static inline bool ARM_AM_isSOImmTwoPartVal(unsigned V)
|
||||
{
|
||||
// If this can be handled with a single shifter_op, bail out.
|
||||
V = ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(V)) & V;
|
||||
if (V == 0)
|
||||
return false;
|
||||
|
||||
// If this can be handled with two shifter_op's, accept.
|
||||
V = ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(V)) & V;
|
||||
return V == 0;
|
||||
}
|
||||
|
||||
/// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
|
||||
/// return the first chunk of it.
|
||||
static inline unsigned ARM_AM_getSOImmTwoPartFirst(unsigned V)
|
||||
{
|
||||
return ARM_AM_rotr32(255U, ARM_AM_getSOImmValRotate(V)) & V;
|
||||
}
|
||||
|
||||
/// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
|
||||
/// return the second chunk of it.
|
||||
static inline unsigned ARM_AM_getSOImmTwoPartSecond(unsigned V)
|
||||
{
|
||||
// Mask out the first hunk.
|
||||
V = ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(V)) & V;
|
||||
|
||||
// Take what's left.
|
||||
|
||||
return V;
|
||||
}
|
||||
|
||||
/// isSOImmTwoPartValNeg - Return true if the specified value can be obtained
|
||||
/// by two SOImmVal, that -V = First + Second.
|
||||
/// "R+V" can be optimized to (sub (sub R, First), Second).
|
||||
/// "R=V" can be optimized to (sub (mvn R, ~(-First)), Second).
|
||||
static inline bool ARM_AM_isSOImmTwoPartValNeg(unsigned V)
|
||||
{
|
||||
unsigned First;
|
||||
if (!ARM_AM_isSOImmTwoPartVal(-V))
|
||||
return false;
|
||||
// Return false if ~(-First) is not a SoImmval.
|
||||
First = ARM_AM_getSOImmTwoPartFirst(-V);
|
||||
First = ~(-First);
|
||||
return !(ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(First)) & First);
|
||||
}
|
||||
|
||||
/// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
|
||||
/// by a left shift. Returns the shift amount to use.
|
||||
static inline unsigned ARM_AM_getThumbImmValShift(unsigned Imm)
|
||||
{
|
||||
// 8-bit (or less) immediates are trivially immediate operand with a shift
|
||||
// of zero.
|
||||
if ((Imm & ~255U) == 0)
|
||||
return 0;
|
||||
|
||||
// Use CTZ to compute the shift amount.
|
||||
return CountTrailingZeros_32(Imm);
|
||||
}
|
||||
|
||||
/// isThumbImmShiftedVal - Return true if the specified value can be obtained
|
||||
/// by left shifting a 8-bit immediate.
|
||||
static inline bool ARM_AM_isThumbImmShiftedVal(unsigned V)
|
||||
{
|
||||
// If this can be handled with
|
||||
V = (~255U << ARM_AM_getThumbImmValShift(V)) & V;
|
||||
return V == 0;
|
||||
}
|
||||
|
||||
/// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
|
||||
/// by a left shift. Returns the shift amount to use.
|
||||
static inline unsigned ARM_AM_getThumbImm16ValShift(unsigned Imm)
|
||||
{
|
||||
// 16-bit (or less) immediates are trivially immediate operand with a shift
|
||||
// of zero.
|
||||
if ((Imm & ~65535U) == 0)
|
||||
return 0;
|
||||
|
||||
// Use CTZ to compute the shift amount.
|
||||
return CountTrailingZeros_32(Imm);
|
||||
}
|
||||
|
||||
/// isThumbImm16ShiftedVal - Return true if the specified value can be
|
||||
/// obtained by left shifting a 16-bit immediate.
|
||||
static inline bool ARM_AM_isThumbImm16ShiftedVal(unsigned V)
|
||||
{
|
||||
// If this can be handled with
|
||||
V = (~65535U << ARM_AM_getThumbImm16ValShift(V)) & V;
|
||||
return V == 0;
|
||||
}
|
||||
|
||||
/// getThumbImmNonShiftedVal - If V is a value that satisfies
|
||||
/// isThumbImmShiftedVal, return the non-shiftd value.
|
||||
static inline unsigned ARM_AM_getThumbImmNonShiftedVal(unsigned V)
|
||||
{
|
||||
return V >> ARM_AM_getThumbImmValShift(V);
|
||||
}
|
||||
|
||||
/// getT2SOImmValSplat - Return the 12-bit encoded representation
|
||||
/// if the specified value can be obtained by splatting the low 8 bits
|
||||
/// into every other byte or every byte of a 32-bit value. i.e.,
|
||||
/// 00000000 00000000 00000000 abcdefgh control = 0
|
||||
/// 00000000 abcdefgh 00000000 abcdefgh control = 1
|
||||
/// abcdefgh 00000000 abcdefgh 00000000 control = 2
|
||||
/// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
|
||||
/// Return -1 if none of the above apply.
|
||||
/// See ARM Reference Manual A6.3.2.
|
||||
static inline int ARM_AM_getT2SOImmValSplatVal(unsigned V)
|
||||
{
|
||||
unsigned u, Vs, Imm;
|
||||
// control = 0
|
||||
if ((V & 0xffffff00) == 0)
|
||||
return V;
|
||||
|
||||
// If the value is zeroes in the first byte, just shift those off
|
||||
Vs = ((V & 0xff) == 0) ? V >> 8 : V;
|
||||
// Any passing value only has 8 bits of payload, splatted across the word
|
||||
Imm = Vs & 0xff;
|
||||
// Likewise, any passing values have the payload splatted into the 3rd byte
|
||||
u = Imm | (Imm << 16);
|
||||
|
||||
// control = 1 or 2
|
||||
if (Vs == u)
|
||||
return (((Vs == V) ? 1 : 2) << 8) | Imm;
|
||||
|
||||
// control = 3
|
||||
if (Vs == (u | (u << 8)))
|
||||
return (3 << 8) | Imm;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
|
||||
/// specified value is a rotated 8-bit value. Return -1 if no rotation
|
||||
/// encoding is possible.
|
||||
/// See ARM Reference Manual A6.3.2.
|
||||
static inline int ARM_AM_getT2SOImmValRotateVal(unsigned V)
|
||||
{
|
||||
unsigned RotAmt = CountLeadingZeros_32(V);
|
||||
if (RotAmt >= 24)
|
||||
return -1;
|
||||
|
||||
// If 'Arg' can be handled with a single shifter_op return the value.
|
||||
if ((ARM_AM_rotr32(0xff000000U, RotAmt) & V) == V)
|
||||
return (ARM_AM_rotr32(V, 24 - RotAmt) & 0x7f) |
|
||||
((RotAmt + 8) << 7);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
|
||||
/// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
|
||||
/// encoding for it. If not, return -1.
|
||||
/// See ARM Reference Manual A6.3.2.
|
||||
static inline int ARM_AM_getT2SOImmVal(unsigned Arg)
|
||||
{
|
||||
// If 'Arg' is an 8-bit splat, then get the encoded value.
|
||||
int Splat = ARM_AM_getT2SOImmValSplatVal(Arg);
|
||||
if (Splat != -1)
|
||||
return Splat;
|
||||
|
||||
// If 'Arg' can be handled with a single shifter_op return the value.
|
||||
int Rot = ARM_AM_getT2SOImmValRotateVal(Arg);
|
||||
if (Rot != -1)
|
||||
return Rot;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getT2SOImmValRotate(unsigned V)
|
||||
{
|
||||
if ((V & ~255U) == 0)
|
||||
return 0;
|
||||
// Use CTZ to compute the rotate amount.
|
||||
unsigned RotAmt = CountTrailingZeros_32(V);
|
||||
return (32 - RotAmt) & 31;
|
||||
}
|
||||
|
||||
static inline bool ARM_AM_isT2SOImmTwoPartVal(unsigned Imm)
|
||||
{
|
||||
unsigned V = Imm;
|
||||
// Passing values can be any combination of splat values and shifter
|
||||
// values. If this can be handled with a single shifter or splat, bail
|
||||
// out. Those should be handled directly, not with a two-part val.
|
||||
if (ARM_AM_getT2SOImmValSplatVal(V) != -1)
|
||||
return false;
|
||||
V = ARM_AM_rotr32(~255U, ARM_AM_getT2SOImmValRotate(V)) & V;
|
||||
if (V == 0)
|
||||
return false;
|
||||
|
||||
// If this can be handled as an immediate, accept.
|
||||
if (ARM_AM_getT2SOImmVal(V) != -1)
|
||||
return true;
|
||||
|
||||
// Likewise, try masking out a splat value first.
|
||||
V = Imm;
|
||||
if (ARM_AM_getT2SOImmValSplatVal(V & 0xff00ff00U) != -1)
|
||||
V &= ~0xff00ff00U;
|
||||
else if (ARM_AM_getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1)
|
||||
V &= ~0x00ff00ffU;
|
||||
// If what's left can be handled as an immediate, accept.
|
||||
if (ARM_AM_getT2SOImmVal(V) != -1)
|
||||
return true;
|
||||
|
||||
// Otherwise, do not accept.
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getT2SOImmTwoPartFirst(unsigned Imm)
|
||||
{
|
||||
CS_ASSERT(ARM_AM_isT2SOImmTwoPartVal(Imm) &&
|
||||
"Immedate cannot be encoded as two part immediate!");
|
||||
// Try a shifter operand as one part
|
||||
unsigned V = ARM_AM_rotr32(~255, ARM_AM_getT2SOImmValRotate(Imm)) & Imm;
|
||||
// If the rest is encodable as an immediate, then return it.
|
||||
if (ARM_AM_getT2SOImmVal(V) != -1)
|
||||
return V;
|
||||
|
||||
// Try masking out a splat value first.
|
||||
if (ARM_AM_getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1)
|
||||
return Imm & 0xff00ff00U;
|
||||
|
||||
// The other splat is all that's left as an option.
|
||||
CS_ASSERT(ARM_AM_getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1);
|
||||
return Imm & 0x00ff00ffU;
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getT2SOImmTwoPartSecond(unsigned Imm)
|
||||
{
|
||||
// Mask out the first hunk
|
||||
Imm ^= ARM_AM_getT2SOImmTwoPartFirst(Imm);
|
||||
// Return what's left
|
||||
CS_ASSERT(ARM_AM_getT2SOImmVal(Imm) != -1 &&
|
||||
"Unable to encode second part of T2 two part SO immediate");
|
||||
return Imm;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #2
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for most simple load/store instructions.
|
||||
//
|
||||
// addrmode2 := reg +/- reg shop imm
|
||||
// addrmode2 := reg +/- imm12
|
||||
//
|
||||
// The first operand is always a Reg. The second operand is a reg if in
|
||||
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
|
||||
// in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
|
||||
// fourth operand 16-17 encodes the index mode.
|
||||
//
|
||||
// If this addressing mode is a frame index (before prolog/epilog insertion
|
||||
// and code rewriting), this operand will have the form: FI#, reg0, <offs>
|
||||
// with no shift amount for the frame offset.
|
||||
//
|
||||
static inline unsigned ARM_AM_getAM2Opc(ARM_AM_AddrOpc Opc, unsigned Imm12,
|
||||
ARM_AM_ShiftOpc SO, unsigned IdxMode)
|
||||
{
|
||||
CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!");
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16);
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getAM2Offset(unsigned AM2Opc)
|
||||
{
|
||||
return AM2Opc & ((1 << 12) - 1);
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc ARM_AM_getAM2Op(unsigned AM2Opc)
|
||||
{
|
||||
return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
static inline ARM_AM_ShiftOpc ARM_AM_getAM2ShiftOpc(unsigned AM2Opc)
|
||||
{
|
||||
return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7);
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getAM2IdxMode(unsigned AM2Opc)
|
||||
{
|
||||
return (AM2Opc >> 16);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #3
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for sign-extending loads, and load/store-pair instructions.
|
||||
//
|
||||
// addrmode3 := reg +/- reg
|
||||
// addrmode3 := reg +/- imm8
|
||||
//
|
||||
// The first operand is always a Reg. The second operand is a reg if in
|
||||
// reg/reg form, otherwise it's reg#0. The third field encodes the operation
|
||||
// in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
|
||||
// index mode.
|
||||
/// getAM3Opc - This function encodes the addrmode3 opc field.
|
||||
static inline unsigned ARM_AM_getAM3Opc(ARM_AM_AddrOpc Opc,
|
||||
unsigned char Offset, unsigned IdxMode)
|
||||
{
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return ((int)isSub << 8) | Offset | (IdxMode << 9);
|
||||
}
|
||||
|
||||
static inline unsigned char ARM_AM_getAM3Offset(unsigned AM3Opc)
|
||||
{
|
||||
return AM3Opc & 0xFF;
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc ARM_AM_getAM3Op(unsigned AM3Opc)
|
||||
{
|
||||
return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getAM3IdxMode(unsigned AM3Opc)
|
||||
{
|
||||
return (AM3Opc >> 9);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #4
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for load / store multiple instructions.
|
||||
//
|
||||
// addrmode4 := reg, <mode>
|
||||
//
|
||||
// The four modes are:
|
||||
// IA - Increment after
|
||||
// IB - Increment before
|
||||
// DA - Decrement after
|
||||
// DB - Decrement before
|
||||
// For VFP instructions, only the IA and DB modes are valid.
|
||||
static inline ARM_AM_SubMode ARM_AM_getAM4SubMode(unsigned Mode)
|
||||
{
|
||||
return (ARM_AM_SubMode)(Mode & 0x7);
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getAM4ModeImm(ARM_AM_SubMode SubMode)
|
||||
{
|
||||
return (int)SubMode;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #5
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for coprocessor instructions, such as FP load/stores.
|
||||
//
|
||||
// addrmode5 := reg +/- imm8*4
|
||||
//
|
||||
// The first operand is always a Reg. The second operand encodes the
|
||||
// operation (add or subtract) in bit 8 and the immediate in bits 0-7.
|
||||
/// getAM5Opc - This function encodes the addrmode5 opc field.
|
||||
static inline unsigned ARM_AM_getAM5Opc(ARM_AM_AddrOpc Opc,
|
||||
unsigned char Offset)
|
||||
{
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return ((int)isSub << 8) | Offset;
|
||||
}
|
||||
|
||||
static inline unsigned char ARM_AM_getAM5Offset(unsigned AM5Opc)
|
||||
{
|
||||
return AM5Opc & 0xFF;
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc)
|
||||
{
|
||||
return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #5 FP16
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for coprocessor instructions, such as 16-bit FP load/stores.
|
||||
//
|
||||
// addrmode5fp16 := reg +/- imm8*2
|
||||
//
|
||||
// The first operand is always a Reg. The second operand encodes the
|
||||
// operation (add or subtract) in bit 8 and the immediate in bits 0-7.
|
||||
/// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
|
||||
static inline unsigned ARM_AM_getAM5FP16Opc(ARM_AM_AddrOpc Opc,
|
||||
unsigned char Offset)
|
||||
{
|
||||
bool isSub = Opc == ARM_AM_sub;
|
||||
return ((int)isSub << 8) | Offset;
|
||||
}
|
||||
|
||||
static inline unsigned char ARM_AM_getAM5FP16Offset(unsigned AM5Opc)
|
||||
{
|
||||
return AM5Opc & 0xFF;
|
||||
}
|
||||
|
||||
static inline ARM_AM_AddrOpc ARM_AM_getAM5FP16Op(unsigned AM5Opc)
|
||||
{
|
||||
return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Addressing Mode #6
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// This is used for NEON load / store instructions.
|
||||
//
|
||||
// addrmode6 := reg with optional alignment
|
||||
//
|
||||
// This is stored in two operands [regaddr, align]. The first is the
|
||||
// address register. The second operand is the value of the alignment
|
||||
// specifier in bytes or zero if no explicit alignment.
|
||||
// Valid alignments depend on the specific instruction.
|
||||
//===--------------------------------------------------------------------===//
|
||||
// NEON/MVE Modified Immediates
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate"
|
||||
// vector operand, where a small immediate encoded in the instruction
|
||||
// specifies a full NEON vector value. These modified immediates are
|
||||
// represented here as encoded integers. The low 8 bits hold the immediate
|
||||
// value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
|
||||
// the "Cmode" field of the instruction. The interfaces below treat the
|
||||
// Op and Cmode values as a single 5-bit value.
|
||||
static inline unsigned ARM_AM_createVMOVModImm(unsigned OpCmode, unsigned Val)
|
||||
{
|
||||
return (OpCmode << 8) | Val;
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getVMOVModImmOpCmode(unsigned ModImm)
|
||||
{
|
||||
return (ModImm >> 8) & 0x1f;
|
||||
}
|
||||
|
||||
static inline unsigned ARM_AM_getVMOVModImmVal(unsigned ModImm)
|
||||
{
|
||||
return ModImm & 0xff;
|
||||
}
|
||||
|
||||
/// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the
|
||||
/// element value and the element size in bits. (If the element size is
|
||||
/// smaller than the vector, it is splatted into all the elements.)
|
||||
static inline uint64_t ARM_AM_decodeVMOVModImm(unsigned ModImm,
|
||||
unsigned *EltBits)
|
||||
{
|
||||
unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm);
|
||||
unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm);
|
||||
uint64_t Val = 0;
|
||||
|
||||
if (OpCmode == 0xe) {
|
||||
// 8-bit vector elements
|
||||
Val = Imm8;
|
||||
*EltBits = 8;
|
||||
} else if ((OpCmode & 0xc) == 0x8) {
|
||||
// 16-bit vector elements
|
||||
unsigned ByteNum = (OpCmode & 0x6) >> 1;
|
||||
Val = Imm8 << (8 * ByteNum);
|
||||
*EltBits = 16;
|
||||
} else if ((OpCmode & 0x8) == 0) {
|
||||
// 32-bit vector elements, zero with one byte set
|
||||
unsigned ByteNum = (OpCmode & 0x6) >> 1;
|
||||
Val = Imm8 << (8 * ByteNum);
|
||||
*EltBits = 32;
|
||||
} else if ((OpCmode & 0xe) == 0xc) {
|
||||
// 32-bit vector elements, one byte with low bits set
|
||||
unsigned ByteNum = 1 + (OpCmode & 0x1);
|
||||
Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));
|
||||
*EltBits = 32;
|
||||
} else if (OpCmode == 0x1e) {
|
||||
// 64-bit vector elements
|
||||
for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
|
||||
if ((ModImm >> ByteNum) & 1)
|
||||
Val |= (uint64_t)0xff << (8 * ByteNum);
|
||||
}
|
||||
*EltBits = 64;
|
||||
} else {
|
||||
CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0);
|
||||
}
|
||||
return Val;
|
||||
}
|
||||
|
||||
// Generic validation for single-byte immediate (0X00, 00X0, etc).
|
||||
static inline bool ARM_AM_isNEONBytesplat(unsigned Value, unsigned Size)
|
||||
{
|
||||
CS_ASSERT(Size >= 1 && Size <= 4 && "Invalid size");
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0; i < Size; ++i) {
|
||||
if (Value & 0xff)
|
||||
count++;
|
||||
Value >>= 8;
|
||||
}
|
||||
return count == 1;
|
||||
}
|
||||
|
||||
/// Checks if Value is a correct immediate for instructions like VBIC/VORR.
|
||||
static inline bool ARM_AM_isNEONi16splat(unsigned Value)
|
||||
{
|
||||
if (Value > 0xffff)
|
||||
return false;
|
||||
// i16 value with set bits only in one byte X0 or 0X.
|
||||
return Value == 0 || ARM_AM_isNEONBytesplat(Value, 2);
|
||||
}
|
||||
|
||||
// Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR
|
||||
static inline unsigned ARM_AM_encodeNEONi16splat(unsigned Value)
|
||||
{
|
||||
CS_ASSERT(ARM_AM_isNEONi16splat(Value) && "Invalid NEON splat value");
|
||||
if (Value >= 0x100)
|
||||
Value = (Value >> 8) | 0xa00;
|
||||
else
|
||||
Value |= 0x800;
|
||||
return Value;
|
||||
}
|
||||
|
||||
/// Checks if Value is a correct immediate for instructions like VBIC/VORR.
|
||||
static inline bool ARM_AM_isNEONi32splat(unsigned Value)
|
||||
{
|
||||
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
|
||||
return Value == 0 || ARM_AM_isNEONBytesplat(Value, 4);
|
||||
}
|
||||
|
||||
/// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR.
|
||||
static inline unsigned ARM_AM_encodeNEONi32splat(unsigned Value)
|
||||
{
|
||||
CS_ASSERT(ARM_AM_isNEONi32splat(Value) && "Invalid NEON splat value");
|
||||
if (Value >= 0x100 && Value <= 0xff00)
|
||||
Value = (Value >> 8) | 0x200;
|
||||
else if (Value > 0xffff && Value <= 0xff0000)
|
||||
Value = (Value >> 16) | 0x400;
|
||||
else if (Value > 0xffffff)
|
||||
Value = (Value >> 24) | 0x600;
|
||||
return Value;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Floating-point Immediates
|
||||
//
|
||||
static inline float ARM_AM_getFPImmFloat(unsigned Imm)
|
||||
{
|
||||
// We expect an 8-bit binary encoding of a floating-point number here.
|
||||
|
||||
uint32_t Sign = (Imm >> 7) & 0x1;
|
||||
uint32_t Exp = (Imm >> 4) & 0x7;
|
||||
uint32_t Mantissa = Imm & 0xf;
|
||||
|
||||
// 8-bit FP IEEE Float Encoding
|
||||
// abcd efgh aBbbbbbc defgh000 00000000 00000000
|
||||
//
|
||||
// where B = NOT(b);
|
||||
uint32_t I = 0;
|
||||
I |= Sign << 31;
|
||||
I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
|
||||
I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
|
||||
I |= (Exp & 0x3) << 23;
|
||||
I |= Mantissa << 19;
|
||||
return BitsToFloat(I);
|
||||
}
|
||||
|
||||
#endif // CS_ARM_ADDRESSINGMODES_H
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
||||
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
||||
/* Automatically translated source file from LLVM. */
|
||||
|
||||
/* LLVM-commit: <commit> */
|
||||
/* LLVM-tag: <tag> */
|
||||
|
||||
/* Only small edits allowed. */
|
||||
/* For multiple similar edits, please create a Patch for the translator. */
|
||||
|
||||
/* Capstone's C++ file translator: */
|
||||
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
||||
|
||||
//===-- ARMBaseInfo.cpp - ARM Base encoding information------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides basic encoding and assembly information for ARM.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <capstone/platform.h>
|
||||
|
||||
#include "ARMBaseInfo.h"
|
||||
#include "../../utils.h"
|
||||
|
||||
#define CONCAT(a, b) CONCAT_(a, b)
|
||||
#define CONCAT_(a, b) a##_##b
|
||||
|
||||
// CS namespace begin: ARMSysReg
|
||||
|
||||
// lookup system register using 12-bit SYSm value.
|
||||
// Note: the search is uniqued using M1 mask
|
||||
const char *get_pred_mask(ARM_PredBlockMask pred_mask)
|
||||
{
|
||||
switch (pred_mask) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL(0 && "pred_mask not handled.", NULL);
|
||||
case ARM_T:
|
||||
return "T";
|
||||
case ARM_TT:
|
||||
return "TT";
|
||||
case ARM_TE:
|
||||
return "TE";
|
||||
case ARM_TTT:
|
||||
return "TTT";
|
||||
case ARM_TTE:
|
||||
return "TTE";
|
||||
case ARM_TEE:
|
||||
return "TEE";
|
||||
case ARM_TET:
|
||||
return "TET";
|
||||
case ARM_TTTT:
|
||||
return "TTTT";
|
||||
case ARM_TTTE:
|
||||
return "TTTE";
|
||||
case ARM_TTEE:
|
||||
return "TTEE";
|
||||
case ARM_TTET:
|
||||
return "TTET";
|
||||
case ARM_TEEE:
|
||||
return "TEEE";
|
||||
case ARM_TEET:
|
||||
return "TEET";
|
||||
case ARM_TETT:
|
||||
return "TETT";
|
||||
case ARM_TETE:
|
||||
return "TETE";
|
||||
}
|
||||
}
|
||||
|
||||
#define GET_MCLASSSYSREG_IMPL
|
||||
#include "ARMGenSystemRegister.inc"
|
||||
|
||||
const ARMSysReg_MClassSysReg *
|
||||
ARMSysReg_lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm)
|
||||
{
|
||||
return ARMSysReg_lookupMClassSysRegByM1Encoding12(SYSm);
|
||||
}
|
||||
|
||||
// returns APSR with _<bits> qualifier.
|
||||
// Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
|
||||
const ARMSysReg_MClassSysReg *
|
||||
ARMSysReg_lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm)
|
||||
{
|
||||
return ARMSysReg_lookupMClassSysRegByM2M3Encoding8((1 << 9) |
|
||||
(SYSm & 0xFF));
|
||||
}
|
||||
|
||||
// lookup system registers using 8-bit SYSm value
|
||||
const ARMSysReg_MClassSysReg *
|
||||
ARMSysReg_lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm)
|
||||
{
|
||||
return ARMSysReg_lookupMClassSysRegByM2M3Encoding8((1 << 8) |
|
||||
(SYSm & 0xFF));
|
||||
}
|
||||
+572
@@ -0,0 +1,572 @@
|
||||
//===-- ARMBaseInfo.h - Top level definitions for ARM ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains small standalone helper functions and enum definitions for
|
||||
// the ARM target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CS_ARM_BASEINFO_H
|
||||
#define CS_ARM_BASEINFO_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../MCInstPrinter.h"
|
||||
#include "../../cs_priv.h"
|
||||
#include "capstone/arm.h"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
|
||||
// System Registers
|
||||
typedef struct MClassSysReg {
|
||||
const char *Name;
|
||||
arm_sysop_reg sysreg;
|
||||
uint16_t M1Encoding12;
|
||||
uint16_t M2M3Encoding8;
|
||||
uint16_t Encoding;
|
||||
int FeaturesRequired[2];
|
||||
} ARMSysReg_MClassSysReg;
|
||||
|
||||
// return true if FeaturesRequired are all present in ActiveFeatures
|
||||
static inline bool hasRequiredFeatures(const ARMSysReg_MClassSysReg *TheReg,
|
||||
int ActiveFeatures)
|
||||
{
|
||||
return (TheReg->FeaturesRequired[0] == ActiveFeatures ||
|
||||
TheReg->FeaturesRequired[1] == ActiveFeatures);
|
||||
}
|
||||
|
||||
// returns true if TestFeatures are all present in FeaturesRequired
|
||||
static inline bool
|
||||
MClassSysReg_isInRequiredFeatures(const ARMSysReg_MClassSysReg *TheReg,
|
||||
int TestFeatures)
|
||||
{
|
||||
return (TheReg->FeaturesRequired[0] == TestFeatures ||
|
||||
TheReg->FeaturesRequired[1] == TestFeatures);
|
||||
}
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "ARMGenSubtargetInfo.inc"
|
||||
|
||||
// lookup system register using 12-bit SYSm value.
|
||||
// Note: the search is uniqued using M1 mask
|
||||
const ARMSysReg_MClassSysReg *
|
||||
ARMSysReg_lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm);
|
||||
// returns APSR with _<bits> qualifier.
|
||||
// Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
|
||||
const ARMSysReg_MClassSysReg *
|
||||
ARMSysReg_lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm);
|
||||
// lookup system registers using 8-bit SYSm value
|
||||
const ARMSysReg_MClassSysReg *
|
||||
ARMSysReg_lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm);
|
||||
// end namespace ARMSysReg
|
||||
|
||||
// Banked Registers
|
||||
typedef struct BankedReg {
|
||||
const char *Name;
|
||||
arm_sysop_reg sysreg;
|
||||
uint16_t Encoding;
|
||||
} ARMBankedReg_BankedReg;
|
||||
|
||||
#define GET_BANKEDREG_DECL
|
||||
#define GET_MCLASSSYSREG_DECL
|
||||
#include "ARMGenSystemRegister.inc"
|
||||
|
||||
typedef enum IMod { ARM_PROC_IE = 2, ARM_PROC_ID = 3 } ARM_PROC_IMod;
|
||||
|
||||
typedef enum IFlags {
|
||||
ARM_PROC_F = 1,
|
||||
ARM_PROC_I = 2,
|
||||
ARM_PROC_A = 4
|
||||
} ARM_PROC_IFlags;
|
||||
|
||||
inline static const char *ARM_PROC_IFlagsToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
default:
|
||||
// llvm_unreachable("Unknown iflags operand");
|
||||
case ARM_PROC_F:
|
||||
return "f";
|
||||
case ARM_PROC_I:
|
||||
return "i";
|
||||
case ARM_PROC_A:
|
||||
return "a";
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *ARM_PROC_IModToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL("Unknown imod operand", NULL);
|
||||
case ARM_PROC_IE:
|
||||
return "ie";
|
||||
case ARM_PROC_ID:
|
||||
return "id";
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *ARM_MB_MemBOptToString(unsigned val, bool HasV8)
|
||||
{
|
||||
switch (val) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL("Unknown memory operation", NULL);
|
||||
case ARM_MB_SY:
|
||||
return "sy";
|
||||
case ARM_MB_ST:
|
||||
return "st";
|
||||
case ARM_MB_LD:
|
||||
return HasV8 ? "ld" : "#0xd";
|
||||
case ARM_MB_RESERVED_12:
|
||||
return "#0xc";
|
||||
case ARM_MB_ISH:
|
||||
return "ish";
|
||||
case ARM_MB_ISHST:
|
||||
return "ishst";
|
||||
case ARM_MB_ISHLD:
|
||||
return HasV8 ? "ishld" : "#0x9";
|
||||
case ARM_MB_RESERVED_8:
|
||||
return "#0x8";
|
||||
case ARM_MB_NSH:
|
||||
return "nsh";
|
||||
case ARM_MB_NSHST:
|
||||
return "nshst";
|
||||
case ARM_MB_NSHLD:
|
||||
return HasV8 ? "nshld" : "#0x5";
|
||||
case ARM_MB_RESERVED_4:
|
||||
return "#0x4";
|
||||
case ARM_MB_OSH:
|
||||
return "osh";
|
||||
case ARM_MB_OSHST:
|
||||
return "oshst";
|
||||
case ARM_MB_OSHLD:
|
||||
return HasV8 ? "oshld" : "#0x1";
|
||||
case ARM_MB_RESERVED_0:
|
||||
return "#0x0";
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum TraceSyncBOpt { ARM_TSB_CSYNC = 0 } ARM_TSB_TraceSyncBOpt;
|
||||
|
||||
inline static const char *ARM_TSB_TraceSyncBOptToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL(
|
||||
"Unknown trace synchronization barrier operation",
|
||||
NULL);
|
||||
case ARM_TSB_CSYNC:
|
||||
return "csync";
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum InstSyncBOpt {
|
||||
ARM_ISB_RESERVED_0 = 0,
|
||||
ARM_ISB_RESERVED_1 = 1,
|
||||
ARM_ISB_RESERVED_2 = 2,
|
||||
ARM_ISB_RESERVED_3 = 3,
|
||||
ARM_ISB_RESERVED_4 = 4,
|
||||
ARM_ISB_RESERVED_5 = 5,
|
||||
ARM_ISB_RESERVED_6 = 6,
|
||||
ARM_ISB_RESERVED_7 = 7,
|
||||
ARM_ISB_RESERVED_8 = 8,
|
||||
ARM_ISB_RESERVED_9 = 9,
|
||||
ARM_ISB_RESERVED_10 = 10,
|
||||
ARM_ISB_RESERVED_11 = 11,
|
||||
ARM_ISB_RESERVED_12 = 12,
|
||||
ARM_ISB_RESERVED_13 = 13,
|
||||
ARM_ISB_RESERVED_14 = 14,
|
||||
ARM_ISB_SY = 15
|
||||
} ARM_ISB_InstSyncBOpt;
|
||||
|
||||
inline static const char *ARM_ISB_InstSyncBOptToString(unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
default:
|
||||
CS_ASSERT_RET_VAL("Unknown memory operation", NULL);
|
||||
case ARM_ISB_RESERVED_0:
|
||||
return "#0x0";
|
||||
case ARM_ISB_RESERVED_1:
|
||||
return "#0x1";
|
||||
case ARM_ISB_RESERVED_2:
|
||||
return "#0x2";
|
||||
case ARM_ISB_RESERVED_3:
|
||||
return "#0x3";
|
||||
case ARM_ISB_RESERVED_4:
|
||||
return "#0x4";
|
||||
case ARM_ISB_RESERVED_5:
|
||||
return "#0x5";
|
||||
case ARM_ISB_RESERVED_6:
|
||||
return "#0x6";
|
||||
case ARM_ISB_RESERVED_7:
|
||||
return "#0x7";
|
||||
case ARM_ISB_RESERVED_8:
|
||||
return "#0x8";
|
||||
case ARM_ISB_RESERVED_9:
|
||||
return "#0x9";
|
||||
case ARM_ISB_RESERVED_10:
|
||||
return "#0xa";
|
||||
case ARM_ISB_RESERVED_11:
|
||||
return "#0xb";
|
||||
case ARM_ISB_RESERVED_12:
|
||||
return "#0xc";
|
||||
case ARM_ISB_RESERVED_13:
|
||||
return "#0xd";
|
||||
case ARM_ISB_RESERVED_14:
|
||||
return "#0xe";
|
||||
case ARM_ISB_SY:
|
||||
return "sy";
|
||||
}
|
||||
}
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "ARMGenRegisterInfo.inc"
|
||||
|
||||
/// isARMLowRegister - Returns true if the register is a low register (r0-r7).
|
||||
///
|
||||
static inline bool isARMLowRegister(unsigned Reg)
|
||||
{
|
||||
switch (Reg) {
|
||||
case ARM_R0:
|
||||
case ARM_R1:
|
||||
case ARM_R2:
|
||||
case ARM_R3:
|
||||
case ARM_R4:
|
||||
case ARM_R5:
|
||||
case ARM_R6:
|
||||
case ARM_R7:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// ARMII - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
///
|
||||
/// ARM Index Modes
|
||||
typedef enum IndexMode {
|
||||
ARMII_IndexModeNone = 0,
|
||||
ARMII_IndexModePre = 1,
|
||||
ARMII_IndexModePost = 2,
|
||||
ARMII_IndexModeUpd = 3
|
||||
} ARMII_IndexMode;
|
||||
|
||||
/// ARM Addressing Modes
|
||||
typedef enum AddrMode {
|
||||
ARMII_AddrModeNone = 0,
|
||||
ARMII_AddrMode1 = 1,
|
||||
ARMII_AddrMode2 = 2,
|
||||
ARMII_AddrMode3 = 3,
|
||||
ARMII_AddrMode4 = 4,
|
||||
ARMII_AddrMode5 = 5,
|
||||
ARMII_AddrMode6 = 6,
|
||||
ARMII_AddrModeT1_1 = 7,
|
||||
ARMII_AddrModeT1_2 = 8,
|
||||
ARMII_AddrModeT1_4 = 9,
|
||||
ARMII_AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data
|
||||
ARMII_AddrModeT2_i12 = 11,
|
||||
ARMII_AddrModeT2_i8 = 12, // +/- i8
|
||||
ARMII_AddrModeT2_i8pos = 13, // + i8
|
||||
ARMII_AddrModeT2_i8neg = 14, // - i8
|
||||
ARMII_AddrModeT2_so = 15,
|
||||
ARMII_AddrModeT2_pc = 16, // +/- i12 for pc relative data
|
||||
ARMII_AddrModeT2_i8s4 = 17, // i8 * 4
|
||||
ARMII_AddrMode_i12 = 18,
|
||||
ARMII_AddrMode5FP16 = 19, // i8 * 2
|
||||
ARMII_AddrModeT2_ldrex = 20, // i8 * 4, with unscaled offset in MCInst
|
||||
ARMII_AddrModeT2_i7s4 = 21, // i7 * 4
|
||||
ARMII_AddrModeT2_i7s2 = 22, // i7 * 2
|
||||
ARMII_AddrModeT2_i7 = 23, // i7 * 1
|
||||
} ARMII_AddrMode;
|
||||
|
||||
inline static const char *ARMII_AddrModeToString(ARMII_AddrMode addrmode)
|
||||
{
|
||||
switch (addrmode) {
|
||||
case ARMII_AddrModeNone:
|
||||
return "AddrModeNone";
|
||||
case ARMII_AddrMode1:
|
||||
return "AddrMode1";
|
||||
case ARMII_AddrMode2:
|
||||
return "AddrMode2";
|
||||
case ARMII_AddrMode3:
|
||||
return "AddrMode3";
|
||||
case ARMII_AddrMode4:
|
||||
return "AddrMode4";
|
||||
case ARMII_AddrMode5:
|
||||
return "AddrMode5";
|
||||
case ARMII_AddrMode5FP16:
|
||||
return "AddrMode5FP16";
|
||||
case ARMII_AddrMode6:
|
||||
return "AddrMode6";
|
||||
case ARMII_AddrModeT1_1:
|
||||
return "AddrModeT1_1";
|
||||
case ARMII_AddrModeT1_2:
|
||||
return "AddrModeT1_2";
|
||||
case ARMII_AddrModeT1_4:
|
||||
return "AddrModeT1_4";
|
||||
case ARMII_AddrModeT1_s:
|
||||
return "AddrModeT1_s";
|
||||
case ARMII_AddrModeT2_i12:
|
||||
return "AddrModeT2_i12";
|
||||
case ARMII_AddrModeT2_i8:
|
||||
return "AddrModeT2_i8";
|
||||
case ARMII_AddrModeT2_i8pos:
|
||||
return "AddrModeT2_i8pos";
|
||||
case ARMII_AddrModeT2_i8neg:
|
||||
return "AddrModeT2_i8neg";
|
||||
case ARMII_AddrModeT2_so:
|
||||
return "AddrModeT2_so";
|
||||
case ARMII_AddrModeT2_pc:
|
||||
return "AddrModeT2_pc";
|
||||
case ARMII_AddrModeT2_i8s4:
|
||||
return "AddrModeT2_i8s4";
|
||||
case ARMII_AddrMode_i12:
|
||||
return "AddrMode_i12";
|
||||
case ARMII_AddrModeT2_ldrex:
|
||||
return "AddrModeT2_ldrex";
|
||||
case ARMII_AddrModeT2_i7s4:
|
||||
return "AddrModeT2_i7s4";
|
||||
case ARMII_AddrModeT2_i7s2:
|
||||
return "AddrModeT2_i7s2";
|
||||
case ARMII_AddrModeT2_i7:
|
||||
return "AddrModeT2_i7";
|
||||
}
|
||||
}
|
||||
|
||||
/// Target Operand Flag enum.
|
||||
typedef enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// ARM Specific MachineOperand flags.
|
||||
|
||||
ARMII_MO_NO_FLAG = 0,
|
||||
|
||||
/// MO_LO16 - On a symbol operand, this represents a relocation containing
|
||||
/// lower 16 bit of the address. Used only via movw instruction.
|
||||
ARMII_MO_LO16 = 0x1,
|
||||
|
||||
/// MO_HI16 - On a symbol operand, this represents a relocation containing
|
||||
/// higher 16 bit of the address. Used only via movt instruction.
|
||||
ARMII_MO_HI16 = 0x2,
|
||||
|
||||
/// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects
|
||||
/// just that part of the flag set.
|
||||
ARMII_MO_OPTION_MASK = 0x3,
|
||||
|
||||
/// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the
|
||||
/// reference is actually to the ".refptr.FOO" symbol. This is used for
|
||||
/// stub symbols on windows.
|
||||
ARMII_MO_COFFSTUB = 0x4,
|
||||
|
||||
/// MO_GOT - On a symbol operand, this represents a GOT relative relocation.
|
||||
ARMII_MO_GOT = 0x8,
|
||||
|
||||
/// MO_SBREL - On a symbol operand, this represents a static base relative
|
||||
/// relocation. Used in movw and movt instructions.
|
||||
ARMII_MO_SBREL = 0x10,
|
||||
|
||||
/// MO_DLLIMPORT - On a symbol operand, this represents that the reference
|
||||
/// to the symbol is for an import stub. This is used for DLL import
|
||||
/// storage class indication on Windows.
|
||||
ARMII_MO_DLLIMPORT = 0x20,
|
||||
|
||||
/// MO_SECREL - On a symbol operand this indicates that the immediate is
|
||||
/// the offset from beginning of section.
|
||||
///
|
||||
/// This is the TLS offset for the COFF/Windows TLS mechanism.
|
||||
ARMII_MO_SECREL = 0x40,
|
||||
|
||||
/// MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it
|
||||
/// represents a symbol which, if indirect, will get special Darwin mangling
|
||||
/// as a non-lazy-ptr indirect symbol (i.e. "L_FOO$non_lazy_ptr"). Can be
|
||||
/// combined with MO_LO16, MO_HI16 or MO_NO_FLAG (in a constant-pool, for
|
||||
/// example).
|
||||
ARMII_MO_NONLAZY = 0x80,
|
||||
|
||||
// It's undefined behaviour if an enum overflows the range between its
|
||||
// smallest and largest values, but since these are |ed together, it can
|
||||
// happen. Put a sentinel in (values of this enum are stored as "unsigned
|
||||
// char").
|
||||
ARMII_MO_UNUSED_MAXIMUM = 0xff
|
||||
} ARMII_TOF;
|
||||
|
||||
enum {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction Flags.
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// This four-bit field describes the addressing mode used.
|
||||
ARMII_AddrModeMask =
|
||||
0x1f, // The AddrMode enums are declared in ARMBaseInfo.h
|
||||
|
||||
// IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
|
||||
// and store ops only. Generic "updating" flag is used for ld/st multiple.
|
||||
// The index mode enums are declared in ARMBaseInfo.h
|
||||
ARMII_IndexModeShift = 5,
|
||||
ARMII_IndexModeMask = 3 << ARMII_IndexModeShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Instruction encoding formats.
|
||||
//
|
||||
ARMII_FormShift = 7,
|
||||
ARMII_FormMask = 0x3f << ARMII_FormShift,
|
||||
|
||||
// Pseudo instructions
|
||||
ARMII_Pseudo = 0 << ARMII_FormShift,
|
||||
|
||||
// Multiply instructions
|
||||
ARMII_MulFrm = 1 << ARMII_FormShift,
|
||||
|
||||
// Branch instructions
|
||||
ARMII_BrFrm = 2 << ARMII_FormShift,
|
||||
ARMII_BrMiscFrm = 3 << ARMII_FormShift,
|
||||
|
||||
// Data Processing instructions
|
||||
ARMII_DPFrm = 4 << ARMII_FormShift,
|
||||
ARMII_DPSoRegFrm = 5 << ARMII_FormShift,
|
||||
|
||||
// Load and Store
|
||||
ARMII_LdFrm = 6 << ARMII_FormShift,
|
||||
ARMII_StFrm = 7 << ARMII_FormShift,
|
||||
ARMII_LdMiscFrm = 8 << ARMII_FormShift,
|
||||
ARMII_StMiscFrm = 9 << ARMII_FormShift,
|
||||
ARMII_LdStMulFrm = 10 << ARMII_FormShift,
|
||||
|
||||
ARMII_LdStExFrm = 11 << ARMII_FormShift,
|
||||
|
||||
// Miscellaneous arithmetic instructions
|
||||
ARMII_ArithMiscFrm = 12 << ARMII_FormShift,
|
||||
ARMII_SatFrm = 13 << ARMII_FormShift,
|
||||
|
||||
// Extend instructions
|
||||
ARMII_ExtFrm = 14 << ARMII_FormShift,
|
||||
|
||||
// VFP formats
|
||||
ARMII_VFPUnaryFrm = 15 << ARMII_FormShift,
|
||||
ARMII_VFPBinaryFrm = 16 << ARMII_FormShift,
|
||||
ARMII_VFPConv1Frm = 17 << ARMII_FormShift,
|
||||
ARMII_VFPConv2Frm = 18 << ARMII_FormShift,
|
||||
ARMII_VFPConv3Frm = 19 << ARMII_FormShift,
|
||||
ARMII_VFPConv4Frm = 20 << ARMII_FormShift,
|
||||
ARMII_VFPConv5Frm = 21 << ARMII_FormShift,
|
||||
ARMII_VFPLdStFrm = 22 << ARMII_FormShift,
|
||||
ARMII_VFPLdStMulFrm = 23 << ARMII_FormShift,
|
||||
ARMII_VFPMiscFrm = 24 << ARMII_FormShift,
|
||||
|
||||
// Thumb format
|
||||
ARMII_ThumbFrm = 25 << ARMII_FormShift,
|
||||
|
||||
// Miscelleaneous format
|
||||
ARMII_MiscFrm = 26 << ARMII_FormShift,
|
||||
|
||||
// NEON formats
|
||||
ARMII_NGetLnFrm = 27 << ARMII_FormShift,
|
||||
ARMII_NSetLnFrm = 28 << ARMII_FormShift,
|
||||
ARMII_NDupFrm = 29 << ARMII_FormShift,
|
||||
ARMII_NLdStFrm = 30 << ARMII_FormShift,
|
||||
ARMII_N1RegModImmFrm = 31 << ARMII_FormShift,
|
||||
ARMII_N2RegFrm = 32 << ARMII_FormShift,
|
||||
ARMII_NVCVTFrm = 33 << ARMII_FormShift,
|
||||
ARMII_NVDupLnFrm = 34 << ARMII_FormShift,
|
||||
ARMII_N2RegVShLFrm = 35 << ARMII_FormShift,
|
||||
ARMII_N2RegVShRFrm = 36 << ARMII_FormShift,
|
||||
ARMII_N3RegFrm = 37 << ARMII_FormShift,
|
||||
ARMII_N3RegVShFrm = 38 << ARMII_FormShift,
|
||||
ARMII_NVExtFrm = 39 << ARMII_FormShift,
|
||||
ARMII_NVMulSLFrm = 40 << ARMII_FormShift,
|
||||
ARMII_NVTBLFrm = 41 << ARMII_FormShift,
|
||||
ARMII_N3RegCplxFrm = 43 << ARMII_FormShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Misc flags.
|
||||
|
||||
// UnaryDP - Indicates this is a unary data processing instruction, i.e.
|
||||
// it doesn't have a Rn operand.
|
||||
ARMII_UnaryDP = 1 << 13,
|
||||
|
||||
// Xform16Bit - Indicates this Thumb2 instruction may be transformed into
|
||||
// a 16-bit Thumb instruction if certain conditions are met.
|
||||
ARMII_Xform16Bit = 1 << 14,
|
||||
|
||||
// ThumbArithFlagSetting - The instruction is a 16-bit flag setting Thumb
|
||||
// instruction. Used by the parser to determine whether to require the 'S'
|
||||
// suffix on the mnemonic (when not in an IT block) or preclude it (when
|
||||
// in an IT block).
|
||||
ARMII_ThumbArithFlagSetting = 1 << 19,
|
||||
|
||||
// Whether an instruction can be included in an MVE tail-predicated loop,
|
||||
// though extra validity checks may need to be performed too.
|
||||
ARMII_ValidForTailPredication = 1 << 20,
|
||||
|
||||
// Whether an instruction writes to the top/bottom half of a vector element
|
||||
// and leaves the other half untouched.
|
||||
ARMII_RetainsPreviousHalfElement = 1 << 21,
|
||||
|
||||
// Whether the instruction produces a scalar result from vector operands.
|
||||
ARMII_HorizontalReduction = 1 << 22,
|
||||
|
||||
// Whether this instruction produces a vector result that is larger than
|
||||
// its input, typically reading from the top/bottom halves of the input(s).
|
||||
ARMII_DoubleWidthResult = 1 << 23,
|
||||
|
||||
// The vector element size for MVE instructions. 00 = i8, 01 = i16, 10 = i32
|
||||
// and 11 = i64. This is the largest type if multiple are present, so a
|
||||
// MVE_VMOVLs8bh is ize 01=i16, as it extends from a i8 to a i16. There are
|
||||
// some caveats so cannot be used blindly, such as exchanging VMLADAVA's and
|
||||
// complex instructions, which may use different input lanes.
|
||||
ARMII_VecSizeShift = 24,
|
||||
ARMII_VecSize = 3 << ARMII_VecSizeShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Code domain.
|
||||
ARMII_DomainShift = 15,
|
||||
ARMII_DomainMask = 15 << ARMII_DomainShift,
|
||||
ARMII_DomainGeneral = 0 << ARMII_DomainShift,
|
||||
ARMII_DomainVFP = 1 << ARMII_DomainShift,
|
||||
ARMII_DomainNEON = 2 << ARMII_DomainShift,
|
||||
ARMII_DomainNEONA8 = 4 << ARMII_DomainShift,
|
||||
ARMII_DomainMVE = 8 << ARMII_DomainShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Field shifts - such shifts are used to set field while generating
|
||||
// machine instructions.
|
||||
//
|
||||
// FIXME: This list will need adjusting/fixing as the MC code emitter
|
||||
// takes shape and the ARMCodeEmitter.cpp bits go away.
|
||||
ARMII_ShiftTypeShift = 4,
|
||||
|
||||
ARMII_M_BitShift = 5,
|
||||
ARMII_ShiftImmShift = 5,
|
||||
ARMII_ShiftShift = 7,
|
||||
ARMII_N_BitShift = 7,
|
||||
ARMII_ImmHiShift = 8,
|
||||
ARMII_SoRotImmShift = 8,
|
||||
ARMII_RegRsShift = 8,
|
||||
ARMII_ExtRotImmShift = 10,
|
||||
ARMII_RegRdLoShift = 12,
|
||||
ARMII_RegRdShift = 12,
|
||||
ARMII_RegRdHiShift = 16,
|
||||
ARMII_RegRnShift = 16,
|
||||
ARMII_S_BitShift = 20,
|
||||
ARMII_W_BitShift = 21,
|
||||
ARMII_AM3_I_BitShift = 22,
|
||||
ARMII_D_BitShift = 22,
|
||||
ARMII_U_BitShift = 23,
|
||||
ARMII_P_BitShift = 24,
|
||||
ARMII_I_BitShift = 25,
|
||||
ARMII_CondShift = 28
|
||||
};
|
||||
|
||||
const char *get_pred_mask(ARM_PredBlockMask pred_mask);
|
||||
|
||||
#endif // CS_ARM_BASEINFO_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user