mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-16 20:17:05 +03:00
[abi] Added support for 32-bit ARM (WIP)
This commit is contained in:
@@ -70,6 +70,7 @@ option(ASMJIT_NO_CUSTOM_FLAGS "Disable extra compilation flags added by AsmJit
|
||||
option(ASMJIT_NO_ABI_NAMESPACE "Disable the use of inline ABI namespace {asmjit::v...}" OFF)
|
||||
option(ASMJIT_NO_SHM_OPEN "Disable the use of shm_open() (some platforms have better options)" OFF)
|
||||
option(ASMJIT_NO_X86 "Disable X86/X64 backend" OFF)
|
||||
option(ASMJIT_NO_AARCH32 "Disable AArch32 backend" OFF)
|
||||
option(ASMJIT_NO_AARCH64 "Disable AArch64 backend" OFF)
|
||||
option(ASMJIT_NO_FOREIGN "Disable all foreign backends (enables only a backend that matches the target)" OFF)
|
||||
option(ASMJIT_NO_JIT "Disable VirtMem, JitAllocator, and JitRuntime at build time" OFF)
|
||||
@@ -219,12 +220,29 @@ set(ASMJIT_SRC
|
||||
asmjit/support/support.h
|
||||
asmjit/support/support_p.h
|
||||
|
||||
asmjit/a32.h
|
||||
asmjit/a64.h
|
||||
asmjit/arm.h
|
||||
asmjit/arm/armformatter.cpp
|
||||
asmjit/arm/armformatter_p.h
|
||||
asmjit/arm/armglobals.h
|
||||
asmjit/arm/armutils.h
|
||||
asmjit/arm/a32archtraits_p.h
|
||||
asmjit/arm/a32assembler.cpp
|
||||
asmjit/arm/a32assembler.h
|
||||
asmjit/arm/a32builder.cpp
|
||||
asmjit/arm/a32builder.h
|
||||
asmjit/arm/a32emithelper.cpp
|
||||
asmjit/arm/a32emithelper_p.h
|
||||
asmjit/arm/a32emitter.h
|
||||
asmjit/arm/a32formatter.cpp
|
||||
asmjit/arm/a32formatter_p.h
|
||||
asmjit/arm/a32globals.h
|
||||
asmjit/arm/a32instapi.cpp
|
||||
asmjit/arm/a32instapi_p.h
|
||||
asmjit/arm/a32instdb.cpp
|
||||
asmjit/arm/a32instdb_p.h
|
||||
asmjit/arm/a32operand.h
|
||||
asmjit/arm/a64archtraits_p.h
|
||||
asmjit/arm/a64assembler.cpp
|
||||
asmjit/arm/a64assembler.h
|
||||
@@ -504,6 +522,7 @@ if (ASMJIT_NO_SHM_OPEN)
|
||||
endif()
|
||||
|
||||
foreach(build_option ASMJIT_NO_X86
|
||||
ASMJIT_NO_AARCH32
|
||||
ASMJIT_NO_AARCH64
|
||||
ASMJIT_NO_FOREIGN
|
||||
ASMJIT_NO_ABI_NAMESPACE
|
||||
@@ -613,6 +632,7 @@ else()
|
||||
asmjit_add_target(asmjit_test_assembler TEST
|
||||
SOURCES asmjit-testing/tests/asmjit_test_assembler.cpp
|
||||
asmjit-testing/tests/asmjit_test_assembler.h
|
||||
asmjit-testing/tests/asmjit_test_assembler_a32.cpp
|
||||
asmjit-testing/tests/asmjit_test_assembler_a64.cpp
|
||||
asmjit-testing/tests/asmjit_test_assembler_x64.cpp
|
||||
asmjit-testing/tests/asmjit_test_assembler_x86.cpp
|
||||
@@ -689,6 +709,7 @@ else()
|
||||
|
||||
asmjit_add_target(asmjit_bench_codegen EXECUTABLE
|
||||
SOURCES asmjit-testing/bench/asmjit_bench_codegen.cpp
|
||||
asmjit-testing/bench/asmjit_bench_codegen_a32.cpp
|
||||
asmjit-testing/bench/asmjit_bench_codegen_a64.cpp
|
||||
asmjit-testing/bench/asmjit_bench_codegen_x86.cpp
|
||||
SOURCES asmjit-testing/bench/asmjit_bench_codegen.h
|
||||
|
||||
@@ -28,6 +28,10 @@ static void print_app_info() noexcept {
|
||||
void benchmark_x86_emitters(uint32_t num_iterations, bool test_x86, bool test_x64) noexcept;
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
void benchmark_aarch32_emitters(uint32_t num_iterations);
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
void benchmark_aarch64_emitters(uint32_t num_iterations);
|
||||
#endif
|
||||
@@ -49,6 +53,9 @@ int main(int argc, char* argv[]) {
|
||||
printf(" --arch=x86 32-bit X86 architecture (X86)\n");
|
||||
printf(" --arch=x64 64-bit X86 architecture (X86_64)\n");
|
||||
#endif
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
printf(" --arch=aarch32 32-bit ARM architecture (AArch32)\n");
|
||||
#endif
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
printf(" --arch=aarch64 64-bit ARM architecture (AArch64)\n");
|
||||
#endif
|
||||
@@ -71,6 +78,14 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
bool test_aarch32 = strcmp(arch, "all") == 0 || strcmp(arch, "aarch32") == 0;
|
||||
|
||||
if (test_aarch32) {
|
||||
benchmark_aarch32_emitters(num_iterations);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
bool test_aarch64 = strcmp(arch, "all") == 0 || strcmp(arch, "aarch64") == 0;
|
||||
|
||||
|
||||
23
asmjit-testing/bench/asmjit_bench_codegen_a32.cpp
Normal file
23
asmjit-testing/bench/asmjit_bench_codegen_a32.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See <asmjit/core.h> or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core.h>
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
#include <asmjit/a32.h>
|
||||
|
||||
#include <limits>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <asmjit-testing/bench/asmjit_bench_codegen.h>
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
void benchmark_aarch32_emitters(uint32_t num_iterations) {
|
||||
Support::maybe_unused(num_iterations);
|
||||
}
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32
|
||||
@@ -20,6 +20,10 @@ bool test_x86_assembler(const TestSettings& settings) noexcept;
|
||||
bool test_x64_assembler(const TestSettings& settings) noexcept;
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
bool test_aarch32_assembler(const TestSettings& settings) noexcept;
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
bool test_aarch64_assembler(const TestSettings& settings) noexcept;
|
||||
#endif
|
||||
@@ -47,6 +51,9 @@ static void print_app_usage(const TestSettings& settings) noexcept {
|
||||
printf(" --arch=x86 32-bit X86 architecture (X86)\n");
|
||||
printf(" --arch=x64 64-bit X86 architecture (X86_64)\n");
|
||||
#endif
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
printf(" --arch=aarch32 32-bit ARM architecture (AArch32)\n");
|
||||
#endif
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
printf(" --arch=aarch64 64-bit ARM architecture (AArch64)\n");
|
||||
#endif
|
||||
@@ -68,34 +75,52 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
const char* arch = cmd_line.value_of("--arch", "all");
|
||||
|
||||
bool x86_failed = false;
|
||||
bool x64_failed = false;
|
||||
bool aarch32_failed = false;
|
||||
bool aarch64_failed = false;
|
||||
|
||||
#if !defined(ASMJIT_NO_X86)
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "x86") == 0))
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "x86") == 0)) {
|
||||
x86_failed = !test_x86_assembler(settings);
|
||||
}
|
||||
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "x64") == 0))
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "x64") == 0)) {
|
||||
x64_failed = !test_x64_assembler(settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "aarch32") == 0)) {
|
||||
aarch32_failed = !test_aarch32_assembler(settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "aarch64") == 0))
|
||||
if ((strcmp(arch, "all") == 0 || strcmp(arch, "aarch64") == 0)) {
|
||||
aarch64_failed = !test_aarch64_assembler(settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool failed = x86_failed || x64_failed || aarch64_failed;
|
||||
bool failed = x86_failed || x64_failed || aarch32_failed || aarch64_failed;
|
||||
|
||||
if (failed) {
|
||||
if (x86_failed)
|
||||
if (x86_failed) {
|
||||
printf("** X86 test suite failed **\n");
|
||||
}
|
||||
|
||||
if (x64_failed)
|
||||
if (x64_failed) {
|
||||
printf("** X64 test suite failed **\n");
|
||||
}
|
||||
|
||||
if (aarch64_failed)
|
||||
if (aarch32_failed) {
|
||||
printf("** AArch32 test suite failed **\n");
|
||||
}
|
||||
|
||||
if (aarch64_failed) {
|
||||
printf("** AArch64 test suite failed **\n");
|
||||
}
|
||||
|
||||
printf("** FAILURE **\n");
|
||||
}
|
||||
|
||||
2881
asmjit-testing/tests/asmjit_test_assembler_a32.cpp
Normal file
2881
asmjit-testing/tests/asmjit_test_assembler_a32.cpp
Normal file
File diff suppressed because it is too large
Load Diff
638
asmjit-testing/tests/asmjit_test_perf_a32.cpp
Normal file
638
asmjit-testing/tests/asmjit_test_perf_a32.cpp
Normal file
@@ -0,0 +1,638 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core.h>
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
#include <asmjit/a32.h>
|
||||
|
||||
#include <asmjit-testing/commons/asmjit_test_perf.h.
|
||||
|
||||
#include <limits>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
// Generates a long sequence of GP instructions.
|
||||
template<typename Emitter>
|
||||
static void generateGpSequenceInternal(
|
||||
Emitter& cc,
|
||||
const a32::Gp& a, const a32::Gp& b, const a32::Gp& c, const a32::Gp& d) {
|
||||
|
||||
using namespace asmjit::a32;
|
||||
|
||||
cc.mov(a, 0);
|
||||
cc.mov(b, 1);
|
||||
cc.mov(c, 2);
|
||||
cc.mov(d, 3);
|
||||
|
||||
cc.adc(a, b, c, lsl(d));
|
||||
cc.adc(a, b, c, lsr(d));
|
||||
cc.adc(a, b, c, asr(d));
|
||||
cc.adc(a, b, c, ror(d));
|
||||
cc.adc(a, b, c, lsl(8));
|
||||
cc.adc(a, b, c, lsr(8));
|
||||
cc.adc(a, b, c, asr(8));
|
||||
cc.adc(a, b, c, ror(8));
|
||||
cc.adc(a, b, 0xFF);
|
||||
cc.adc(a, b, 0xFF00);
|
||||
cc.adc(a, b, 0xFF000000);
|
||||
cc.adc(a, b, 0xF000000F);
|
||||
cc.adcs(a, b, c, lsl(d));
|
||||
cc.adcs(a, b, c, lsr(d));
|
||||
cc.adcs(a, b, c, asr(d));
|
||||
cc.adcs(a, b, c, ror(d));
|
||||
cc.adcs(a, b, c, lsl(8));
|
||||
cc.adcs(a, b, c, lsr(8));
|
||||
cc.adcs(a, b, c, asr(8));
|
||||
cc.adcs(a, b, c, ror(8));
|
||||
cc.adcs(a, b, 0xFF);
|
||||
cc.adcs(a, b, 0xFF00);
|
||||
cc.adcs(a, b, 0xFF000000);
|
||||
cc.adcs(a, b, 0xF000000F);
|
||||
cc.add(a, b, c, lsl(d));
|
||||
cc.add(a, b, c, lsr(d));
|
||||
cc.add(a, b, c, asr(d));
|
||||
cc.add(a, b, c, ror(d));
|
||||
cc.add(a, b, c, lsl(8));
|
||||
cc.add(a, b, c, lsr(8));
|
||||
cc.add(a, b, c, asr(8));
|
||||
cc.add(a, b, c, ror(8));
|
||||
cc.add(a, b, 0xFF);
|
||||
cc.add(a, b, 0xFF00);
|
||||
cc.add(a, b, 0xFF000000);
|
||||
cc.add(a, b, 0xF000000F);
|
||||
cc.adds(a, b, c, lsl(d));
|
||||
cc.adds(a, b, c, lsr(d));
|
||||
cc.adds(a, b, c, asr(d));
|
||||
cc.adds(a, b, c, ror(d));
|
||||
cc.adds(a, b, c, lsl(8));
|
||||
cc.adds(a, b, c, lsr(8));
|
||||
cc.adds(a, b, c, asr(8));
|
||||
cc.adds(a, b, c, ror(8));
|
||||
cc.adds(a, b, 0xFF);
|
||||
cc.adds(a, b, 0xFF00);
|
||||
cc.adds(a, b, 0xFF000000);
|
||||
cc.adds(a, b, 0xF000000F);
|
||||
cc.and_(a, b, c, lsl(d));
|
||||
cc.and_(a, b, c, lsr(d));
|
||||
cc.and_(a, b, c, asr(d));
|
||||
cc.and_(a, b, c, ror(d));
|
||||
cc.and_(a, b, c, lsl(8));
|
||||
cc.and_(a, b, c, lsr(8));
|
||||
cc.and_(a, b, c, asr(8));
|
||||
cc.and_(a, b, c, ror(8));
|
||||
cc.and_(a, b, 0xFF);
|
||||
cc.and_(a, b, 0xFF00);
|
||||
cc.and_(a, b, 0xFF000000);
|
||||
cc.and_(a, b, 0xF000000F);
|
||||
cc.ands(a, b, c, lsl(d));
|
||||
cc.ands(a, b, c, lsr(d));
|
||||
cc.ands(a, b, c, asr(d));
|
||||
cc.ands(a, b, c, ror(d));
|
||||
cc.ands(a, b, c, lsl(8));
|
||||
cc.ands(a, b, c, lsr(8));
|
||||
cc.ands(a, b, c, asr(8));
|
||||
cc.ands(a, b, c, ror(8));
|
||||
cc.ands(a, b, 0xFF);
|
||||
cc.ands(a, b, 0xFF00);
|
||||
cc.ands(a, b, 0xFF000000);
|
||||
cc.ands(a, b, 0xF000000F);
|
||||
cc.asr(a, b, c);
|
||||
cc.asr(a, b, 3);
|
||||
cc.asrs(a, b, c);
|
||||
cc.asrs(a, b, 3);
|
||||
cc.bfc(a, 3, 5);
|
||||
cc.bfi(a, b, 3, 5);
|
||||
cc.bic(a, b, c, lsl(d));
|
||||
cc.bic(a, b, c, lsr(d));
|
||||
cc.bic(a, b, c, asr(d));
|
||||
cc.bic(a, b, c, ror(d));
|
||||
cc.bic(a, b, c, lsl(8));
|
||||
cc.bic(a, b, c, lsr(8));
|
||||
cc.bic(a, b, c, asr(8));
|
||||
cc.bic(a, b, c, ror(8));
|
||||
cc.bic(a, b, 0xFF);
|
||||
cc.bic(a, b, 0xFF00);
|
||||
cc.bic(a, b, 0xFF000000);
|
||||
cc.bic(a, b, 0xF000000F);
|
||||
cc.bics(a, b, c, lsl(d));
|
||||
cc.bics(a, b, c, lsr(d));
|
||||
cc.bics(a, b, c, asr(d));
|
||||
cc.bics(a, b, c, ror(d));
|
||||
cc.bics(a, b, c, lsl(8));
|
||||
cc.bics(a, b, c, lsr(8));
|
||||
cc.bics(a, b, c, asr(8));
|
||||
cc.bics(a, b, c, ror(8));
|
||||
cc.bics(a, b, 0xFF);
|
||||
cc.bics(a, b, 0xFF00);
|
||||
cc.bics(a, b, 0xFF000000);
|
||||
cc.bics(a, b, 0xF000000F);
|
||||
cc.clz(a, b);
|
||||
cc.cmn(a, b, lsl(c));
|
||||
cc.cmn(a, b, lsr(c));
|
||||
cc.cmn(a, b, asr(c));
|
||||
cc.cmn(a, b, ror(c));
|
||||
cc.cmn(a, b, lsl(8));
|
||||
cc.cmn(a, b, lsr(8));
|
||||
cc.cmn(a, b, asr(8));
|
||||
cc.cmn(a, b, ror(8));
|
||||
cc.cmn(a, 0xFF);
|
||||
cc.cmn(a, 0xFF00);
|
||||
cc.cmn(a, 0xFF000000);
|
||||
cc.cmn(a, 0xF000000F);
|
||||
cc.cmp(a, b, lsl(c));
|
||||
cc.cmp(a, b, lsr(c));
|
||||
cc.cmp(a, b, asr(c));
|
||||
cc.cmp(a, b, ror(c));
|
||||
cc.cmp(a, b, lsl(8));
|
||||
cc.cmp(a, b, lsr(8));
|
||||
cc.cmp(a, b, asr(8));
|
||||
cc.cmp(a, b, ror(8));
|
||||
cc.cmp(a, 0xFF);
|
||||
cc.cmp(a, 0xFF00);
|
||||
cc.cmp(a, 0xFF000000);
|
||||
cc.cmp(a, 0xF000000F);
|
||||
cc.crc32b(a, b, c);
|
||||
cc.crc32cb(a, b, c);
|
||||
cc.crc32ch(a, b, c);
|
||||
cc.crc32cw(a, b, c);
|
||||
cc.crc32h(a, b, c);
|
||||
cc.crc32w(a, b, c);
|
||||
cc.eor(a, b, c, lsl(d));
|
||||
cc.eor(a, b, c, lsr(d));
|
||||
cc.eor(a, b, c, asr(d));
|
||||
cc.eor(a, b, c, ror(d));
|
||||
cc.eor(a, b, c, lsl(8));
|
||||
cc.eor(a, b, c, lsr(8));
|
||||
cc.eor(a, b, c, asr(8));
|
||||
cc.eor(a, b, c, ror(8));
|
||||
cc.eor(a, b, 0xFF);
|
||||
cc.eor(a, b, 0xFF00);
|
||||
cc.eor(a, b, 0xFF000000);
|
||||
cc.eor(a, b, 0xF000000F);
|
||||
cc.eors(a, b, c, lsl(d));
|
||||
cc.eors(a, b, c, lsr(d));
|
||||
cc.eors(a, b, c, asr(d));
|
||||
cc.eors(a, b, c, ror(d));
|
||||
cc.eors(a, b, c, lsl(8));
|
||||
cc.eors(a, b, c, lsr(8));
|
||||
cc.eors(a, b, c, asr(8));
|
||||
cc.eors(a, b, c, ror(8));
|
||||
cc.eors(a, b, 0xFF);
|
||||
cc.eors(a, b, 0xFF00);
|
||||
cc.eors(a, b, 0xFF000000);
|
||||
cc.eors(a, b, 0xF000000F);
|
||||
cc.ldr(a, ptr(b, c));
|
||||
cc.ldr(a, ptr_pre(b, c));
|
||||
cc.ldr(a, ptr_post(b, c));
|
||||
cc.ldr(a, ptr(b, 4));
|
||||
cc.ldr(a, ptr_pre(b, 4));
|
||||
cc.ldr(a, ptr_post(b, 4));
|
||||
cc.ldrb(a, ptr(b, c));
|
||||
cc.ldrb(a, ptr_pre(b, c));
|
||||
cc.ldrb(a, ptr_post(b, c));
|
||||
cc.ldrb(a, ptr(b, 4));
|
||||
cc.ldrb(a, ptr_pre(b, 4));
|
||||
cc.ldrb(a, ptr_post(b, 4));
|
||||
cc.ldrbt(a, ptr_post(b, c));
|
||||
cc.ldrbt(a, ptr_post(b, 4));
|
||||
cc.ldrh(a, ptr(b, c));
|
||||
cc.ldrh(a, ptr_pre(b, c));
|
||||
cc.ldrh(a, ptr_post(b, c));
|
||||
cc.ldrh(a, ptr(b, 4));
|
||||
cc.ldrh(a, ptr_pre(b, 4));
|
||||
cc.ldrh(a, ptr_post(b, 4));
|
||||
cc.ldrht(a, ptr_post(b, c));
|
||||
cc.ldrht(a, ptr_post(b, 4));
|
||||
cc.ldrsb(a, ptr(b, c));
|
||||
cc.ldrsb(a, ptr_pre(b, c));
|
||||
cc.ldrsb(a, ptr_post(b, c));
|
||||
cc.ldrsb(a, ptr(b, 4));
|
||||
cc.ldrsb(a, ptr_pre(b, 4));
|
||||
cc.ldrsb(a, ptr_post(b, 4));
|
||||
cc.ldrsbt(a, ptr_post(b, c));
|
||||
cc.ldrsbt(a, ptr_post(b, 4));
|
||||
cc.ldrsh(a, ptr(b, c));
|
||||
cc.ldrsh(a, ptr_pre(b, c));
|
||||
cc.ldrsh(a, ptr_post(b, c));
|
||||
cc.ldrsh(a, ptr(b, 4));
|
||||
cc.ldrsh(a, ptr_pre(b, 4));
|
||||
cc.ldrsh(a, ptr_post(b, 4));
|
||||
cc.ldrsht(a, ptr_post(b, 4));
|
||||
cc.ldrsht(a, ptr_post(b, c));
|
||||
cc.ldrt(a, ptr_post(b, c));
|
||||
cc.ldrt(a, ptr_post(b, 4));
|
||||
cc.lsl(a, b, 3);
|
||||
cc.lsl(a, b, c);
|
||||
cc.lsls(a, b, 3);
|
||||
cc.lsls(a, b, c);
|
||||
cc.lsr(a, b, 3);
|
||||
cc.lsr(a, b, c);
|
||||
cc.lsrs(a, b, 3);
|
||||
cc.lsrs(a, b, c);
|
||||
cc.mla(a, b, c, d);
|
||||
cc.mlas(a, b, c, d);
|
||||
cc.mls(a, b, c, d);
|
||||
cc.mov(a, b, lsl(c));
|
||||
cc.mov(a, b, lsr(c));
|
||||
cc.mov(a, b, asr(c));
|
||||
cc.mov(a, b, ror(c));
|
||||
cc.mov(a, b, lsl(8));
|
||||
cc.mov(a, b, lsr(8));
|
||||
cc.mov(a, b, asr(8));
|
||||
cc.mov(a, b, ror(8));
|
||||
cc.mov(a, 0xFF);
|
||||
cc.mov(a, 0xFF00);
|
||||
cc.mov(a, 0xFF000000);
|
||||
cc.mov(a, 0xF000000F);
|
||||
cc.movs(a, b, lsl(c));
|
||||
cc.movs(a, b, lsr(c));
|
||||
cc.movs(a, b, asr(c));
|
||||
cc.movs(a, b, ror(c));
|
||||
cc.movs(a, b, lsl(8));
|
||||
cc.movs(a, b, lsr(8));
|
||||
cc.movs(a, b, asr(8));
|
||||
cc.movs(a, b, ror(8));
|
||||
cc.movs(a, 0xFF);
|
||||
cc.movs(a, 0xFF00);
|
||||
cc.movs(a, 0xFF000000);
|
||||
cc.movs(a, 0xF000000F);
|
||||
cc.movt(a, 1);
|
||||
cc.movw(a, 1);
|
||||
cc.mul(a, b, c);
|
||||
cc.muls(a, b, c);
|
||||
cc.mvn(a, b, lsl(c));
|
||||
cc.mvn(a, b, lsr(c));
|
||||
cc.mvn(a, b, asr(c));
|
||||
cc.mvn(a, b, ror(c));
|
||||
cc.mvn(a, b, lsl(8));
|
||||
cc.mvn(a, b, lsr(8));
|
||||
cc.mvn(a, b, asr(8));
|
||||
cc.mvn(a, b, ror(8));
|
||||
cc.mvn(a, 0xFF);
|
||||
cc.mvn(a, 0xFF00);
|
||||
cc.mvn(a, 0xFF000000);
|
||||
cc.mvn(a, 0xF000000F);
|
||||
cc.mvns(a, b, lsl(c));
|
||||
cc.mvns(a, b, lsr(c));
|
||||
cc.mvns(a, b, asr(c));
|
||||
cc.mvns(a, b, ror(c));
|
||||
cc.mvns(a, b, lsl(8));
|
||||
cc.mvns(a, b, lsr(8));
|
||||
cc.mvns(a, b, asr(8));
|
||||
cc.mvns(a, b, ror(8));
|
||||
cc.mvns(a, 0xFF);
|
||||
cc.mvns(a, 0xFF00);
|
||||
cc.mvns(a, 0xFF000000);
|
||||
cc.mvns(a, 0xF000000F);
|
||||
cc.orr(a, b, c, lsl(d));
|
||||
cc.orr(a, b, c, lsr(d));
|
||||
cc.orr(a, b, c, asr(d));
|
||||
cc.orr(a, b, c, ror(d));
|
||||
cc.orr(a, b, c, lsl(8));
|
||||
cc.orr(a, b, c, lsr(8));
|
||||
cc.orr(a, b, c, asr(8));
|
||||
cc.orr(a, b, c, ror(8));
|
||||
cc.orr(a, b, 0xFF);
|
||||
cc.orr(a, b, 0xFF00);
|
||||
cc.orr(a, b, 0xFF000000);
|
||||
cc.orr(a, b, 0xF000000F);
|
||||
cc.orrs(a, b, c, lsl(d));
|
||||
cc.orrs(a, b, c, lsr(d));
|
||||
cc.orrs(a, b, c, asr(d));
|
||||
cc.orrs(a, b, c, ror(d));
|
||||
cc.orrs(a, b, c, lsl(8));
|
||||
cc.orrs(a, b, c, lsr(8));
|
||||
cc.orrs(a, b, c, asr(8));
|
||||
cc.orrs(a, b, c, ror(8));
|
||||
cc.orrs(a, b, 0xFF);
|
||||
cc.orrs(a, b, 0xFF00);
|
||||
cc.orrs(a, b, 0xFF000000);
|
||||
cc.orrs(a, b, 0xF000000F);
|
||||
cc.pkhbt(a, b, c, lsl(8));
|
||||
cc.pkhtb(a, b, c, asr(8));
|
||||
cc.qadd(a, b, c);
|
||||
cc.qadd16(a, b, c);
|
||||
cc.qadd8(a, b, c);
|
||||
cc.qasx(a, b, c);
|
||||
cc.qdadd(a, b, c);
|
||||
cc.qdsub(a, b, c);
|
||||
cc.qsax(a, b, c);
|
||||
cc.qsub(a, b, c);
|
||||
cc.qsub16(a, b, c);
|
||||
cc.qsub8(a, b, c);
|
||||
cc.rbit(a, b);
|
||||
cc.rev(a, b);
|
||||
cc.rev16(a, b);
|
||||
cc.revsh(a, b);
|
||||
cc.ror(a, b, 3);
|
||||
cc.ror(a, b, c);
|
||||
cc.rors(a, b, 3);
|
||||
cc.rors(a, b, c);
|
||||
cc.rrx(a, b);
|
||||
cc.rrxs(a, b);
|
||||
cc.rsb(a, b, c, lsl(d));
|
||||
cc.rsb(a, b, c, lsr(d));
|
||||
cc.rsb(a, b, c, asr(d));
|
||||
cc.rsb(a, b, c, ror(d));
|
||||
cc.rsb(a, b, c, lsl(8));
|
||||
cc.rsb(a, b, c, lsr(8));
|
||||
cc.rsb(a, b, c, asr(8));
|
||||
cc.rsb(a, b, c, ror(8));
|
||||
cc.rsb(a, b, 0xFF);
|
||||
cc.rsb(a, b, 0xFF00);
|
||||
cc.rsb(a, b, 0xFF000000);
|
||||
cc.rsb(a, b, 0xF000000F);
|
||||
cc.rsbs(a, b, c, lsl(d));
|
||||
cc.rsbs(a, b, c, lsr(d));
|
||||
cc.rsbs(a, b, c, asr(d));
|
||||
cc.rsbs(a, b, c, ror(d));
|
||||
cc.rsbs(a, b, c, lsl(8));
|
||||
cc.rsbs(a, b, c, lsr(8));
|
||||
cc.rsbs(a, b, c, asr(8));
|
||||
cc.rsbs(a, b, c, ror(8));
|
||||
cc.rsbs(a, b, 0xFF);
|
||||
cc.rsbs(a, b, 0xFF00);
|
||||
cc.rsbs(a, b, 0xFF000000);
|
||||
cc.rsbs(a, b, 0xF000000F);
|
||||
cc.rsc(a, b, c, lsl(d));
|
||||
cc.rsc(a, b, c, lsr(d));
|
||||
cc.rsc(a, b, c, asr(d));
|
||||
cc.rsc(a, b, c, ror(d));
|
||||
cc.rsc(a, b, c, lsl(8));
|
||||
cc.rsc(a, b, c, lsr(8));
|
||||
cc.rsc(a, b, c, asr(8));
|
||||
cc.rsc(a, b, c, ror(8));
|
||||
cc.rsc(a, b, 0xFF);
|
||||
cc.rsc(a, b, 0xFF00);
|
||||
cc.rsc(a, b, 0xFF000000);
|
||||
cc.rsc(a, b, 0xF000000F);
|
||||
cc.rscs(a, b, c, lsl(d));
|
||||
cc.rscs(a, b, c, lsr(d));
|
||||
cc.rscs(a, b, c, asr(d));
|
||||
cc.rscs(a, b, c, ror(d));
|
||||
cc.rscs(a, b, c, lsl(8));
|
||||
cc.rscs(a, b, c, lsr(8));
|
||||
cc.rscs(a, b, c, asr(8));
|
||||
cc.rscs(a, b, c, ror(8));
|
||||
cc.rscs(a, b, 0xFF);
|
||||
cc.rscs(a, b, 0xFF00);
|
||||
cc.rscs(a, b, 0xFF000000);
|
||||
cc.rscs(a, b, 0xF000000F);
|
||||
cc.sadd16(a, b, c);
|
||||
cc.sadd8(a, b, c);
|
||||
cc.sasx(a, b, c);
|
||||
cc.sbc(a, b, c, lsl(d));
|
||||
cc.sbc(a, b, c, lsr(d));
|
||||
cc.sbc(a, b, c, asr(d));
|
||||
cc.sbc(a, b, c, ror(d));
|
||||
cc.sbc(a, b, c, lsl(8));
|
||||
cc.sbc(a, b, c, lsr(8));
|
||||
cc.sbc(a, b, c, asr(8));
|
||||
cc.sbc(a, b, c, ror(8));
|
||||
cc.sbc(a, b, 0xFF);
|
||||
cc.sbc(a, b, 0xFF00);
|
||||
cc.sbc(a, b, 0xFF000000);
|
||||
cc.sbc(a, b, 0xF000000F);
|
||||
cc.sbcs(a, b, c, lsl(d));
|
||||
cc.sbcs(a, b, c, lsr(d));
|
||||
cc.sbcs(a, b, c, asr(d));
|
||||
cc.sbcs(a, b, c, ror(d));
|
||||
cc.sbcs(a, b, c, lsl(8));
|
||||
cc.sbcs(a, b, c, lsr(8));
|
||||
cc.sbcs(a, b, c, asr(8));
|
||||
cc.sbcs(a, b, c, ror(8));
|
||||
cc.sbcs(a, b, 0xFF);
|
||||
cc.sbcs(a, b, 0xFF00);
|
||||
cc.sbcs(a, b, 0xFF000000);
|
||||
cc.sbcs(a, b, 0xF000000F);
|
||||
cc.sbfx(a, b, 3, 5);
|
||||
cc.sdiv(a, b, c);
|
||||
cc.sel(a, b, c);
|
||||
cc.shadd16(a, b, c);
|
||||
cc.shadd8(a, b, c);
|
||||
cc.shasx(a, b, c);
|
||||
cc.shsax(a, b, c);
|
||||
cc.shsub16(a, b, c);
|
||||
cc.shsub8(a, b, c);
|
||||
cc.smlabb(a, b, c, d);
|
||||
cc.smlabt(a, b, c, d);
|
||||
cc.smlad(a, b, c, d);
|
||||
cc.smladx(a, b, c, d);
|
||||
cc.smlal(a, b, c, d);
|
||||
cc.smlalbb(a, b, c, d);
|
||||
cc.smlalbt(a, b, c, d);
|
||||
cc.smlald(a, b, c, d);
|
||||
cc.smlaldx(a, b, c, d);
|
||||
cc.smlals(a, b, c, d);
|
||||
cc.smlaltb(a, b, c, d);
|
||||
cc.smlaltt(a, b, c, d);
|
||||
cc.smlatb(a, b, c, d);
|
||||
cc.smlatt(a, b, c, d);
|
||||
cc.smlawb(a, b, c, d);
|
||||
cc.smlawt(a, b, c, d);
|
||||
cc.smlsd(a, b, c, d);
|
||||
cc.smlsdx(a, b, c, d);
|
||||
cc.smlsld(a, b, c, d);
|
||||
cc.smlsldx(a, b, c, d);
|
||||
cc.smmla(a, b, c, d);
|
||||
cc.smmlar(a, b, c, d);
|
||||
cc.smmls(a, b, c, d);
|
||||
cc.smmlsr(a, b, c, d);
|
||||
cc.smmul(a, b, c);
|
||||
cc.smmulr(a, b, c);
|
||||
cc.smuad(a, b, c);
|
||||
cc.smuadx(a, b, c);
|
||||
cc.smulbb(a, b, c);
|
||||
cc.smulbt(a, b, c);
|
||||
cc.smull(a, b, c, d);
|
||||
cc.smulls(a, b, c, d);
|
||||
cc.smultb(a, b, c);
|
||||
cc.smultt(a, b, c);
|
||||
cc.smulwb(a, b, c);
|
||||
cc.smulwt(a, b, c);
|
||||
cc.smusd(a, b, c);
|
||||
cc.smusdx(a, b, c);
|
||||
cc.ssat(a, 8, c);
|
||||
cc.ssat(a, 8, c, lsl(8));
|
||||
cc.ssat(a, 8, c, asr(8));
|
||||
cc.ssat16(a, 8, c);
|
||||
cc.ssax(a, b, c);
|
||||
cc.ssub16(a, b, c);
|
||||
cc.ssub8(a, b, c);
|
||||
cc.str(a, ptr(b, c));
|
||||
cc.str(a, ptr_pre(b, c));
|
||||
cc.str(a, ptr_post(b, c));
|
||||
cc.str(a, ptr(b, 4));
|
||||
cc.str(a, ptr_pre(b, 4));
|
||||
cc.str(a, ptr_post(b, 4));
|
||||
cc.strb(a, ptr(b, c));
|
||||
cc.strb(a, ptr_pre(b, c));
|
||||
cc.strb(a, ptr_post(b, c));
|
||||
cc.strb(a, ptr(b, 4));
|
||||
cc.strb(a, ptr_pre(b, 4));
|
||||
cc.strb(a, ptr_post(b, 4));
|
||||
cc.strbt(a, ptr_post(b, c));
|
||||
cc.strbt(a, ptr_post(b, 4));
|
||||
cc.strh(a, ptr(b, c));
|
||||
cc.strh(a, ptr_pre(b, c));
|
||||
cc.strh(a, ptr_post(b, c));
|
||||
cc.strh(a, ptr(b, 4));
|
||||
cc.strh(a, ptr_pre(b, 4));
|
||||
cc.strh(a, ptr_post(b, 4));
|
||||
cc.strht(a, ptr_post(b, c));
|
||||
cc.strht(a, ptr_post(b, 4));
|
||||
cc.strt(a, ptr_post(b, c));
|
||||
cc.strt(a, ptr_post(b, 4));
|
||||
cc.sub(a, b, c, lsl(d));
|
||||
cc.sub(a, b, c, lsr(d));
|
||||
cc.sub(a, b, c, asr(d));
|
||||
cc.sub(a, b, c, ror(d));
|
||||
cc.sub(a, b, c, lsl(8));
|
||||
cc.sub(a, b, c, lsr(8));
|
||||
cc.sub(a, b, c, asr(8));
|
||||
cc.sub(a, b, c, ror(8));
|
||||
cc.sub(a, b, 0xFF);
|
||||
cc.sub(a, b, 0xFF00);
|
||||
cc.sub(a, b, 0xFF000000);
|
||||
cc.sub(a, b, 0xF000000F);
|
||||
cc.subs(a, b, c, lsl(d));
|
||||
cc.subs(a, b, c, lsr(d));
|
||||
cc.subs(a, b, c, asr(d));
|
||||
cc.subs(a, b, c, ror(d));
|
||||
cc.subs(a, b, c, lsl(8));
|
||||
cc.subs(a, b, c, lsr(8));
|
||||
cc.subs(a, b, c, asr(8));
|
||||
cc.subs(a, b, c, ror(8));
|
||||
cc.subs(a, b, 0xFF);
|
||||
cc.subs(a, b, 0xFF00);
|
||||
cc.subs(a, b, 0xFF000000);
|
||||
cc.subs(a, b, 0xF000000F);
|
||||
cc.sxtab(a, b, c, ror(8));
|
||||
cc.sxtab16(a, b, c, ror(8));
|
||||
cc.sxtah(a, b, c, ror(8));
|
||||
cc.sxtb(a, b, ror(8));
|
||||
cc.sxtb16(a, b, ror(8));
|
||||
cc.sxth(a, b, ror(8));
|
||||
cc.teq(a, b, lsl(c));
|
||||
cc.teq(a, b, lsr(c));
|
||||
cc.teq(a, b, asr(c));
|
||||
cc.teq(a, b, ror(c));
|
||||
cc.teq(a, b, lsl(8));
|
||||
cc.teq(a, b, lsr(8));
|
||||
cc.teq(a, b, asr(8));
|
||||
cc.teq(a, b, ror(8));
|
||||
cc.teq(a, 0xFF);
|
||||
cc.teq(a, 0xFF00);
|
||||
cc.teq(a, 0xFF000000);
|
||||
cc.teq(a, 0xF000000F);
|
||||
cc.tst(a, b, lsl(c));
|
||||
cc.tst(a, b, lsr(c));
|
||||
cc.tst(a, b, asr(c));
|
||||
cc.tst(a, b, ror(c));
|
||||
cc.tst(a, b, lsl(8));
|
||||
cc.tst(a, b, lsr(8));
|
||||
cc.tst(a, b, asr(8));
|
||||
cc.tst(a, b, ror(8));
|
||||
cc.tst(a, 0xFF);
|
||||
cc.tst(a, 0xFF00);
|
||||
cc.tst(a, 0xFF000000);
|
||||
cc.tst(a, 0xF000000F);
|
||||
cc.uadd16(a, b, c);
|
||||
cc.uadd8(a, b, c);
|
||||
cc.uasx(a, b, c);
|
||||
cc.ubfx(a, b, 3, 5);
|
||||
cc.udiv(a, b, c);
|
||||
cc.uhadd16(a, b, c);
|
||||
cc.uhadd8(a, b, c);
|
||||
cc.uhasx(a, b, c);
|
||||
cc.uhsax(a, b, c);
|
||||
cc.uhsub16(a, b, c);
|
||||
cc.uhsub8(a, b, c);
|
||||
cc.umaal(a, b, c, d);
|
||||
cc.umlal(a, b, c, d);
|
||||
cc.umlals(a, b, c, d);
|
||||
cc.umull(a, b, c, d);
|
||||
cc.umulls(a, b, c, d);
|
||||
cc.uqadd16(a, b, c);
|
||||
cc.uqadd8(a, b, c);
|
||||
cc.uqasx(a, b, c);
|
||||
cc.uqsax(a, b, c);
|
||||
cc.uqsub16(a, b, c);
|
||||
cc.uqsub8(a, b, c);
|
||||
cc.usad8(a, b, c);
|
||||
cc.usada8(a, b, c, d);
|
||||
cc.usat(a, 8, c, lsl(8));
|
||||
cc.usat(a, 8, c, asr(8));
|
||||
cc.usat16(a, 8, c);
|
||||
cc.usax(a, b, c);
|
||||
cc.usub16(a, b, c);
|
||||
cc.usub8(a, b, c);
|
||||
cc.uxtab(a, b, c, ror(8));
|
||||
cc.uxtab16(a, b, c, ror(8));
|
||||
cc.uxtah(a, b, c, ror(8));
|
||||
cc.uxtb(a, b, ror(8));
|
||||
cc.uxtb16(a, b, ror(8));
|
||||
cc.uxth(a, b, ror(8));
|
||||
}
|
||||
|
||||
static void generateGpSequence(BaseEmitter& emitter, bool emitPrologEpilog) {
|
||||
if (emitter.isAssembler()) {
|
||||
a32::Assembler& cc = *emitter.as<a32::Assembler>();
|
||||
|
||||
a32::Gp a = a32::r0;
|
||||
a32::Gp b = a32::r1;
|
||||
a32::Gp c = a32::r2;
|
||||
a32::Gp d = a32::r3;
|
||||
|
||||
if (emitPrologEpilog) {
|
||||
FuncDetail func;
|
||||
func.init(FuncSignature::build<void, void*, const void*, size_t>(), cc.environment());
|
||||
|
||||
FuncFrame frame;
|
||||
frame.init(func);
|
||||
frame.addDirtyRegs(a, b, c, d);
|
||||
frame.finalize();
|
||||
|
||||
cc.emitProlog(frame);
|
||||
generateGpSequenceInternal(cc, a, b, c, d);
|
||||
cc.emitEpilog(frame);
|
||||
}
|
||||
else {
|
||||
generateGpSequenceInternal(cc, a, b, c, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename EmitterFn>
|
||||
static void benchmarkA32Function(Arch arch, uint32_t numIterations, const char* description, const EmitterFn& emitterFn) noexcept {
|
||||
CodeHolder code;
|
||||
printf("%s:\n", description);
|
||||
|
||||
uint32_t instCount = 0;
|
||||
|
||||
#ifndef ASMJIT_NO_BUILDER
|
||||
instCount = asmjit_perf_utils::calculateInstructionCount<a32::Builder>(code, arch, [&](a32::Builder& emitter) {
|
||||
emitterFn(emitter, false);
|
||||
});
|
||||
#endif
|
||||
|
||||
asmjit_perf_utils::bench<a32::Assembler>(code, arch, numIterations, "[raw]", instCount, [&](a32::Assembler& emitter) {
|
||||
emitterFn(emitter, false);
|
||||
});
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void benchmarkA32Emitters(uint32_t numIterations) {
|
||||
static const char description[] = "GpSequence (Sequence of GP instructions)";
|
||||
benchmarkA32Function(Arch::kARM, numIterations, description, [](BaseEmitter& emitter, bool emitPrologEpilog) {
|
||||
generateGpSequence(emitter, emitPrologEpilog);
|
||||
});
|
||||
}
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32
|
||||
55
asmjit/a32.h
Normal file
55
asmjit/a32.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_A32_H_INCLUDED
|
||||
#define ASMJIT_A32_H_INCLUDED
|
||||
|
||||
//! \addtogroup asmjit_a32
|
||||
//!
|
||||
//! ### Emitters
|
||||
//!
|
||||
//! - \ref a32::Assembler - AArch32 assembler (must read, provides examples).
|
||||
//! - \ref a32::Builder - AArch32 builder.
|
||||
//! - \ref a32::Compiler - AArch32 compiler.
|
||||
//! - \ref a32::Emitter - AArch32 emitter (abstract).
|
||||
//!
|
||||
//! ### Supported Instructions
|
||||
//!
|
||||
//! - Emitters:
|
||||
//! - \ref a32::EmitterExplicitT - Provides all instructions that use explicit operands, provides also utility
|
||||
//! functions. The member functions provided are part of all AArch32 emitters.
|
||||
//!
|
||||
//! - Instruction representation:
|
||||
//! - \ref a32::Inst::Id - instruction identifiers.
|
||||
//!
|
||||
//! ### Register Operands
|
||||
//!
|
||||
//! - \ref arm::Reg - Base class of any AArch32/AArch64 register.
|
||||
//! - \ref a32::Gp - 32-bit general purpose register (AArch32)
|
||||
//! - \ref arm::Vec - Vector (SIMD) register:
|
||||
//! - \ref arm::VecS - 32-bit SIMD register.
|
||||
//! - \ref arm::VecD - 64-bit SIMD register.
|
||||
//! - \ref arm::VecV - 128-bit SIMD register.
|
||||
//!
|
||||
//! ### Memory Operands
|
||||
//!
|
||||
//! - \ref arm::Mem - AArch32/AArch64 memory operand that provides support for all ARM addressing features
|
||||
//! including base, index, pre/post increment, and ARM-specific shift addressing and index extending.
|
||||
//!
|
||||
//! ### Other
|
||||
//!
|
||||
//! - \ref arm::Shift - Shift operation and value.
|
||||
//! - \ref arm::DataType - Data type that is part of an instruction in AArch32 mode.
|
||||
//! - \ref a32::Utils - Utilities that can help during code generation for AArch32.
|
||||
|
||||
#include <asmjit/arm.h>
|
||||
#include <asmjit/arm/a32assembler.h>
|
||||
#include <asmjit/arm/a32builder.h>
|
||||
#include <asmjit/arm/a32emitter.h>
|
||||
#include <asmjit/arm/a32globals.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
#endif // ASMJIT_A32_H_INCLUDED
|
||||
|
||||
76
asmjit/arm/a32archtraits_p.h
Normal file
76
asmjit/arm/a32archtraits_p.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32ARCHTRAITS_P_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32ARCHTRAITS_P_H_INCLUDED
|
||||
|
||||
#include <asmjit/core/archtraits.h>
|
||||
#include <asmjit/core/misc_p.h>
|
||||
#include <asmjit/core/type.h>
|
||||
#include <asmjit/arm/a32globals.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
static const constexpr ArchTraits a32_arch_traits = {
|
||||
// SP/FP/LR/PC.
|
||||
13, 11, 14, 15,
|
||||
|
||||
// Reserved.
|
||||
{ 0u, 0u, 0u },
|
||||
|
||||
// HW stack alignment (AArch32 requires stack aligned to 4 bytes at HW level).
|
||||
4,
|
||||
|
||||
// Min/max stack offset.
|
||||
0, 0, // TODO: ARM32
|
||||
|
||||
// Supported register types.
|
||||
0u | (1u << uint32_t(RegType::kGp32 ))
|
||||
| (1u << uint32_t(RegType::kVec32 ))
|
||||
| (1u << uint32_t(RegType::kVec64 ))
|
||||
| (1u << uint32_t(RegType::kVec128)),
|
||||
|
||||
// Instruction hints [Gp, Vec, ExtraVirt2, ExtraVirt3].
|
||||
{{
|
||||
InstHints::kPushPop,
|
||||
InstHints::kPushPop,
|
||||
InstHints::kNoHints,
|
||||
InstHints::kNoHints
|
||||
}},
|
||||
|
||||
// TypeIdToRegType.
|
||||
#define V(index) (index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt8) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt8) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt16) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt16) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt32) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt32) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kIntPtr) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUIntPtr) ? RegType::kGp32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat32) ? RegType::kVec32 : \
|
||||
index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat64) ? RegType::kVec64 : RegType::kNone)
|
||||
{{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
|
||||
#undef V
|
||||
|
||||
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
|
||||
{
|
||||
ArchTypeNameId::kByte,
|
||||
ArchTypeNameId::kHWord,
|
||||
ArchTypeNameId::kWord,
|
||||
ArchTypeNameId::kXWord
|
||||
}
|
||||
};
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32ARCHTRAITS_P_H_INCLUDED
|
||||
11016
asmjit/arm/a32assembler.cpp
Normal file
11016
asmjit/arm/a32assembler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
69
asmjit/arm/a32assembler.h
Normal file
69
asmjit/arm/a32assembler.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32ASSEMBLER_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32ASSEMBLER_H_INCLUDED
|
||||
|
||||
#include <asmjit/core/assembler.h>
|
||||
#include <asmjit/arm/a32emitter.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
//! AArch32 assembler implementation.
|
||||
class ASMJIT_VIRTAPI Assembler
|
||||
: public BaseAssembler,
|
||||
public EmitterExplicitT<Assembler> {
|
||||
|
||||
public:
|
||||
typedef BaseAssembler Base;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Assembler(CodeHolder* code = nullptr) noexcept;
|
||||
ASMJIT_API ~Assembler() noexcept override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
//! Gets whether the current ARM mode is THUMB (alternative to 32-bit ARM encoding).
|
||||
ASMJIT_INLINE_NODEBUG bool is_in_thumb_mode() const noexcept { return _environment.is_arch_thumb(); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Emit
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error _emit(InstId inst_id, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Align
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error align(AlignMode align_mode, uint32_t alignment) override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Events
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error on_attach(CodeHolder& code) noexcept override;
|
||||
ASMJIT_API Error on_detach(CodeHolder& code) noexcept override;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32ASSEMBLER_H_INCLUDED
|
||||
58
asmjit/arm/a32builder.cpp
Normal file
58
asmjit/arm/a32builder.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core/api-build_p.h>
|
||||
#if !defined(ASMJIT_NO_AARCH32) && !defined(ASMJIT_NO_BUILDER)
|
||||
|
||||
#include <asmjit/arm/a32assembler.h>
|
||||
#include <asmjit/arm/a32builder.h>
|
||||
#include <asmjit/arm/a32emithelper_p.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
// a32::Builder - Construction & Destruction
|
||||
// =========================================
|
||||
|
||||
Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() {
|
||||
_arch_mask = uint64_t(1) << uint32_t(Arch::kARM ) |
|
||||
uint64_t(1) << uint32_t(Arch::kARM_BE ) |
|
||||
uint64_t(1) << uint32_t(Arch::kThumb ) |
|
||||
uint64_t(1) << uint32_t(Arch::kThumb_BE) ;
|
||||
if (code)
|
||||
code->attach(this);
|
||||
}
|
||||
Builder::~Builder() noexcept {}
|
||||
|
||||
// a32::Builder - Events
|
||||
// =====================
|
||||
|
||||
Error Builder::on_attach(CodeHolder& code) noexcept {
|
||||
ASMJIT_PROPAGATE(Base::on_attach(code));
|
||||
|
||||
_instruction_alignment = _environment.is_arch_thumb() ? uint8_t(2) : uint8_t(4);
|
||||
_instruction_alignment = uint8_t(4);
|
||||
update_emitter_funcs(this);
|
||||
|
||||
return Error::kOk;
|
||||
}
|
||||
|
||||
Error Builder::on_detach(CodeHolder& code) noexcept {
|
||||
return Base::on_detach(code);
|
||||
}
|
||||
|
||||
// a32::Builder - Finalize
|
||||
// =======================
|
||||
|
||||
Error Builder::finalize() {
|
||||
ASMJIT_PROPAGATE(run_passes());
|
||||
Assembler a(_code);
|
||||
a.add_encoding_options(encoding_options());
|
||||
a.add_diagnostic_options(diagnostic_options());
|
||||
return serialize_to(&a);
|
||||
}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32 && !ASMJIT_NO_BUILDER
|
||||
57
asmjit/arm/a32builder.h
Normal file
57
asmjit/arm/a32builder.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32BUILDER_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32BUILDER_H_INCLUDED
|
||||
|
||||
#include <asmjit/core/api-config.h>
|
||||
#ifndef ASMJIT_NO_BUILDER
|
||||
|
||||
#include <asmjit/core/builder.h>
|
||||
#include <asmjit/arm/a32emitter.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
//! AArch32 builder implementation.
|
||||
class ASMJIT_VIRTAPI Builder
|
||||
: public BaseBuilder,
|
||||
public EmitterExplicitT<Builder> {
|
||||
public:
|
||||
ASMJIT_NONCOPYABLE(Builder)
|
||||
typedef BaseBuilder Base;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
ASMJIT_API explicit Builder(CodeHolder* code = nullptr) noexcept;
|
||||
ASMJIT_API ~Builder() noexcept override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Events
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error on_attach(CodeHolder& code) noexcept override;
|
||||
ASMJIT_API Error on_detach(CodeHolder& code) noexcept override;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Finalize
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error finalize() override;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_BUILDER
|
||||
#endif // ASMJIT_ARM_A32BUILDER_H_INCLUDED
|
||||
395
asmjit/arm/a32emithelper.cpp
Normal file
395
asmjit/arm/a32emithelper.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core/api-build_p.h>
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
|
||||
#include <asmjit/core/formatter.h>
|
||||
#include <asmjit/core/funcargscontext_p.h>
|
||||
#include <asmjit/core/string.h>
|
||||
#include <asmjit/core/type.h>
|
||||
#include <asmjit/support/support.h>
|
||||
#include <asmjit/arm/a32emithelper_p.h>
|
||||
#include <asmjit/arm/a32formatter_p.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
// a32::EmitHelper - Emit Operations
|
||||
// =================================
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error EmitHelper::emit_reg_move(
|
||||
const Operand_& dst_,
|
||||
const Operand_& src_, TypeId type_id, const char* comment) {
|
||||
|
||||
Emitter* emitter = _emitter->as<Emitter>();
|
||||
|
||||
// Invalid or abstract TypeIds are not allowed.
|
||||
ASMJIT_ASSERT(TypeUtils::is_valid(type_id) && !TypeUtils::is_abstract(type_id));
|
||||
|
||||
emitter->set_inline_comment(comment);
|
||||
|
||||
if (dst_.is_reg() && src_.is_mem()) {
|
||||
Reg dst(dst_.as<Reg>());
|
||||
Mem src(src_.as<Mem>());
|
||||
|
||||
switch (type_id) {
|
||||
case TypeId::kInt8:
|
||||
case TypeId::kUInt8:
|
||||
return emitter->ldrb(dst.as<Gp>(), src);
|
||||
|
||||
case TypeId::kInt16:
|
||||
case TypeId::kUInt16:
|
||||
return emitter->ldrh(dst.as<Gp>(), src);
|
||||
|
||||
case TypeId::kInt32:
|
||||
case TypeId::kUInt32:
|
||||
return emitter->ldr(dst.as<Gp>(), src);
|
||||
|
||||
default: {
|
||||
if (TypeUtils::is_float32(type_id) || TypeUtils::is_vec32(type_id))
|
||||
return emitter->vldr_32(dst.as<Vec>().s(), src);
|
||||
|
||||
if (TypeUtils::is_float64(type_id) || TypeUtils::is_vec64(type_id))
|
||||
return emitter->vldr_64(dst.as<Vec>().d(), src);
|
||||
|
||||
// TODO: AArch32.
|
||||
// if (TypeUtils::is_vec128(type_id))
|
||||
// return emitter->vldr(dst.as<Vec>().q(), src);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst_.is_mem() && src_.is_reg()) {
|
||||
Mem dst(dst_.as<Mem>());
|
||||
Reg src(src_.as<Reg>());
|
||||
|
||||
switch (type_id) {
|
||||
case TypeId::kInt8:
|
||||
case TypeId::kUInt8:
|
||||
return emitter->strb(src.as<Gp>(), dst);
|
||||
|
||||
case TypeId::kInt16:
|
||||
case TypeId::kUInt16:
|
||||
return emitter->strh(src.as<Gp>(), dst);
|
||||
|
||||
case TypeId::kInt32:
|
||||
case TypeId::kUInt32:
|
||||
return emitter->str(src.as<Gp>(), dst);
|
||||
|
||||
default: {
|
||||
if (TypeUtils::is_float32(type_id) || TypeUtils::is_vec32(type_id))
|
||||
return emitter->vstr_32(src.as<Vec>().s(), dst);
|
||||
|
||||
if (TypeUtils::is_float64(type_id) || TypeUtils::is_vec64(type_id))
|
||||
return emitter->vstr_64(src.as<Vec>().d(), dst);
|
||||
|
||||
// TODO: AArch32
|
||||
// if (TypeUtils::isVec128(type_id))
|
||||
// return emitter->vstr(src.as<Vec>().q(), dst);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst_.is_reg() && src_.is_reg()) {
|
||||
Reg dst(dst_.as<Reg>());
|
||||
Reg src(src_.as<Reg>());
|
||||
|
||||
switch (type_id) {
|
||||
case TypeId::kInt8:
|
||||
case TypeId::kUInt8:
|
||||
case TypeId::kInt16:
|
||||
case TypeId::kUInt16:
|
||||
case TypeId::kInt32:
|
||||
case TypeId::kUInt32:
|
||||
return emitter->mov(src.as<Gp>(), dst.as<Gp>());
|
||||
|
||||
default: {
|
||||
if (TypeUtils::is_float32(type_id) || TypeUtils::is_vec32(type_id))
|
||||
return emitter->vmov(dst.as<Vec>().s(), src.as<Vec>().s());
|
||||
|
||||
if (TypeUtils::is_float64(type_id) || TypeUtils::is_vec64(type_id))
|
||||
return emitter->vmov(dst.as<Vec>().d(), src.as<Vec>().d());
|
||||
|
||||
if (TypeUtils::is_vec128(type_id))
|
||||
return emitter->vmov(dst.as<Vec>().q(), src.as<Vec>().q());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emitter->set_inline_comment(nullptr);
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
|
||||
Error EmitHelper::emit_reg_swap(
|
||||
const Reg& a,
|
||||
const Reg& b, const char* comment) {
|
||||
|
||||
Support::maybe_unused(a, b, comment);
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
|
||||
Error EmitHelper::emit_arg_move(
|
||||
const Reg& dst_, TypeId dst_type_id,
|
||||
const Operand_& src_, TypeId src_type_id, const char* comment) {
|
||||
|
||||
// TODO: AArch32 - EmitArgMove is unfinished.
|
||||
Support::maybe_unused(dst_, dst_type_id, src_, src_type_id, comment);
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
|
||||
// a32::EmitHelper - Emit Prolog & Epilog
|
||||
// ======================================
|
||||
|
||||
struct LoadStoreInstructions {
|
||||
InstId singleInstId;
|
||||
InstId pairInstId;
|
||||
};
|
||||
|
||||
/*
|
||||
struct PrologEpilogInfo {
|
||||
struct RegPair {
|
||||
uint8_t ids[2];
|
||||
uint16_t offset;
|
||||
};
|
||||
|
||||
struct GroupData {
|
||||
RegPair pairs[16];
|
||||
uint32_t pairCount;
|
||||
};
|
||||
|
||||
Support::Array<GroupData, 2> groups;
|
||||
uint32_t sizeTotal;
|
||||
|
||||
Error init(const FuncFrame& frame) noexcept {
|
||||
uint32_t offset = 0;
|
||||
|
||||
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) {
|
||||
GroupData& data = groups[group];
|
||||
|
||||
uint32_t n = 0;
|
||||
uint32_t pairCount = 0;
|
||||
RegPair* pairs = data.pairs;
|
||||
|
||||
uint32_t slotSize = frame.saveRestoreRegSize(group);
|
||||
uint32_t savedRegs = frame.savedRegs(group);
|
||||
|
||||
if (group == RegGroup::kGp && frame.hasPreservedFP()) {
|
||||
// Must be at the beginning of the push/pop sequence.
|
||||
ASMJIT_ASSERT(pairCount == 0);
|
||||
|
||||
pairs[0].offset = uint16_t(offset);
|
||||
pairs[0].ids[0] = Gp::kIdFp;
|
||||
pairs[0].ids[1] = Gp::kIdLr;
|
||||
offset += slotSize * 2;
|
||||
pairCount++;
|
||||
|
||||
savedRegs &= ~Support::bitMask(Gp::kIdFp, Gp::kIdLr);
|
||||
}
|
||||
|
||||
Support::BitWordIterator<uint32_t> it(savedRegs);
|
||||
while (it.hasNext()) {
|
||||
pairs[pairCount].ids[n] = uint8_t(it.next());
|
||||
|
||||
if (++n == 2) {
|
||||
pairs[pairCount].offset = uint16_t(offset);
|
||||
offset += slotSize * 2;
|
||||
|
||||
n = 0;
|
||||
pairCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 1) {
|
||||
pairs[pairCount].ids[1] = uint8_t(BaseReg::kIdBad);
|
||||
pairs[pairCount].offset = uint16_t(offset);
|
||||
offset += slotSize * 2;
|
||||
pairCount++;
|
||||
}
|
||||
|
||||
data.pairCount = pairCount;
|
||||
}
|
||||
|
||||
sizeTotal = offset;
|
||||
return kErrorOk;
|
||||
}
|
||||
};
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) {
|
||||
Emitter* emitter = _emitter->as<Emitter>();
|
||||
|
||||
PrologEpilogInfo pei;
|
||||
ASMJIT_PROPAGATE(pei.init(frame));
|
||||
|
||||
static const Support::Array<Reg, 2> groupRegs = {{ x0, d0 }};
|
||||
static const Support::Array<LoadStoreInstructions, 2> groupInsts = {{
|
||||
{ Inst::kIdStr , Inst::kIdStp },
|
||||
{ Inst::kIdStr_v, Inst::kIdStp_v }
|
||||
}};
|
||||
|
||||
uint32_t adjustInitialOffset = pei.sizeTotal;
|
||||
|
||||
for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) {
|
||||
const PrologEpilogInfo::GroupData& data = pei.groups[group];
|
||||
uint32_t pairCount = data.pairCount;
|
||||
|
||||
Reg regs[2] = { groupRegs[group], groupRegs[group] };
|
||||
Mem mem = ptr(sp);
|
||||
|
||||
const LoadStoreInstructions& insts = groupInsts[group];
|
||||
for (uint32_t i = 0; i < pairCount; i++) {
|
||||
const PrologEpilogInfo::RegPair& pair = data.pairs[i];
|
||||
|
||||
regs[0].setId(pair.ids[0]);
|
||||
regs[1].setId(pair.ids[1]);
|
||||
mem.setOffsetLo32(pair.offset);
|
||||
|
||||
if (pair.offset == 0 && adjustInitialOffset) {
|
||||
mem.setOffset(-int(adjustInitialOffset));
|
||||
mem.makePreIndex();
|
||||
}
|
||||
|
||||
if (pair.ids[1] == BaseReg::kIdBad)
|
||||
ASMJIT_PROPAGATE(emitter->emit(insts.singleInstId, regs[0], mem));
|
||||
else
|
||||
ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem));
|
||||
|
||||
mem.resetToFixedOffset();
|
||||
|
||||
if (i == 0 && frame.hasPreservedFP()) {
|
||||
ASMJIT_PROPAGATE(emitter->mov(x29, sp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.hasStackAdjustment()) {
|
||||
uint32_t adj = frame.stackAdjustment();
|
||||
if (adj <= 0xFFFu) {
|
||||
ASMJIT_PROPAGATE(emitter->sub(sp, sp, adj));
|
||||
}
|
||||
else if (adj <= 0xFFFFFFu) {
|
||||
// TODO: [ARM] Prolog - we must touch the pages otherwise it's undefined.
|
||||
ASMJIT_PROPAGATE(emitter->sub(sp, sp, adj & 0x000FFFu));
|
||||
ASMJIT_PROPAGATE(emitter->sub(sp, sp, adj & 0xFFF000u));
|
||||
}
|
||||
else {
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// TODO: [ARM] Emit epilog.
|
||||
ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) {
|
||||
Emitter* emitter = _emitter->as<Emitter>();
|
||||
|
||||
PrologEpilogInfo pei;
|
||||
ASMJIT_PROPAGATE(pei.init(frame));
|
||||
|
||||
static const Support::Array<Reg, 2> groupRegs = {{ x0, d0 }};
|
||||
static const Support::Array<LoadStoreInstructions, 2> groupInsts = {{
|
||||
{ Inst::kIdLdr , Inst::kIdLdp },
|
||||
{ Inst::kIdLdr_v, Inst::kIdLdp_v }
|
||||
}};
|
||||
|
||||
uint32_t adjustInitialOffset = pei.sizeTotal;
|
||||
|
||||
if (frame.hasStackAdjustment()) {
|
||||
uint32_t adj = frame.stackAdjustment();
|
||||
if (adj <= 0xFFFu) {
|
||||
ASMJIT_PROPAGATE(emitter->add(sp, sp, adj));
|
||||
}
|
||||
else if (adj <= 0xFFFFFFu) {
|
||||
ASMJIT_PROPAGATE(emitter->add(sp, sp, adj & 0x000FFFu));
|
||||
ASMJIT_PROPAGATE(emitter->add(sp, sp, adj & 0xFFF000u));
|
||||
}
|
||||
else {
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
}
|
||||
|
||||
for (int g = 1; g >= 0; g--) {
|
||||
RegGroup group = RegGroup(g);
|
||||
const PrologEpilogInfo::GroupData& data = pei.groups[group];
|
||||
uint32_t pairCount = data.pairCount;
|
||||
|
||||
Reg regs[2] = { groupRegs[group], groupRegs[group] };
|
||||
Mem mem = ptr(sp);
|
||||
|
||||
const LoadStoreInstructions& insts = groupInsts[group];
|
||||
|
||||
for (int i = int(pairCount) - 1; i >= 0; i--) {
|
||||
const PrologEpilogInfo::RegPair& pair = data.pairs[i];
|
||||
|
||||
regs[0].setId(pair.ids[0]);
|
||||
regs[1].setId(pair.ids[1]);
|
||||
mem.setOffsetLo32(pair.offset);
|
||||
|
||||
if (pair.offset == 0 && adjustInitialOffset) {
|
||||
mem.setOffset(int(adjustInitialOffset));
|
||||
mem.makePostIndex();
|
||||
}
|
||||
|
||||
if (pair.ids[1] == BaseReg::kIdBad)
|
||||
ASMJIT_PROPAGATE(emitter->emit(insts.singleInstId, regs[0], mem));
|
||||
else
|
||||
ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem));
|
||||
|
||||
mem.resetToFixedOffset();
|
||||
}
|
||||
}
|
||||
|
||||
ASMJIT_PROPAGATE(emitter->ret(x30));
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
*/
|
||||
|
||||
static Error ASMJIT_CDECL Emitter_emit_prolog(BaseEmitter* emitter, const FuncFrame& frame) {
|
||||
// EmitHelper emitHelper(emitter);
|
||||
// return emitHelper.emitProlog(frame);
|
||||
Support::maybe_unused(emitter, frame);
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
|
||||
static Error ASMJIT_CDECL Emitter_emit_epilog(BaseEmitter* emitter, const FuncFrame& frame) {
|
||||
// EmitHelper emitHelper(emitter);
|
||||
// return emitHelper.emitEpilog(frame);
|
||||
Support::maybe_unused(emitter, frame);
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
|
||||
static Error ASMJIT_CDECL Emitter_emit_args_assignment(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args) {
|
||||
// EmitHelper emitHelper(emitter);
|
||||
// return emitHelper.emitArgsAssignment(frame, args);
|
||||
Support::maybe_unused(emitter, frame, args);
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
|
||||
void assignEmitterFuncs(BaseEmitter* emitter) {
|
||||
emitter->_funcs.emit_prolog = Emitter_emit_prolog;
|
||||
emitter->_funcs.emit_epilog = Emitter_emit_epilog;
|
||||
emitter->_funcs.emit_args_assignment = Emitter_emit_args_assignment;
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
emitter->_funcs.format_instruction = FormatterInternal::format_instruction;
|
||||
#endif
|
||||
|
||||
#ifndef ASMJIT_NO_VALIDATION
|
||||
// TODO: AArch32.
|
||||
// emitter->_funcs.validate = InstInternal::validate;
|
||||
#endif
|
||||
}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32
|
||||
53
asmjit/arm/a32emithelper_p.h
Normal file
53
asmjit/arm/a32emithelper_p.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32EMITHELPER_P_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32EMITHELPER_P_H_INCLUDED
|
||||
|
||||
#include <asmjit/core/api-config.h>
|
||||
|
||||
#include <asmjit/core/emithelper_p.h>
|
||||
#include <asmjit/core/func.h>
|
||||
#include <asmjit/arm/a32emitter.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
class EmitHelper : public BaseEmitHelper {
|
||||
public:
|
||||
ASMJIT_INLINE_NODEBUG explicit EmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
||||
: BaseEmitHelper(emitter) {}
|
||||
|
||||
ASMJIT_INLINE_NODEBUG ~EmitHelper() noexcept override = default;
|
||||
|
||||
Error emit_reg_move(
|
||||
const Operand_& dst_,
|
||||
const Operand_& src_, TypeId type_id, const char* comment = nullptr) override;
|
||||
|
||||
Error emit_reg_swap(
|
||||
const Reg& a,
|
||||
const Reg& b, const char* comment = nullptr) override;
|
||||
|
||||
Error emit_arg_move(
|
||||
const Reg& dst_, TypeId dst_type_id,
|
||||
const Operand_& src_, TypeId src_type_id, const char* comment = nullptr) override;
|
||||
|
||||
Error emit_prolog(const FuncFrame& frame);
|
||||
Error emit_epilog(const FuncFrame& frame);
|
||||
};
|
||||
|
||||
[[maybe_unused]]
|
||||
static inline void update_emitter_funcs(BaseEmitter* emitter) noexcept { Support::maybe_unused(emitter); }
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32EMITHELPER_P_H_INCLUDED
|
||||
1603
asmjit/arm/a32emitter.h
Normal file
1603
asmjit/arm/a32emitter.h
Normal file
File diff suppressed because it is too large
Load Diff
68
asmjit/arm/a32formatter.cpp
Normal file
68
asmjit/arm/a32formatter.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core/api-build_p.h>
|
||||
#if !defined(ASMJIT_NO_AARCH32) && !defined(ASMJIT_NO_LOGGING)
|
||||
|
||||
#include <asmjit/core/misc_p.h>
|
||||
#include <asmjit/support/support.h>
|
||||
#include <asmjit/arm/a32formatter_p.h>
|
||||
#include <asmjit/arm/a32instapi_p.h>
|
||||
#include <asmjit/arm/a32instdb_p.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
#ifndef ASMJIT_NO_COMPILER
|
||||
#include <asmjit/core/compiler.h>
|
||||
#endif
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
// a32::FormatterInternal - Format Instruction
|
||||
// ===========================================
|
||||
|
||||
ASMJIT_FAVOR_SIZE Error FormatterInternal::format_instruction(
|
||||
String& sb,
|
||||
FormatFlags format_flags,
|
||||
const BaseEmitter* emitter,
|
||||
Arch arch,
|
||||
const BaseInst& inst, Span<const Operand_> operands) noexcept {
|
||||
|
||||
Support::maybe_unused(arch);
|
||||
|
||||
// Format instruction options and instruction mnemonic.
|
||||
InstId inst_id = inst.real_id();
|
||||
if (inst_id < Inst::_kIdCount) {
|
||||
InstStringifyOptions stringifyOptions =
|
||||
Support::test(format_flags, FormatFlags::kShowAliases)
|
||||
? InstStringifyOptions::kAliases
|
||||
: InstStringifyOptions::kNone;
|
||||
ASMJIT_PROPAGATE(InstInternal::inst_id_to_string(inst_id, stringifyOptions, sb));
|
||||
}
|
||||
else {
|
||||
ASMJIT_PROPAGATE(sb.append_format("[InstId=#%u]", unsigned(inst_id)));
|
||||
}
|
||||
|
||||
CondCode cc = inst.arm_cond_code();
|
||||
if (cc != CondCode::kAL) {
|
||||
ASMJIT_PROPAGATE(sb.append('.'));
|
||||
ASMJIT_PROPAGATE(format_cond_code(sb, cc));
|
||||
}
|
||||
|
||||
// Format instruction operands.
|
||||
for (size_t i = 0; i < operands.size(); i++) {
|
||||
const Operand_& op = operands[i];
|
||||
if (op.is_none())
|
||||
break;
|
||||
|
||||
ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
|
||||
ASMJIT_PROPAGATE(format_operand(sb, format_flags, emitter, arch, op));
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32 && !ASMJIT_NO_LOGGING
|
||||
42
asmjit/arm/a32formatter_p.h
Normal file
42
asmjit/arm/a32formatter_p.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32FORMATTER_P_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32FORMATTER_P_H_INCLUDED
|
||||
|
||||
#include <asmjit/core/api-config.h>
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
|
||||
#include <asmjit/core/formatter.h>
|
||||
#include <asmjit/core/string.h>
|
||||
#include <asmjit/arm/armformatter_p.h>
|
||||
#include <asmjit/arm/a32globals.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
namespace FormatterInternal {
|
||||
|
||||
using namespace arm::FormatterInternal;
|
||||
|
||||
Error ASMJIT_CDECL format_instruction(
|
||||
String& sb,
|
||||
FormatFlags format_flags,
|
||||
const BaseEmitter* emitter,
|
||||
Arch arch,
|
||||
const BaseInst& inst, Span<const Operand_> operands) noexcept;
|
||||
|
||||
} // {FormatterInternal}
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_LOGGING
|
||||
#endif // ASMJIT_ARM_A32FORMATTER_P_H_INCLUDED
|
||||
531
asmjit/arm/a32globals.h
Normal file
531
asmjit/arm/a32globals.h
Normal file
@@ -0,0 +1,531 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32GLOBALS_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32GLOBALS_H_INCLUDED
|
||||
|
||||
#include <asmjit/arm/armglobals.h>
|
||||
|
||||
//! \namespace asmjit::a32
|
||||
//! \ingroup asmjit_a32
|
||||
//!
|
||||
//! AArch32 backend.
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
//! ARM32/THUMB instruction.
|
||||
//!
|
||||
//! \note Only used to hold ARM-specific enumerations and static functions.
|
||||
struct Inst {
|
||||
//! Instruction id.
|
||||
enum Id : uint32_t {
|
||||
// ${a32::InstId:Begin}
|
||||
// ------------------- Automatically generated, do not edit -------------------
|
||||
kIdNone = 0, //!< Instruction '<none>'.
|
||||
kIdAdc, //!< Instruction 'adc'.
|
||||
kIdAdcs, //!< Instruction 'adcs'.
|
||||
kIdAdd, //!< Instruction 'add'.
|
||||
kIdAdds, //!< Instruction 'adds'.
|
||||
kIdAdr, //!< Instruction 'adr'.
|
||||
kIdAesd, //!< Instruction 'aesd' {AES}.
|
||||
kIdAese, //!< Instruction 'aese' {AES}.
|
||||
kIdAesimc, //!< Instruction 'aesimc' {AES}.
|
||||
kIdAesmc, //!< Instruction 'aesmc' {AES}.
|
||||
kIdAnd, //!< Instruction 'and'.
|
||||
kIdAnds, //!< Instruction 'ands'.
|
||||
kIdAsr, //!< Instruction 'asr'.
|
||||
kIdAsrs, //!< Instruction 'asrs'.
|
||||
kIdB, //!< Instruction 'b'.
|
||||
kIdBfc, //!< Instruction 'bfc'.
|
||||
kIdBfi, //!< Instruction 'bfi'.
|
||||
kIdBic, //!< Instruction 'bic'.
|
||||
kIdBics, //!< Instruction 'bics'.
|
||||
kIdBkpt, //!< Instruction 'bkpt'.
|
||||
kIdBl, //!< Instruction 'bl'.
|
||||
kIdBlx, //!< Instruction 'blx'.
|
||||
kIdBx, //!< Instruction 'bx'.
|
||||
kIdBxj, //!< Instruction 'bxj'.
|
||||
kIdCbnz, //!< Instruction 'cbnz' (THUMB).
|
||||
kIdCbz, //!< Instruction 'cbz' (THUMB).
|
||||
kIdClrbhb, //!< Instruction 'clrbhb' {CLRBHB}.
|
||||
kIdClrex, //!< Instruction 'clrex'.
|
||||
kIdClz, //!< Instruction 'clz'.
|
||||
kIdCmn, //!< Instruction 'cmn'.
|
||||
kIdCmp, //!< Instruction 'cmp'.
|
||||
kIdCps, //!< Instruction 'cps' (ARM).
|
||||
kIdCpsid, //!< Instruction 'cpsid' (ARM).
|
||||
kIdCpsie, //!< Instruction 'cpsie' (ARM).
|
||||
kIdCrc32b, //!< Instruction 'crc32b' {CRC32}.
|
||||
kIdCrc32cb, //!< Instruction 'crc32cb' {CRC32}.
|
||||
kIdCrc32ch, //!< Instruction 'crc32ch' {CRC32}.
|
||||
kIdCrc32cw, //!< Instruction 'crc32cw' {CRC32}.
|
||||
kIdCrc32h, //!< Instruction 'crc32h' {CRC32}.
|
||||
kIdCrc32w, //!< Instruction 'crc32w' {CRC32}.
|
||||
kIdCsdb, //!< Instruction 'csdb'.
|
||||
kIdDbg, //!< Instruction 'dbg' {ARMv8-}.
|
||||
kIdDcps1, //!< Instruction 'dcps1' (THUMB).
|
||||
kIdDcps2, //!< Instruction 'dcps2' (THUMB).
|
||||
kIdDcps3, //!< Instruction 'dcps3' (THUMB).
|
||||
kIdDmb, //!< Instruction 'dmb'.
|
||||
kIdDsb, //!< Instruction 'dsb'.
|
||||
kIdEor, //!< Instruction 'eor'.
|
||||
kIdEors, //!< Instruction 'eors'.
|
||||
kIdEret, //!< Instruction 'eret' (ARM).
|
||||
kIdEsb, //!< Instruction 'esb' {RAS}.
|
||||
kIdHlt, //!< Instruction 'hlt'.
|
||||
kIdHvc, //!< Instruction 'hvc' (ARM).
|
||||
kIdIsb, //!< Instruction 'isb'.
|
||||
kIdIt, //!< Instruction 'it' (THUMB).
|
||||
kIdIte, //!< Instruction 'ite' (THUMB).
|
||||
kIdItee, //!< Instruction 'itee' (THUMB).
|
||||
kIdIteee, //!< Instruction 'iteee' (THUMB).
|
||||
kIdIteet, //!< Instruction 'iteet' (THUMB).
|
||||
kIdItet, //!< Instruction 'itet' (THUMB).
|
||||
kIdItete, //!< Instruction 'itete' (THUMB).
|
||||
kIdItett, //!< Instruction 'itett' (THUMB).
|
||||
kIdItt, //!< Instruction 'itt' (THUMB).
|
||||
kIdItte, //!< Instruction 'itte' (THUMB).
|
||||
kIdIttee, //!< Instruction 'ittee' (THUMB).
|
||||
kIdIttet, //!< Instruction 'ittet' (THUMB).
|
||||
kIdIttt, //!< Instruction 'ittt' (THUMB).
|
||||
kIdIttte, //!< Instruction 'ittte' (THUMB).
|
||||
kIdItttt, //!< Instruction 'itttt' (THUMB).
|
||||
kIdLda, //!< Instruction 'lda'.
|
||||
kIdLdab, //!< Instruction 'ldab'.
|
||||
kIdLdaex, //!< Instruction 'ldaex'.
|
||||
kIdLdaexb, //!< Instruction 'ldaexb'.
|
||||
kIdLdaexd, //!< Instruction 'ldaexd'.
|
||||
kIdLdaexh, //!< Instruction 'ldaexh'.
|
||||
kIdLdah, //!< Instruction 'ldah'.
|
||||
kIdLdmda, //!< Instruction 'ldmda' (ARM).
|
||||
kIdLdmdb, //!< Instruction 'ldmdb'.
|
||||
kIdLdmia, //!< Instruction 'ldmia'.
|
||||
kIdLdmib, //!< Instruction 'ldmib' (ARM).
|
||||
kIdLdr, //!< Instruction 'ldr'.
|
||||
kIdLdrb, //!< Instruction 'ldrb'.
|
||||
kIdLdrbt, //!< Instruction 'ldrbt'.
|
||||
kIdLdrd, //!< Instruction 'ldrd'.
|
||||
kIdLdrex, //!< Instruction 'ldrex'.
|
||||
kIdLdrexb, //!< Instruction 'ldrexb'.
|
||||
kIdLdrexd, //!< Instruction 'ldrexd'.
|
||||
kIdLdrexh, //!< Instruction 'ldrexh'.
|
||||
kIdLdrh, //!< Instruction 'ldrh'.
|
||||
kIdLdrht, //!< Instruction 'ldrht'.
|
||||
kIdLdrsb, //!< Instruction 'ldrsb'.
|
||||
kIdLdrsbt, //!< Instruction 'ldrsbt'.
|
||||
kIdLdrsh, //!< Instruction 'ldrsh'.
|
||||
kIdLdrsht, //!< Instruction 'ldrsht'.
|
||||
kIdLdrt, //!< Instruction 'ldrt'.
|
||||
kIdLsl, //!< Instruction 'lsl'.
|
||||
kIdLsls, //!< Instruction 'lsls'.
|
||||
kIdLsr, //!< Instruction 'lsr'.
|
||||
kIdLsrs, //!< Instruction 'lsrs'.
|
||||
kIdMcr, //!< Instruction 'mcr' {ARMv6T2+}.
|
||||
kIdMcr2, //!< Instruction 'mcr2' {ARMv6T2+}.
|
||||
kIdMcrr, //!< Instruction 'mcrr' {ARMv6T2+}.
|
||||
kIdMcrr2, //!< Instruction 'mcrr2' {ARMv6T2+}.
|
||||
kIdMla, //!< Instruction 'mla'.
|
||||
kIdMlas, //!< Instruction 'mlas' (ARM).
|
||||
kIdMls, //!< Instruction 'mls'.
|
||||
kIdMov, //!< Instruction 'mov'.
|
||||
kIdMovs, //!< Instruction 'movs'.
|
||||
kIdMovt, //!< Instruction 'movt'.
|
||||
kIdMovw, //!< Instruction 'movw'.
|
||||
kIdMrc, //!< Instruction 'mrc'.
|
||||
kIdMrc2, //!< Instruction 'mrc2'.
|
||||
kIdMrrc, //!< Instruction 'mrrc'.
|
||||
kIdMrrc2, //!< Instruction 'mrrc2'.
|
||||
kIdMrs, //!< Instruction 'mrs'.
|
||||
kIdMsr, //!< Instruction 'msr'.
|
||||
kIdMul, //!< Instruction 'mul'.
|
||||
kIdMuls, //!< Instruction 'muls'.
|
||||
kIdMvn, //!< Instruction 'mvn'.
|
||||
kIdMvns, //!< Instruction 'mvns'.
|
||||
kIdNop, //!< Instruction 'nop'.
|
||||
kIdOrn, //!< Instruction 'orn' (THUMB).
|
||||
kIdOrns, //!< Instruction 'orns' (THUMB).
|
||||
kIdOrr, //!< Instruction 'orr'.
|
||||
kIdOrrs, //!< Instruction 'orrs'.
|
||||
kIdPkhbt, //!< Instruction 'pkhbt'.
|
||||
kIdPkhtb, //!< Instruction 'pkhtb'.
|
||||
kIdPld, //!< Instruction 'pld'.
|
||||
kIdPldw, //!< Instruction 'pldw' {MP}.
|
||||
kIdPli, //!< Instruction 'pli'.
|
||||
kIdPop, //!< Instruction 'pop'.
|
||||
kIdPssbb, //!< Instruction 'pssbb'.
|
||||
kIdPush, //!< Instruction 'push'.
|
||||
kIdQadd, //!< Instruction 'qadd'.
|
||||
kIdQadd16, //!< Instruction 'qadd16'.
|
||||
kIdQadd8, //!< Instruction 'qadd8'.
|
||||
kIdQasx, //!< Instruction 'qasx'.
|
||||
kIdQdadd, //!< Instruction 'qdadd'.
|
||||
kIdQdsub, //!< Instruction 'qdsub'.
|
||||
kIdQsax, //!< Instruction 'qsax'.
|
||||
kIdQsub, //!< Instruction 'qsub'.
|
||||
kIdQsub16, //!< Instruction 'qsub16'.
|
||||
kIdQsub8, //!< Instruction 'qsub8'.
|
||||
kIdRbit, //!< Instruction 'rbit'.
|
||||
kIdRev, //!< Instruction 'rev'.
|
||||
kIdRev16, //!< Instruction 'rev16'.
|
||||
kIdRevsh, //!< Instruction 'revsh'.
|
||||
kIdRfeda, //!< Instruction 'rfeda' (ARM).
|
||||
kIdRfedb, //!< Instruction 'rfedb' (ARM).
|
||||
kIdRfeia, //!< Instruction 'rfeia' (ARM).
|
||||
kIdRfeib, //!< Instruction 'rfeib' (ARM).
|
||||
kIdRor, //!< Instruction 'ror'.
|
||||
kIdRors, //!< Instruction 'rors'.
|
||||
kIdRrx, //!< Instruction 'rrx'.
|
||||
kIdRrxs, //!< Instruction 'rrxs'.
|
||||
kIdRsb, //!< Instruction 'rsb'.
|
||||
kIdRsbs, //!< Instruction 'rsbs'.
|
||||
kIdRsc, //!< Instruction 'rsc' (ARM).
|
||||
kIdRscs, //!< Instruction 'rscs' (ARM).
|
||||
kIdSadd16, //!< Instruction 'sadd16'.
|
||||
kIdSadd8, //!< Instruction 'sadd8'.
|
||||
kIdSasx, //!< Instruction 'sasx'.
|
||||
kIdSb, //!< Instruction 'sb' {SB}.
|
||||
kIdSbc, //!< Instruction 'sbc'.
|
||||
kIdSbcs, //!< Instruction 'sbcs'.
|
||||
kIdSbfx, //!< Instruction 'sbfx'.
|
||||
kIdSdiv, //!< Instruction 'sdiv' {IDIVA & IDIVT}.
|
||||
kIdSel, //!< Instruction 'sel'.
|
||||
kIdSetend, //!< Instruction 'setend' {ARMv8-}.
|
||||
kIdSetpan, //!< Instruction 'setpan' {PAN}.
|
||||
kIdSev, //!< Instruction 'sev'.
|
||||
kIdSevl, //!< Instruction 'sevl'.
|
||||
kIdSha1c, //!< Instruction 'sha1c' {SHA1}.
|
||||
kIdSha1h, //!< Instruction 'sha1h' {SHA1}.
|
||||
kIdSha1m, //!< Instruction 'sha1m' {SHA1}.
|
||||
kIdSha1p, //!< Instruction 'sha1p' {SHA1}.
|
||||
kIdSha1su0, //!< Instruction 'sha1su0' {SHA1}.
|
||||
kIdSha1su1, //!< Instruction 'sha1su1' {SHA1}.
|
||||
kIdSha256h, //!< Instruction 'sha256h' {SHA256}.
|
||||
kIdSha256h2, //!< Instruction 'sha256h2' {SHA256}.
|
||||
kIdSha256su0, //!< Instruction 'sha256su0' {SHA256}.
|
||||
kIdSha256su1, //!< Instruction 'sha256su1' {SHA256}.
|
||||
kIdShadd16, //!< Instruction 'shadd16'.
|
||||
kIdShadd8, //!< Instruction 'shadd8'.
|
||||
kIdShasx, //!< Instruction 'shasx'.
|
||||
kIdShsax, //!< Instruction 'shsax'.
|
||||
kIdShsub16, //!< Instruction 'shsub16'.
|
||||
kIdShsub8, //!< Instruction 'shsub8'.
|
||||
kIdSmc, //!< Instruction 'smc' {SECURITY}.
|
||||
kIdSmlabb, //!< Instruction 'smlabb'.
|
||||
kIdSmlabt, //!< Instruction 'smlabt'.
|
||||
kIdSmlad, //!< Instruction 'smlad'.
|
||||
kIdSmladx, //!< Instruction 'smladx'.
|
||||
kIdSmlal, //!< Instruction 'smlal'.
|
||||
kIdSmlalbb, //!< Instruction 'smlalbb'.
|
||||
kIdSmlalbt, //!< Instruction 'smlalbt'.
|
||||
kIdSmlald, //!< Instruction 'smlald'.
|
||||
kIdSmlaldx, //!< Instruction 'smlaldx'.
|
||||
kIdSmlals, //!< Instruction 'smlals' (ARM).
|
||||
kIdSmlaltb, //!< Instruction 'smlaltb'.
|
||||
kIdSmlaltt, //!< Instruction 'smlaltt'.
|
||||
kIdSmlatb, //!< Instruction 'smlatb'.
|
||||
kIdSmlatt, //!< Instruction 'smlatt'.
|
||||
kIdSmlawb, //!< Instruction 'smlawb'.
|
||||
kIdSmlawt, //!< Instruction 'smlawt'.
|
||||
kIdSmlsd, //!< Instruction 'smlsd'.
|
||||
kIdSmlsdx, //!< Instruction 'smlsdx'.
|
||||
kIdSmlsld, //!< Instruction 'smlsld'.
|
||||
kIdSmlsldx, //!< Instruction 'smlsldx'.
|
||||
kIdSmmla, //!< Instruction 'smmla'.
|
||||
kIdSmmlar, //!< Instruction 'smmlar'.
|
||||
kIdSmmls, //!< Instruction 'smmls'.
|
||||
kIdSmmlsr, //!< Instruction 'smmlsr'.
|
||||
kIdSmmul, //!< Instruction 'smmul'.
|
||||
kIdSmmulr, //!< Instruction 'smmulr'.
|
||||
kIdSmuad, //!< Instruction 'smuad'.
|
||||
kIdSmuadx, //!< Instruction 'smuadx'.
|
||||
kIdSmulbb, //!< Instruction 'smulbb'.
|
||||
kIdSmulbt, //!< Instruction 'smulbt'.
|
||||
kIdSmull, //!< Instruction 'smull'.
|
||||
kIdSmulls, //!< Instruction 'smulls' (ARM).
|
||||
kIdSmultb, //!< Instruction 'smultb'.
|
||||
kIdSmultt, //!< Instruction 'smultt'.
|
||||
kIdSmulwb, //!< Instruction 'smulwb'.
|
||||
kIdSmulwt, //!< Instruction 'smulwt'.
|
||||
kIdSmusd, //!< Instruction 'smusd'.
|
||||
kIdSmusdx, //!< Instruction 'smusdx'.
|
||||
kIdSrsda, //!< Instruction 'srsda' (ARM).
|
||||
kIdSrsdb, //!< Instruction 'srsdb' (ARM).
|
||||
kIdSrsia, //!< Instruction 'srsia' (ARM).
|
||||
kIdSrsib, //!< Instruction 'srsib' (ARM).
|
||||
kIdSsat, //!< Instruction 'ssat'.
|
||||
kIdSsat16, //!< Instruction 'ssat16'.
|
||||
kIdSsax, //!< Instruction 'ssax'.
|
||||
kIdSsbb, //!< Instruction 'ssbb'.
|
||||
kIdSsub16, //!< Instruction 'ssub16'.
|
||||
kIdSsub8, //!< Instruction 'ssub8'.
|
||||
kIdStl, //!< Instruction 'stl'.
|
||||
kIdStlb, //!< Instruction 'stlb'.
|
||||
kIdStlex, //!< Instruction 'stlex'.
|
||||
kIdStlexb, //!< Instruction 'stlexb'.
|
||||
kIdStlexd, //!< Instruction 'stlexd'.
|
||||
kIdStlexh, //!< Instruction 'stlexh'.
|
||||
kIdStlh, //!< Instruction 'stlh'.
|
||||
kIdStmda, //!< Instruction 'stmda' (ARM).
|
||||
kIdStmdb, //!< Instruction 'stmdb'.
|
||||
kIdStmia, //!< Instruction 'stmia'.
|
||||
kIdStmib, //!< Instruction 'stmib' (ARM).
|
||||
kIdStr, //!< Instruction 'str'.
|
||||
kIdStrb, //!< Instruction 'strb'.
|
||||
kIdStrbt, //!< Instruction 'strbt'.
|
||||
kIdStrd, //!< Instruction 'strd'.
|
||||
kIdStrex, //!< Instruction 'strex'.
|
||||
kIdStrexb, //!< Instruction 'strexb'.
|
||||
kIdStrexd, //!< Instruction 'strexd'.
|
||||
kIdStrexh, //!< Instruction 'strexh'.
|
||||
kIdStrh, //!< Instruction 'strh'.
|
||||
kIdStrht, //!< Instruction 'strht'.
|
||||
kIdStrt, //!< Instruction 'strt'.
|
||||
kIdSub, //!< Instruction 'sub'.
|
||||
kIdSubs, //!< Instruction 'subs'.
|
||||
kIdSvc, //!< Instruction 'svc'.
|
||||
kIdSxtab, //!< Instruction 'sxtab'.
|
||||
kIdSxtab16, //!< Instruction 'sxtab16'.
|
||||
kIdSxtah, //!< Instruction 'sxtah'.
|
||||
kIdSxtb, //!< Instruction 'sxtb'.
|
||||
kIdSxtb16, //!< Instruction 'sxtb16'.
|
||||
kIdSxth, //!< Instruction 'sxth'.
|
||||
kIdTbb, //!< Instruction 'tbb' (THUMB).
|
||||
kIdTbh, //!< Instruction 'tbh' (THUMB).
|
||||
kIdTeq, //!< Instruction 'teq'.
|
||||
kIdTst, //!< Instruction 'tst'.
|
||||
kIdUadd16, //!< Instruction 'uadd16'.
|
||||
kIdUadd8, //!< Instruction 'uadd8'.
|
||||
kIdUasx, //!< Instruction 'uasx'.
|
||||
kIdUbfx, //!< Instruction 'ubfx'.
|
||||
kIdUdf, //!< Instruction 'udf' (ARM).
|
||||
kIdUdiv, //!< Instruction 'udiv' {IDIVA & IDIVT}.
|
||||
kIdUhadd16, //!< Instruction 'uhadd16'.
|
||||
kIdUhadd8, //!< Instruction 'uhadd8'.
|
||||
kIdUhasx, //!< Instruction 'uhasx'.
|
||||
kIdUhsax, //!< Instruction 'uhsax'.
|
||||
kIdUhsub16, //!< Instruction 'uhsub16'.
|
||||
kIdUhsub8, //!< Instruction 'uhsub8'.
|
||||
kIdUmaal, //!< Instruction 'umaal'.
|
||||
kIdUmlal, //!< Instruction 'umlal'.
|
||||
kIdUmlals, //!< Instruction 'umlals' (ARM).
|
||||
kIdUmull, //!< Instruction 'umull'.
|
||||
kIdUmulls, //!< Instruction 'umulls' (ARM).
|
||||
kIdUqadd16, //!< Instruction 'uqadd16'.
|
||||
kIdUqadd8, //!< Instruction 'uqadd8'.
|
||||
kIdUqasx, //!< Instruction 'uqasx'.
|
||||
kIdUqsax, //!< Instruction 'uqsax'.
|
||||
kIdUqsub16, //!< Instruction 'uqsub16'.
|
||||
kIdUqsub8, //!< Instruction 'uqsub8'.
|
||||
kIdUsad8, //!< Instruction 'usad8'.
|
||||
kIdUsada8, //!< Instruction 'usada8'.
|
||||
kIdUsat, //!< Instruction 'usat'.
|
||||
kIdUsat16, //!< Instruction 'usat16'.
|
||||
kIdUsax, //!< Instruction 'usax'.
|
||||
kIdUsub16, //!< Instruction 'usub16'.
|
||||
kIdUsub8, //!< Instruction 'usub8'.
|
||||
kIdUxtab, //!< Instruction 'uxtab'.
|
||||
kIdUxtab16, //!< Instruction 'uxtab16'.
|
||||
kIdUxtah, //!< Instruction 'uxtah'.
|
||||
kIdUxtb, //!< Instruction 'uxtb'.
|
||||
kIdUxtb16, //!< Instruction 'uxtb16'.
|
||||
kIdUxth, //!< Instruction 'uxth'.
|
||||
kIdVaba, //!< Instruction 'vaba' {ASIMD}.
|
||||
kIdVabal, //!< Instruction 'vabal' {ASIMD}.
|
||||
kIdVabd, //!< Instruction 'vabd' {ASIMD ~FP16}.
|
||||
kIdVabdl, //!< Instruction 'vabdl' {ASIMD}.
|
||||
kIdVabs, //!< Instruction 'vabs' {ASIMD & FP ~FP16}.
|
||||
kIdVacge, //!< Instruction 'vacge' {ASIMD ~FP16}.
|
||||
kIdVacgt, //!< Instruction 'vacgt' {ASIMD ~FP16}.
|
||||
kIdVacle, //!< Instruction 'vacle' {ASIMD ~FP16}.
|
||||
kIdVaclt, //!< Instruction 'vaclt' {ASIMD ~FP16}.
|
||||
kIdVadd, //!< Instruction 'vadd' {ASIMD & FP ~FP16}.
|
||||
kIdVaddhn, //!< Instruction 'vaddhn' {ASIMD}.
|
||||
kIdVaddl, //!< Instruction 'vaddl' {ASIMD}.
|
||||
kIdVaddw, //!< Instruction 'vaddw' {ASIMD}.
|
||||
kIdVand, //!< Instruction 'vand' {ASIMD}.
|
||||
kIdVbic, //!< Instruction 'vbic' {ASIMD}.
|
||||
kIdVbif, //!< Instruction 'vbif' {ASIMD}.
|
||||
kIdVbit, //!< Instruction 'vbit' {ASIMD}.
|
||||
kIdVbsl, //!< Instruction 'vbsl' {ASIMD}.
|
||||
kIdVcadd, //!< Instruction 'vcadd' {FCMA ~FP16}.
|
||||
kIdVceq, //!< Instruction 'vceq' {ASIMD ~FP16}.
|
||||
kIdVcge, //!< Instruction 'vcge' {ASIMD ~FP16}.
|
||||
kIdVcgt, //!< Instruction 'vcgt' {ASIMD ~FP16}.
|
||||
kIdVcle, //!< Instruction 'vcle' {ASIMD ~FP16}.
|
||||
kIdVcls, //!< Instruction 'vcls' {ASIMD}.
|
||||
kIdVclt, //!< Instruction 'vclt' {ASIMD ~FP16}.
|
||||
kIdVclz, //!< Instruction 'vclz' {ASIMD}.
|
||||
kIdVcmla, //!< Instruction 'vcmla' {FCMA ~FP16}.
|
||||
kIdVcmp, //!< Instruction 'vcmp' {FP ~FP16}.
|
||||
kIdVcmpe, //!< Instruction 'vcmpe' {FP ~FP16}.
|
||||
kIdVcnt, //!< Instruction 'vcnt' {ASIMD}.
|
||||
kIdVcvt, //!< Instruction 'vcvt' {ASIMD & FP & FP16CONV}.
|
||||
kIdVcvta, //!< Instruction 'vcvta' {ASIMD & FP16CONV}.
|
||||
kIdVcvtb, //!< Instruction 'vcvtb' {BF16 & FP16CONV}.
|
||||
kIdVcvtm, //!< Instruction 'vcvtm' {ASIMD & FP16CONV}.
|
||||
kIdVcvtn, //!< Instruction 'vcvtn' {ASIMD & FP16CONV}.
|
||||
kIdVcvtp, //!< Instruction 'vcvtp' {ASIMD & FP16CONV}.
|
||||
kIdVcvtr, //!< Instruction 'vcvtr' {FP & FP16CONV}.
|
||||
kIdVcvtt, //!< Instruction 'vcvtt' {BF16 & FP16CONV}.
|
||||
kIdVdiv, //!< Instruction 'vdiv' {FP ~FP16}.
|
||||
kIdVdot, //!< Instruction 'vdot' {BF16}.
|
||||
kIdVdup, //!< Instruction 'vdup' {ASIMD}.
|
||||
kIdVeor, //!< Instruction 'veor' {ASIMD}.
|
||||
kIdVext, //!< Instruction 'vext' {ASIMD}.
|
||||
kIdVfma, //!< Instruction 'vfma' {ASIMD & VFPv4 ~FP16}.
|
||||
kIdVfmab, //!< Instruction 'vfmab' {BF16}.
|
||||
kIdVfmal, //!< Instruction 'vfmal' {FHM}.
|
||||
kIdVfmat, //!< Instruction 'vfmat' {BF16}.
|
||||
kIdVfms, //!< Instruction 'vfms' {ASIMD & VFPv4 ~FP16}.
|
||||
kIdVfmsl, //!< Instruction 'vfmsl' {FHM}.
|
||||
kIdVfnma, //!< Instruction 'vfnma' {VFPv4 ~FP16}.
|
||||
kIdVfnms, //!< Instruction 'vfnms' {VFPv4 ~FP16}.
|
||||
kIdVhadd, //!< Instruction 'vhadd' {ASIMD}.
|
||||
kIdVhsub, //!< Instruction 'vhsub' {ASIMD}.
|
||||
kIdVins, //!< Instruction 'vins' {ASIMD ~FP16}.
|
||||
kIdVjcvt, //!< Instruction 'vjcvt' {JSCVT}.
|
||||
kIdVld1, //!< Instruction 'vld1' {ASIMD}.
|
||||
kIdVld1r, //!< Instruction 'vld1r' {ASIMD}.
|
||||
kIdVld2, //!< Instruction 'vld2' {ASIMD}.
|
||||
kIdVld2r, //!< Instruction 'vld2r' {ASIMD}.
|
||||
kIdVld3, //!< Instruction 'vld3' {ASIMD}.
|
||||
kIdVld3r, //!< Instruction 'vld3r' {ASIMD}.
|
||||
kIdVld4, //!< Instruction 'vld4' {ASIMD}.
|
||||
kIdVld4r, //!< Instruction 'vld4r' {ASIMD}.
|
||||
kIdVldmdb, //!< Instruction 'vldmdb' {ASIMD}.
|
||||
kIdVldmia, //!< Instruction 'vldmia' {ASIMD}.
|
||||
kIdVldr, //!< Instruction 'vldr' {FP ~FP16}.
|
||||
kIdVmax, //!< Instruction 'vmax' {ASIMD ~FP16}.
|
||||
kIdVmaxnm, //!< Instruction 'vmaxnm' {ASIMD ~FP16}.
|
||||
kIdVmin, //!< Instruction 'vmin' {ASIMD ~FP16}.
|
||||
kIdVminnm, //!< Instruction 'vminnm' {ASIMD ~FP16}.
|
||||
kIdVmla, //!< Instruction 'vmla' {ASIMD & FP ~FP16}.
|
||||
kIdVmlal, //!< Instruction 'vmlal' {ASIMD}.
|
||||
kIdVmls, //!< Instruction 'vmls' {ASIMD & FP ~FP16}.
|
||||
kIdVmlsl, //!< Instruction 'vmlsl' {ASIMD}.
|
||||
kIdVmmla, //!< Instruction 'vmmla' {BF16}.
|
||||
kIdVmov, //!< Instruction 'vmov' {ASIMD & FP ~FP16}.
|
||||
kIdVmovl, //!< Instruction 'vmovl' {ASIMD}.
|
||||
kIdVmovn, //!< Instruction 'vmovn' {ASIMD}.
|
||||
kIdVmovx, //!< Instruction 'vmovx' {FP ~FP16}.
|
||||
kIdVmul, //!< Instruction 'vmul' {ASIMD & FP ~FP16}.
|
||||
kIdVmull, //!< Instruction 'vmull' {ASIMD}.
|
||||
kIdVmvn, //!< Instruction 'vmvn' {ASIMD}.
|
||||
kIdVneg, //!< Instruction 'vneg' {ASIMD & FP ~FP16}.
|
||||
kIdVnmla, //!< Instruction 'vnmla' {FP ~FP16}.
|
||||
kIdVnmls, //!< Instruction 'vnmls' {FP ~FP16}.
|
||||
kIdVnmul, //!< Instruction 'vnmul' {FP ~FP16}.
|
||||
kIdVorn, //!< Instruction 'vorn' {ASIMD}.
|
||||
kIdVorr, //!< Instruction 'vorr' {ASIMD}.
|
||||
kIdVpadal, //!< Instruction 'vpadal' {ASIMD}.
|
||||
kIdVpadd, //!< Instruction 'vpadd' {ASIMD ~FP16}.
|
||||
kIdVpaddl, //!< Instruction 'vpaddl' {ASIMD}.
|
||||
kIdVpmax, //!< Instruction 'vpmax' {ASIMD ~FP16}.
|
||||
kIdVpmin, //!< Instruction 'vpmin' {ASIMD ~FP16}.
|
||||
kIdVpop, //!< Instruction 'vpop' {ASIMD}.
|
||||
kIdVpush, //!< Instruction 'vpush' {ASIMD}.
|
||||
kIdVqabs, //!< Instruction 'vqabs' {ASIMD}.
|
||||
kIdVqadd, //!< Instruction 'vqadd' {ASIMD}.
|
||||
kIdVqdmlal, //!< Instruction 'vqdmlal' {ASIMD}.
|
||||
kIdVqdmlsl, //!< Instruction 'vqdmlsl' {ASIMD}.
|
||||
kIdVqdmulh, //!< Instruction 'vqdmulh' {ASIMD}.
|
||||
kIdVqdmull, //!< Instruction 'vqdmull' {ASIMD}.
|
||||
kIdVqmovn, //!< Instruction 'vqmovn' {ASIMD}.
|
||||
kIdVqmovun, //!< Instruction 'vqmovun' {ASIMD}.
|
||||
kIdVqneg, //!< Instruction 'vqneg' {ASIMD}.
|
||||
kIdVqrdmlah, //!< Instruction 'vqrdmlah' {RDM}.
|
||||
kIdVqrdmlsh, //!< Instruction 'vqrdmlsh' {RDM}.
|
||||
kIdVqrdmulh, //!< Instruction 'vqrdmulh' {ASIMD}.
|
||||
kIdVqrshl, //!< Instruction 'vqrshl' {ASIMD}.
|
||||
kIdVqrshrn, //!< Instruction 'vqrshrn' {ASIMD}.
|
||||
kIdVqrshrun, //!< Instruction 'vqrshrun' {ASIMD}.
|
||||
kIdVqshl, //!< Instruction 'vqshl' {ASIMD}.
|
||||
kIdVqshlu, //!< Instruction 'vqshlu' {ASIMD}.
|
||||
kIdVqshrn, //!< Instruction 'vqshrn' {ASIMD}.
|
||||
kIdVqshrun, //!< Instruction 'vqshrun' {ASIMD}.
|
||||
kIdVqsub, //!< Instruction 'vqsub' {ASIMD}.
|
||||
kIdVraddhn, //!< Instruction 'vraddhn' {ASIMD}.
|
||||
kIdVrecpe, //!< Instruction 'vrecpe' {ASIMD ~FP16}.
|
||||
kIdVrecps, //!< Instruction 'vrecps' {ASIMD ~FP16}.
|
||||
kIdVrev16, //!< Instruction 'vrev16' {ASIMD}.
|
||||
kIdVrev32, //!< Instruction 'vrev32' {ASIMD}.
|
||||
kIdVrev64, //!< Instruction 'vrev64' {ASIMD}.
|
||||
kIdVrhadd, //!< Instruction 'vrhadd' {ASIMD}.
|
||||
kIdVrinta, //!< Instruction 'vrinta' {ASIMD ~FP16}.
|
||||
kIdVrintm, //!< Instruction 'vrintm' {ASIMD ~FP16}.
|
||||
kIdVrintn, //!< Instruction 'vrintn' {ASIMD ~FP16}.
|
||||
kIdVrintp, //!< Instruction 'vrintp' {ASIMD ~FP16}.
|
||||
kIdVrintr, //!< Instruction 'vrintr' {ASIMD ~FP16}.
|
||||
kIdVrintx, //!< Instruction 'vrintx' {ASIMD ~FP16}.
|
||||
kIdVrintz, //!< Instruction 'vrintz' {ASIMD ~FP16}.
|
||||
kIdVrshl, //!< Instruction 'vrshl' {ASIMD}.
|
||||
kIdVrshr, //!< Instruction 'vrshr' {ASIMD}.
|
||||
kIdVrshrn, //!< Instruction 'vrshrn' {ASIMD}.
|
||||
kIdVrsqrte, //!< Instruction 'vrsqrte' {ASIMD ~FP16}.
|
||||
kIdVrsqrts, //!< Instruction 'vrsqrts' {ASIMD ~FP16}.
|
||||
kIdVrsra, //!< Instruction 'vrsra' {ASIMD}.
|
||||
kIdVrsubhn, //!< Instruction 'vrsubhn' {ASIMD}.
|
||||
kIdVsdot, //!< Instruction 'vsdot' {DOTPROD}.
|
||||
kIdVseleq, //!< Instruction 'vseleq' {ASIMD ~FP16}.
|
||||
kIdVselge, //!< Instruction 'vselge' {ASIMD ~FP16}.
|
||||
kIdVselgt, //!< Instruction 'vselgt' {ASIMD ~FP16}.
|
||||
kIdVselvs, //!< Instruction 'vselvs' {ASIMD ~FP16}.
|
||||
kIdVshl, //!< Instruction 'vshl' {ASIMD}.
|
||||
kIdVshll, //!< Instruction 'vshll' {ASIMD}.
|
||||
kIdVshr, //!< Instruction 'vshr' {ASIMD}.
|
||||
kIdVshrn, //!< Instruction 'vshrn' {ASIMD}.
|
||||
kIdVsli, //!< Instruction 'vsli' {ASIMD}.
|
||||
kIdVsmmla, //!< Instruction 'vsmmla' {I8MM}.
|
||||
kIdVsqrt, //!< Instruction 'vsqrt' {FP ~FP16}.
|
||||
kIdVsra, //!< Instruction 'vsra' {ASIMD}.
|
||||
kIdVsri, //!< Instruction 'vsri' {ASIMD}.
|
||||
kIdVst1, //!< Instruction 'vst1' {ASIMD}.
|
||||
kIdVst2, //!< Instruction 'vst2' {ASIMD}.
|
||||
kIdVst3, //!< Instruction 'vst3' {ASIMD}.
|
||||
kIdVst4, //!< Instruction 'vst4' {ASIMD}.
|
||||
kIdVstmdb, //!< Instruction 'vstmdb' {ASIMD}.
|
||||
kIdVstmia, //!< Instruction 'vstmia' {ASIMD}.
|
||||
kIdVstr, //!< Instruction 'vstr' {FP ~FP16}.
|
||||
kIdVsub, //!< Instruction 'vsub' {ASIMD & FP ~FP16}.
|
||||
kIdVsubhn, //!< Instruction 'vsubhn' {ASIMD}.
|
||||
kIdVsubl, //!< Instruction 'vsubl' {ASIMD}.
|
||||
kIdVsubw, //!< Instruction 'vsubw' {ASIMD}.
|
||||
kIdVsudot, //!< Instruction 'vsudot' {I8MM}.
|
||||
kIdVswp, //!< Instruction 'vswp' {ASIMD}.
|
||||
kIdVtbl, //!< Instruction 'vtbl' {ASIMD}.
|
||||
kIdVtbx, //!< Instruction 'vtbx' {ASIMD}.
|
||||
kIdVtrn, //!< Instruction 'vtrn' {ASIMD}.
|
||||
kIdVtst, //!< Instruction 'vtst' {ASIMD}.
|
||||
kIdVudot, //!< Instruction 'vudot' {DOTPROD}.
|
||||
kIdVummla, //!< Instruction 'vummla' {I8MM}.
|
||||
kIdVusdot, //!< Instruction 'vusdot' {I8MM}.
|
||||
kIdVusmmla, //!< Instruction 'vusmmla' {I8MM}.
|
||||
kIdVuzp, //!< Instruction 'vuzp' {ASIMD}.
|
||||
kIdVzip, //!< Instruction 'vzip' {ASIMD}.
|
||||
kIdWfe, //!< Instruction 'wfe'.
|
||||
kIdWfi, //!< Instruction 'wfi'.
|
||||
kIdYield, //!< Instruction 'yield'.
|
||||
_kIdCount
|
||||
// ----------------------------------------------------------------------------
|
||||
// ${a32::InstId:End}
|
||||
};
|
||||
|
||||
//! Tests whether the `inst_id` is defined (counts also Inst::kIdNone, which must be zero).
|
||||
//!
|
||||
//! \note This function required identifier to be without modifiers. If the given instruction id contains modifiers
|
||||
//! it would return false as modifiers overflow `_kIdCount`.
|
||||
static constexpr inline bool is_defined_id(InstId inst_id) noexcept {
|
||||
return inst_id < _kIdCount;
|
||||
}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32GLOBALS_H_INCLUDED
|
||||
223
asmjit/arm/a32instapi.cpp
Normal file
223
asmjit/arm/a32instapi.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core/api-build_p.h>
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
|
||||
#include <asmjit/support/support_p.h>
|
||||
#include <asmjit/arm/a32instapi_p.h>
|
||||
#include <asmjit/arm/a32instdb_p.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
namespace InstInternal {
|
||||
|
||||
// a32::InstAPI - Text
|
||||
// ===================
|
||||
|
||||
#ifndef ASMJIT_NO_TEXT
|
||||
Error inst_id_to_string(InstId inst_id, InstStringifyOptions options, String& output) noexcept {
|
||||
uint32_t real_id = inst_id & uint32_t(InstIdParts::kRealId);
|
||||
if (ASMJIT_UNLIKELY(!Inst::is_defined_id(real_id)))
|
||||
return make_error(Error::kInvalidInstruction);
|
||||
|
||||
return InstNameUtils::decode(InstDB::_inst_name_index_table[real_id], options, InstDB::_inst_name_string_table, output);
|
||||
}
|
||||
|
||||
InstId string_to_inst_id(const char* s, size_t len) noexcept {
|
||||
return InstNameUtils::find_instruction(s, len, InstDB::_inst_name_index_table, InstDB::_inst_name_string_table, InstDB::inst_name_index);
|
||||
}
|
||||
#endif // !ASMJIT_NO_TEXT
|
||||
|
||||
// a32::InstAPI - Validation
|
||||
// =========================
|
||||
|
||||
#ifndef ASMJIT_NO_VALIDATION
|
||||
Error validate(const BaseInst& inst, const Operand_* operands, size_t op_count, ValidationFlags validation_flags) noexcept {
|
||||
// TODO: AArch32 tooling.
|
||||
Support::maybe_unused(inst, operands, op_count, validation_flags);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
#endif // !ASMJIT_NO_VALIDATION
|
||||
|
||||
// a32::InstAPI - Introspection
|
||||
// ============================
|
||||
|
||||
#ifndef ASMJIT_NO_INTROSPECTION
|
||||
|
||||
struct InstRWInfoRecord {
|
||||
//! RWX information for each operand.
|
||||
uint8_t rwx[Globals::kMaxOpCount];
|
||||
//! Index to InstRWFlagsRecord table.
|
||||
uint8_t rw_flags_index;
|
||||
};
|
||||
|
||||
struct InstRWFlagsRecord {
|
||||
//! Read flags.
|
||||
CpuRWFlags r;
|
||||
//! Written flags.
|
||||
CpuRWFlags w;
|
||||
};
|
||||
|
||||
// ${a32::RWInfo:Begin}
|
||||
// ------------------- Automatically generated, do not edit -------------------
|
||||
static const constexpr InstRWInfoRecord inst_rw_info_data[] = {
|
||||
#define R uint8_t(OpRWFlags::kRead)
|
||||
#define W uint8_t(OpRWFlags::kWrite)
|
||||
#define X uint8_t(OpRWFlags::kRW)
|
||||
|
||||
{{ R, R, R, R, R, R }, 0}, // #0 [ref=105x]
|
||||
{{ W, R, R, R, R, R }, 1}, // #1 [ref=3x]
|
||||
{{ W, R, R, R, R, R }, 2}, // #2 [ref=1x]
|
||||
{{ W, R, R, R, R, R }, 0}, // #3 [ref=243x]
|
||||
{{ W, R, R, R, R, R }, 3}, // #4 [ref=5x]
|
||||
{{ X, R, R, R, R, R }, 0}, // #5 [ref=32x]
|
||||
{{ W, R, R, R, R, R }, 4}, // #6 [ref=11x]
|
||||
{{ R, R, R, R, R, R }, 3}, // #7 [ref=2x]
|
||||
{{ W, W, R, R, R, R }, 0}, // #8 [ref=6x]
|
||||
{{ W, R, R, R, R, R }, 5}, // #9 [ref=2x]
|
||||
{{ R, R, W, R, R, R }, 0}, // #10 [ref=2x]
|
||||
{{ R, R, W, W, R, R }, 0}, // #11 [ref=2x]
|
||||
{{ W, R, R, R, R, R }, 6}, // #12 [ref=20x]
|
||||
{{ W, R, R, R, R, R }, 7}, // #13 [ref=12x]
|
||||
{{ W, R, R, R, R, R }, 8}, // #14 [ref=1x]
|
||||
{{ X, X, R, R, R, R }, 0}, // #15 [ref=13x]
|
||||
{{ X, X, R, R, R, R }, 5}, // #16 [ref=2x]
|
||||
{{ X, X, R, R, R, R }, 6}, // #17 [ref=2x]
|
||||
{{ W, W, R, R, R, R }, 5}, // #18 [ref=2x]
|
||||
{{ R, R, R, R, R, R }, 4}, // #19 [ref=2x]
|
||||
{{ W, W, W, R, R, R }, 0}, // #20 [ref=2x]
|
||||
{{ W, W, W, W, R, R }, 0} // #21 [ref=2x]
|
||||
|
||||
#undef R
|
||||
#undef W
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const constexpr InstRWFlagsRecord instRWFlagsData[] = {
|
||||
{ CpuRWFlags::kNone, CpuRWFlags::kNone }, // #0 [ref=407x]
|
||||
{ CpuRWFlags::kARM_C, CpuRWFlags::kNone }, // #1 [ref=3x]
|
||||
{ CpuRWFlags::kARM_C, CpuRWFlags::kARM_C | CpuRWFlags::kARM_N | CpuRWFlags::kARM_V | CpuRWFlags::kARM_Z }, // #2 [ref=1x]
|
||||
{ CpuRWFlags::kNone, CpuRWFlags::kARM_C | CpuRWFlags::kARM_N | CpuRWFlags::kARM_V | CpuRWFlags::kARM_Z }, // #3 [ref=7x]
|
||||
{ CpuRWFlags::kNone, CpuRWFlags::kARM_C | CpuRWFlags::kARM_N | CpuRWFlags::kARM_Z }, // #4 [ref=13x]
|
||||
{ CpuRWFlags::kNone, CpuRWFlags::kARM_N | CpuRWFlags::kARM_Z }, // #5 [ref=6x]
|
||||
{ CpuRWFlags::kARM_Q, CpuRWFlags::kARM_Q }, // #6 [ref=22x]
|
||||
{ CpuRWFlags::kNone, CpuRWFlags::kARM_GE }, // #7 [ref=12x]
|
||||
{ CpuRWFlags::kARM_GE, CpuRWFlags::kNone } // #8 [ref=1x]
|
||||
};
|
||||
|
||||
static const constexpr uint8_t instRWInfoIndex[] {
|
||||
0, 1, 2, 3, 4, 3, 5, 5, 3, 3, 3, 6, 3, 6, 0, 3, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 7, 0, 0, 0, 3, 3, 3, 3, 3, 3,
|
||||
0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 8, 3, 3, 0, 0, 0, 0,
|
||||
3, 3, 3, 8, 3, 3, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 3, 6, 0, 0, 0, 0, 3, 9, 3, 0xFFu, 0xFFu, 5, 3, 10, 10, 11, 11, 3, 0,
|
||||
3, 9, 3, 6, 0, 3, 6, 3, 6, 3, 3, 0, 0, 0, 0xFFu, 0, 0, 12, 3, 3, 3, 12, 12, 3, 12, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, 6,
|
||||
1, 6, 3, 4, 3, 4, 13, 13, 13, 0, 1, 4, 3, 3, 14, 0, 0, 0, 0, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 0, 12, 12,
|
||||
12, 12, 15, 15, 15, 15, 15, 16, 15, 15, 12, 12, 12, 12, 12, 12, 17, 17, 3, 3, 3, 3, 3, 3, 12, 12, 3, 3, 8, 18, 3, 3, 3,
|
||||
3, 3, 3, 0, 0, 0, 0, 12, 12, 13, 0, 13, 13, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 3, 4, 0,
|
||||
3, 3, 3, 3, 3, 3, 0, 0, 19, 19, 13, 13, 13, 3, 0, 3, 3, 3, 3, 3, 3, 3, 15, 15, 16, 8, 18, 3, 3, 3, 3, 3, 3, 3, 3, 12,
|
||||
12, 13, 13, 13, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0xFFu, 0xFFu, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
5, 0, 0, 3, 0xFFu, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 5, 3, 5, 5, 5, 5, 3, 3, 3, 3, 0xFFu, 0xFFu, 0xFFu, 8, 20,
|
||||
20, 21, 21, 0, 0, 3, 3, 3, 3, 3, 5, 5, 5, 5, 3, 0xFFu, 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 0xFFu, 0xFFu, 5, 3, 3, 3, 3, 0, 0,
|
||||
3, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 5, 5, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 15, 3, 3, 15, 3, 3, 3, 3, 3, 15, 15, 0,
|
||||
0, 0
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
// ${a32::RWInfo:End}
|
||||
|
||||
Error query_rw_info(const BaseInst& inst, const Operand_* operands, size_t op_count, InstRWInfo* out) noexcept {
|
||||
uint32_t inst_id = inst.inst_id();
|
||||
uint32_t real_id = inst_id & uint32_t(InstIdParts::kRealId);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Inst::is_defined_id(real_id)))
|
||||
return make_error(Error::kInvalidInstruction);
|
||||
|
||||
out->_inst_flags = InstRWFlags::kNone;
|
||||
out->_op_count = uint8_t(op_count);
|
||||
out->_rm_feature = 0;
|
||||
out->_extra_reg.reset();
|
||||
|
||||
out->_read_flags = CpuRWFlags::kNone;
|
||||
out->_write_flags = CpuRWFlags::kNone;
|
||||
|
||||
size_t index = instRWInfoIndex[real_id];
|
||||
if (index < 0xFFu) {
|
||||
const InstRWInfoRecord& rwInfo = inst_rw_info_data[index];
|
||||
size_t rw_flags_index = rwInfo.rw_flags_index;
|
||||
|
||||
out->_read_flags = instRWFlagsData[rw_flags_index].r;
|
||||
out->_write_flags = instRWFlagsData[rw_flags_index].w;
|
||||
|
||||
for (size_t i = 0; i < op_count; i++) {
|
||||
uint32_t access = rwInfo.rwx[i];
|
||||
|
||||
OpRWInfo& rwOp = out->_operands[i];
|
||||
const Operand_& srcOp = operands[i];
|
||||
|
||||
if (!srcOp.is_reg_or_reg_list_or_mem()) {
|
||||
rwOp.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
rwOp._op_flags = OpRWFlags(access);
|
||||
rwOp._phys_id = Reg::kIdBad;
|
||||
rwOp._rm_size = 0;
|
||||
rwOp._reset_reserved();
|
||||
|
||||
uint64_t r_byte_mask = rwOp.is_read() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u;
|
||||
uint64_t w_byte_mask = rwOp.is_write() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u;
|
||||
|
||||
rwOp._read_byte_mask = r_byte_mask;
|
||||
rwOp._write_byte_mask = w_byte_mask;
|
||||
rwOp._extend_byte_mask = 0;
|
||||
rwOp._consecutive_lead_count = 0;
|
||||
|
||||
if (srcOp.is_mem()) {
|
||||
const Mem& mem_op = srcOp.as<Mem>();
|
||||
|
||||
if (mem_op.has_base()) {
|
||||
rwOp.add_op_flags(OpRWFlags::kMemBaseRead);
|
||||
}
|
||||
|
||||
if (mem_op.has_index()) {
|
||||
rwOp.add_op_flags(mem_op.is_pre_or_post() ? OpRWFlags::kMemIndexRW : OpRWFlags::kMemIndexRead);
|
||||
}
|
||||
}
|
||||
else if (srcOp.as<Vec>().has_element_index()) {
|
||||
// Only part of the vector is accessed if element index [] is used.
|
||||
uint32_t elementSize = data_type_size(inst.arm_dt());
|
||||
uint32_t element_index = srcOp.as<Vec>().element_index();
|
||||
|
||||
// NOTE: DataType must be present otherwise it's impossible to calculate the access flags.
|
||||
if (!elementSize)
|
||||
return make_error(Error::kInvalidInstruction);
|
||||
|
||||
uint64_t accessMask = uint64_t(Support::lsb_mask<uint32_t>(elementSize)) << (element_index * elementSize);
|
||||
rwOp._read_byte_mask &= accessMask;
|
||||
rwOp._write_byte_mask &= accessMask;
|
||||
}
|
||||
}
|
||||
return kErrorOk;
|
||||
}
|
||||
else {
|
||||
// TODO: [ARM] Not finished introspection.
|
||||
return make_error(Error::kInvalidState);
|
||||
}
|
||||
}
|
||||
|
||||
Error query_features(const BaseInst& inst, const Operand_* operands, size_t op_count, CpuFeatures* out) noexcept {
|
||||
// TODO: AArch32 tooling.
|
||||
Support::maybe_unused(inst, operands, op_count, out);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
#endif // !ASMJIT_NO_INTROSPECTION
|
||||
|
||||
} // {InstInternal}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32
|
||||
42
asmjit/arm/a32instapi_p.h
Normal file
42
asmjit/arm/a32instapi_p.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32INSTAPI_H_P_INCLUDED
|
||||
#define ASMJIT_ARM_A32INSTAPI_H_P_INCLUDED
|
||||
|
||||
#include <asmjit/core/codeholder.h>
|
||||
#include <asmjit/arm/a32instdb_p.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
namespace InstInternal {
|
||||
|
||||
#ifndef ASMJIT_NO_TEXT
|
||||
Error ASMJIT_CDECL inst_id_to_string(InstId inst_id, InstStringifyOptions options, String& output) noexcept;
|
||||
InstId ASMJIT_CDECL string_to_inst_id(const char* s, size_t len) noexcept;
|
||||
#endif // !ASMJIT_NO_TEXT
|
||||
|
||||
#ifndef ASMJIT_NO_VALIDATION
|
||||
Error ASMJIT_CDECL validate(const BaseInst& inst, const Operand_* operands, size_t op_count, ValidationFlags validation_flags) noexcept;
|
||||
#endif // !ASMJIT_NO_VALIDATION
|
||||
|
||||
#ifndef ASMJIT_NO_INTROSPECTION
|
||||
Error ASMJIT_CDECL query_rw_info(const BaseInst& inst, const Operand_* operands, size_t op_count, InstRWInfo* out) noexcept;
|
||||
Error ASMJIT_CDECL query_features(const BaseInst& inst, const Operand_* operands, size_t op_count, CpuFeatures* out) noexcept;
|
||||
#endif // !ASMJIT_NO_INTROSPECTION
|
||||
|
||||
} // {InstInternal}
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32INSTAPI_H_P_INCLUDED
|
||||
|
||||
547
asmjit/arm/a32instdb.cpp
Normal file
547
asmjit/arm/a32instdb.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#include <asmjit/core/api-build_p.h>
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
|
||||
#include <asmjit/arm/a32instdb_p.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
// a32::InstDB - Id <-> Name
|
||||
// =========================
|
||||
|
||||
#ifndef ASMJIT_NO_TEXT
|
||||
// ${a32::NameData:Begin}
|
||||
// ------------------- Automatically generated, do not edit -------------------
|
||||
const InstNameIndex InstDB::inst_name_index = {{
|
||||
{ Inst::kIdAdc , Inst::kIdAsrs + 1 },
|
||||
{ Inst::kIdB , Inst::kIdBxj + 1 },
|
||||
{ Inst::kIdCbnz , Inst::kIdCsdb + 1 },
|
||||
{ Inst::kIdDbg , Inst::kIdDsb + 1 },
|
||||
{ Inst::kIdEor , Inst::kIdEsb + 1 },
|
||||
{ Inst::kIdNone , Inst::kIdNone + 1 },
|
||||
{ Inst::kIdNone , Inst::kIdNone + 1 },
|
||||
{ Inst::kIdHlt , Inst::kIdHvc + 1 },
|
||||
{ Inst::kIdIsb , Inst::kIdItttt + 1 },
|
||||
{ Inst::kIdNone , Inst::kIdNone + 1 },
|
||||
{ Inst::kIdNone , Inst::kIdNone + 1 },
|
||||
{ Inst::kIdLda , Inst::kIdLsrs + 1 },
|
||||
{ Inst::kIdMcr , Inst::kIdMvns + 1 },
|
||||
{ Inst::kIdNop , Inst::kIdNop + 1 },
|
||||
{ Inst::kIdOrn , Inst::kIdOrrs + 1 },
|
||||
{ Inst::kIdPkhbt , Inst::kIdPush + 1 },
|
||||
{ Inst::kIdQadd , Inst::kIdQsub8 + 1 },
|
||||
{ Inst::kIdRbit , Inst::kIdRscs + 1 },
|
||||
{ Inst::kIdSadd16 , Inst::kIdSxth + 1 },
|
||||
{ Inst::kIdTbb , Inst::kIdTst + 1 },
|
||||
{ Inst::kIdUadd16 , Inst::kIdUxth + 1 },
|
||||
{ Inst::kIdVaba , Inst::kIdVzip + 1 },
|
||||
{ Inst::kIdWfe , Inst::kIdWfi + 1 },
|
||||
{ Inst::kIdNone , Inst::kIdNone + 1 },
|
||||
{ Inst::kIdYield , Inst::kIdYield + 1 },
|
||||
{ Inst::kIdNone , Inst::kIdNone + 1 }
|
||||
}, uint16_t(9)};
|
||||
|
||||
const char InstDB::_inst_name_string_table[] =
|
||||
"sha256su01h2vqrdmlaulhvqrshruncrc32cbwsha1sha1sushadd1shsub1smlalbtdxtbttsmlslsx"
|
||||
"tab1uhadd1uhsub1uqadd1uqsub1uxtab1vqdvqdmvqdmulvqmovvraddhvrsqrtevrsubhvusmsadd1"
|
||||
"8ssat1ssub1sxtb1uadd1usadausat1usub1uxtb1vrev164";
|
||||
|
||||
|
||||
const uint32_t InstDB::_inst_name_index_table[] = {
|
||||
0x80000000, // Small ''.
|
||||
0x80000C81, // Small 'adc'.
|
||||
0x80098C81, // Small 'adcs'.
|
||||
0x80001081, // Small 'add'.
|
||||
0x80099081, // Small 'adds'.
|
||||
0x80004881, // Small 'adr'.
|
||||
0x80024CA1, // Small 'aesd'.
|
||||
0x8002CCA1, // Small 'aese'.
|
||||
0x86D4CCA1, // Small 'aesimc'.
|
||||
0x8036CCA1, // Small 'aesmc'.
|
||||
0x800011C1, // Small 'and'.
|
||||
0x800991C1, // Small 'ands'.
|
||||
0x80004A61, // Small 'asr'.
|
||||
0x8009CA61, // Small 'asrs'.
|
||||
0x80000002, // Small 'b'.
|
||||
0x80000CC2, // Small 'bfc'.
|
||||
0x800024C2, // Small 'bfi'.
|
||||
0x80000D22, // Small 'bic'.
|
||||
0x80098D22, // Small 'bics'.
|
||||
0x800A4162, // Small 'bkpt'.
|
||||
0x80000182, // Small 'bl'.
|
||||
0x80006182, // Small 'blx'.
|
||||
0x80000302, // Small 'bx'.
|
||||
0x80002B02, // Small 'bxj'.
|
||||
0x800D3843, // Small 'cbnz'.
|
||||
0x80006843, // Small 'cbz'.
|
||||
0x84814983, // Small 'clrbhb'.
|
||||
0x8182C983, // Small 'clrex'.
|
||||
0x80006983, // Small 'clz'.
|
||||
0x800039A3, // Small 'cmn'.
|
||||
0x800041A3, // Small 'cmp'.
|
||||
0x80004E03, // Small 'cps'.
|
||||
0x8044CE03, // Small 'cpsid'.
|
||||
0x8054CE03, // Small 'cpsie'.
|
||||
0x85DF0E43, // Small 'crc32b'.
|
||||
0x0000701E, // Large 'crc32cb'.
|
||||
0x1001601E, // Large 'crc32c|h'.
|
||||
0x1025601E, // Large 'crc32c|w'.
|
||||
0x91DF0E43, // Small 'crc32h'.
|
||||
0xAFDF0E43, // Small 'crc32w'.
|
||||
0x80011263, // Small 'csdb'.
|
||||
0x80001C44, // Small 'dbg'.
|
||||
0x81C9C064, // Small 'dcps1'.
|
||||
0x81D9C064, // Small 'dcps2'.
|
||||
0x81E9C064, // Small 'dcps3'.
|
||||
0x800009A4, // Small 'dmb'.
|
||||
0x80000A64, // Small 'dsb'.
|
||||
0x800049E5, // Small 'eor'.
|
||||
0x8009C9E5, // Small 'eors'.
|
||||
0x800A1645, // Small 'eret'.
|
||||
0x80000A65, // Small 'esb'.
|
||||
0x80005188, // Small 'hlt'.
|
||||
0x80000EC8, // Small 'hvc'.
|
||||
0x80000A69, // Small 'isb'.
|
||||
0x80000289, // Small 'it'.
|
||||
0x80001689, // Small 'ite'.
|
||||
0x80029689, // Small 'itee'.
|
||||
0x80529689, // Small 'iteee'.
|
||||
0x81429689, // Small 'iteet'.
|
||||
0x800A1689, // Small 'itet'.
|
||||
0x805A1689, // Small 'itete'.
|
||||
0x814A1689, // Small 'itett'.
|
||||
0x80005289, // Small 'itt'.
|
||||
0x8002D289, // Small 'itte'.
|
||||
0x8052D289, // Small 'ittee'.
|
||||
0x8142D289, // Small 'ittet'.
|
||||
0x800A5289, // Small 'ittt'.
|
||||
0x805A5289, // Small 'ittte'.
|
||||
0x814A5289, // Small 'itttt'.
|
||||
0x8000048C, // Small 'lda'.
|
||||
0x8001048C, // Small 'ldab'.
|
||||
0x8182848C, // Small 'ldaex'.
|
||||
0x8582848C, // Small 'ldaexb'.
|
||||
0x8982848C, // Small 'ldaexd'.
|
||||
0x9182848C, // Small 'ldaexh'.
|
||||
0x8004048C, // Small 'ldah'.
|
||||
0x8012348C, // Small 'ldmda'.
|
||||
0x8022348C, // Small 'ldmdb'.
|
||||
0x8014B48C, // Small 'ldmia'.
|
||||
0x8024B48C, // Small 'ldmib'.
|
||||
0x8000488C, // Small 'ldr'.
|
||||
0x8001488C, // Small 'ldrb'.
|
||||
0x8141488C, // Small 'ldrbt'.
|
||||
0x8002488C, // Small 'ldrd'.
|
||||
0x8182C88C, // Small 'ldrex'.
|
||||
0x8582C88C, // Small 'ldrexb'.
|
||||
0x8982C88C, // Small 'ldrexd'.
|
||||
0x9182C88C, // Small 'ldrexh'.
|
||||
0x8004488C, // Small 'ldrh'.
|
||||
0x8144488C, // Small 'ldrht'.
|
||||
0x8029C88C, // Small 'ldrsb'.
|
||||
0xA829C88C, // Small 'ldrsbt'.
|
||||
0x8089C88C, // Small 'ldrsh'.
|
||||
0xA889C88C, // Small 'ldrsht'.
|
||||
0x800A488C, // Small 'ldrt'.
|
||||
0x8000326C, // Small 'lsl'.
|
||||
0x8009B26C, // Small 'lsls'.
|
||||
0x80004A6C, // Small 'lsr'.
|
||||
0x8009CA6C, // Small 'lsrs'.
|
||||
0x8000486D, // Small 'mcr'.
|
||||
0x800EC86D, // Small 'mcr2'.
|
||||
0x8009486D, // Small 'mcrr'.
|
||||
0x81D9486D, // Small 'mcrr2'.
|
||||
0x8000058D, // Small 'mla'.
|
||||
0x8009858D, // Small 'mlas'.
|
||||
0x80004D8D, // Small 'mls'.
|
||||
0x800059ED, // Small 'mov'.
|
||||
0x8009D9ED, // Small 'movs'.
|
||||
0x800A59ED, // Small 'movt'.
|
||||
0x800BD9ED, // Small 'movw'.
|
||||
0x80000E4D, // Small 'mrc'.
|
||||
0x800E8E4D, // Small 'mrc2'.
|
||||
0x8001CA4D, // Small 'mrrc'.
|
||||
0x81D1CA4D, // Small 'mrrc2'.
|
||||
0x80004E4D, // Small 'mrs'.
|
||||
0x80004A6D, // Small 'msr'.
|
||||
0x800032AD, // Small 'mul'.
|
||||
0x8009B2AD, // Small 'muls'.
|
||||
0x80003ACD, // Small 'mvn'.
|
||||
0x8009BACD, // Small 'mvns'.
|
||||
0x800041EE, // Small 'nop'.
|
||||
0x80003A4F, // Small 'orn'.
|
||||
0x8009BA4F, // Small 'orns'.
|
||||
0x80004A4F, // Small 'orr'.
|
||||
0x8009CA4F, // Small 'orrs'.
|
||||
0x81412170, // Small 'pkhbt'.
|
||||
0x802A2170, // Small 'pkhtb'.
|
||||
0x80001190, // Small 'pld'.
|
||||
0x800B9190, // Small 'pldw'.
|
||||
0x80002590, // Small 'pli'.
|
||||
0x800041F0, // Small 'pop'.
|
||||
0x80214E70, // Small 'pssbb'.
|
||||
0x80044EB0, // Small 'push'.
|
||||
0x80021031, // Small 'qadd'.
|
||||
0x10055061, // Large 'qadd1|6'.
|
||||
0x10A04061, // Large 'qadd|8'.
|
||||
0x800C4C31, // Small 'qasx'.
|
||||
0x80420491, // Small 'qdadd'.
|
||||
0x802ACC91, // Small 'qdsub'.
|
||||
0x800C0671, // Small 'qsax'.
|
||||
0x80015671, // Small 'qsub'.
|
||||
0x10055067, // Large 'qsub1|6'.
|
||||
0x10A04067, // Large 'qsub|8'.
|
||||
0x800A2452, // Small 'rbit'.
|
||||
0x800058B2, // Small 'rev'.
|
||||
0x000050CA, // Large 'rev16'.
|
||||
0x8089D8B2, // Small 'revsh'.
|
||||
0x801214D2, // Small 'rfeda'.
|
||||
0x802214D2, // Small 'rfedb'.
|
||||
0x801494D2, // Small 'rfeia'.
|
||||
0x802494D2, // Small 'rfeib'.
|
||||
0x800049F2, // Small 'ror'.
|
||||
0x8009C9F2, // Small 'rors'.
|
||||
0x80006252, // Small 'rrx'.
|
||||
0x8009E252, // Small 'rrxs'.
|
||||
0x80000A72, // Small 'rsb'.
|
||||
0x80098A72, // Small 'rsbs'.
|
||||
0x80000E72, // Small 'rsc'.
|
||||
0x80098E72, // Small 'rscs'.
|
||||
0x1005509B, // Large 'sadd1|6'.
|
||||
0x10A0409B, // Large 'sadd|8'.
|
||||
0x800C4C33, // Small 'sasx'.
|
||||
0x80000053, // Small 'sb'.
|
||||
0x80000C53, // Small 'sbc'.
|
||||
0x80098C53, // Small 'sbcs'.
|
||||
0x800C1853, // Small 'sbfx'.
|
||||
0x800B2493, // Small 'sdiv'.
|
||||
0x800030B3, // Small 'sel'.
|
||||
0x88E2D0B3, // Small 'setend'.
|
||||
0x9C1850B3, // Small 'setpan'.
|
||||
0x800058B3, // Small 'sev'.
|
||||
0x800658B3, // Small 'sevl'.
|
||||
0x803E0513, // Small 'sha1c'.
|
||||
0x808E0513, // Small 'sha1h'.
|
||||
0x80DE0513, // Small 'sha1m'.
|
||||
0x810E0513, // Small 'sha1p'.
|
||||
0x30064026, // Large 'sha1|su0'.
|
||||
0x1009602A, // Large 'sha1su|1'.
|
||||
0x10016000, // Large 'sha256|h'.
|
||||
0x200A6000, // Large 'sha256|h2'.
|
||||
0x00009000, // Large 'sha256su0'.
|
||||
0x10098000, // Large 'sha256su|1'.
|
||||
0x10056030, // Large 'shadd1|6'.
|
||||
0x10A05030, // Large 'shadd|8'.
|
||||
0x81898513, // Small 'shasx'.
|
||||
0x8180CD13, // Small 'shsax'.
|
||||
0x10056036, // Large 'shsub1|6'.
|
||||
0x10A05036, // Large 'shsub|8'.
|
||||
0x80000DB3, // Small 'smc'.
|
||||
0x8420B1B3, // Small 'smlabb'.
|
||||
0xA820B1B3, // Small 'smlabt'.
|
||||
0x8040B1B3, // Small 'smlad'.
|
||||
0xB040B1B3, // Small 'smladx'.
|
||||
0x80C0B1B3, // Small 'smlal'.
|
||||
0x1024603C, // Large 'smlalb|b'.
|
||||
0x1042603C, // Large 'smlalb|t'.
|
||||
0x88C0B1B3, // Small 'smlald'.
|
||||
0x2043503C, // Large 'smlal|dx'.
|
||||
0xA6C0B1B3, // Small 'smlals'.
|
||||
0x2045503C, // Large 'smlal|tb'.
|
||||
0x2047503C, // Large 'smlal|tt'.
|
||||
0x8540B1B3, // Small 'smlatb'.
|
||||
0xA940B1B3, // Small 'smlatt'.
|
||||
0x8570B1B3, // Small 'smlawb'.
|
||||
0xA970B1B3, // Small 'smlawt'.
|
||||
0x8049B1B3, // Small 'smlsd'.
|
||||
0xB049B1B3, // Small 'smlsdx'.
|
||||
0x88C9B1B3, // Small 'smlsld'.
|
||||
0x20435049, // Large 'smlsl|dx'.
|
||||
0x801635B3, // Small 'smmla'.
|
||||
0xA41635B3, // Small 'smmlar'.
|
||||
0x813635B3, // Small 'smmls'.
|
||||
0xA53635B3, // Small 'smmlsr'.
|
||||
0x80CAB5B3, // Small 'smmul'.
|
||||
0xA4CAB5B3, // Small 'smmulr'.
|
||||
0x8040D5B3, // Small 'smuad'.
|
||||
0xB040D5B3, // Small 'smuadx'.
|
||||
0x842655B3, // Small 'smulbb'.
|
||||
0xA82655B3, // Small 'smulbt'.
|
||||
0x80C655B3, // Small 'smull'.
|
||||
0xA6C655B3, // Small 'smulls'.
|
||||
0x854655B3, // Small 'smultb'.
|
||||
0xA94655B3, // Small 'smultt'.
|
||||
0x857655B3, // Small 'smulwb'.
|
||||
0xA97655B3, // Small 'smulwt'.
|
||||
0x8049D5B3, // Small 'smusd'.
|
||||
0xB049D5B3, // Small 'smusdx'.
|
||||
0x80124E53, // Small 'srsda'.
|
||||
0x80224E53, // Small 'srsdb'.
|
||||
0x8014CE53, // Small 'srsia'.
|
||||
0x8024CE53, // Small 'srsib'.
|
||||
0x800A0673, // Small 'ssat'.
|
||||
0x100550A1, // Large 'ssat1|6'.
|
||||
0x800C0673, // Small 'ssax'.
|
||||
0x80010A73, // Small 'ssbb'.
|
||||
0x100550A6, // Large 'ssub1|6'.
|
||||
0x10A040A6, // Large 'ssub|8'.
|
||||
0x80003293, // Small 'stl'.
|
||||
0x80013293, // Small 'stlb'.
|
||||
0x8182B293, // Small 'stlex'.
|
||||
0x8582B293, // Small 'stlexb'.
|
||||
0x8982B293, // Small 'stlexd'.
|
||||
0x9182B293, // Small 'stlexh'.
|
||||
0x80043293, // Small 'stlh'.
|
||||
0x80123693, // Small 'stmda'.
|
||||
0x80223693, // Small 'stmdb'.
|
||||
0x8014B693, // Small 'stmia'.
|
||||
0x8024B693, // Small 'stmib'.
|
||||
0x80004A93, // Small 'str'.
|
||||
0x80014A93, // Small 'strb'.
|
||||
0x81414A93, // Small 'strbt'.
|
||||
0x80024A93, // Small 'strd'.
|
||||
0x8182CA93, // Small 'strex'.
|
||||
0x8582CA93, // Small 'strexb'.
|
||||
0x8982CA93, // Small 'strexd'.
|
||||
0x9182CA93, // Small 'strexh'.
|
||||
0x80044A93, // Small 'strh'.
|
||||
0x81444A93, // Small 'strht'.
|
||||
0x800A4A93, // Small 'strt'.
|
||||
0x80000AB3, // Small 'sub'.
|
||||
0x80098AB3, // Small 'subs'.
|
||||
0x80000ED3, // Small 'svc'.
|
||||
0x8020D313, // Small 'sxtab'.
|
||||
0x1005604E, // Large 'sxtab1|6'.
|
||||
0x8080D313, // Small 'sxtah'.
|
||||
0x80015313, // Small 'sxtb'.
|
||||
0x100550AB, // Large 'sxtb1|6'.
|
||||
0x80045313, // Small 'sxth'.
|
||||
0x80000854, // Small 'tbb'.
|
||||
0x80002054, // Small 'tbh'.
|
||||
0x800044B4, // Small 'teq'.
|
||||
0x80005274, // Small 'tst'.
|
||||
0x100550B0, // Large 'uadd1|6'.
|
||||
0x10A040B0, // Large 'uadd|8'.
|
||||
0x800C4C35, // Small 'uasx'.
|
||||
0x800C1855, // Small 'ubfx'.
|
||||
0x80001895, // Small 'udf'.
|
||||
0x800B2495, // Small 'udiv'.
|
||||
0x10056054, // Large 'uhadd1|6'.
|
||||
0x10A05054, // Large 'uhadd|8'.
|
||||
0x81898515, // Small 'uhasx'.
|
||||
0x8180CD15, // Small 'uhsax'.
|
||||
0x1005605A, // Large 'uhsub1|6'.
|
||||
0x10A0505A, // Large 'uhsub|8'.
|
||||
0x80C085B5, // Small 'umaal'.
|
||||
0x80C0B1B5, // Small 'umlal'.
|
||||
0xA6C0B1B5, // Small 'umlals'.
|
||||
0x80C655B5, // Small 'umull'.
|
||||
0xA6C655B5, // Small 'umulls'.
|
||||
0x10056060, // Large 'uqadd1|6'.
|
||||
0x10A05060, // Large 'uqadd|8'.
|
||||
0x81898635, // Small 'uqasx'.
|
||||
0x8180CE35, // Small 'uqsax'.
|
||||
0x10056066, // Large 'uqsub1|6'.
|
||||
0x10A05066, // Large 'uqsub|8'.
|
||||
0x10A040B5, // Large 'usad|8'.
|
||||
0x10A050B5, // Large 'usada|8'.
|
||||
0x800A0675, // Small 'usat'.
|
||||
0x100550BA, // Large 'usat1|6'.
|
||||
0x800C0675, // Small 'usax'.
|
||||
0x100550BF, // Large 'usub1|6'.
|
||||
0x10A040BF, // Large 'usub|8'.
|
||||
0x8020D315, // Small 'uxtab'.
|
||||
0x1005606C, // Large 'uxtab1|6'.
|
||||
0x8080D315, // Small 'uxtah'.
|
||||
0x80015315, // Small 'uxtb'.
|
||||
0x100550C4, // Large 'uxtb1|6'.
|
||||
0x80045315, // Small 'uxth'.
|
||||
0x80008836, // Small 'vaba'.
|
||||
0x80C08836, // Small 'vabal'.
|
||||
0x80020836, // Small 'vabd'.
|
||||
0x80C20836, // Small 'vabdl'.
|
||||
0x80098836, // Small 'vabs'.
|
||||
0x80538C36, // Small 'vacge'.
|
||||
0x81438C36, // Small 'vacgt'.
|
||||
0x80560C36, // Small 'vacle'.
|
||||
0x81460C36, // Small 'vaclt'.
|
||||
0x80021036, // Small 'vadd'.
|
||||
0x9C821036, // Small 'vaddhn'.
|
||||
0x80C21036, // Small 'vaddl'.
|
||||
0x81721036, // Small 'vaddw'.
|
||||
0x80023836, // Small 'vand'.
|
||||
0x8001A456, // Small 'vbic'.
|
||||
0x80032456, // Small 'vbif'.
|
||||
0x800A2456, // Small 'vbit'.
|
||||
0x80064C56, // Small 'vbsl'.
|
||||
0x80420476, // Small 'vcadd'.
|
||||
0x80089476, // Small 'vceq'.
|
||||
0x80029C76, // Small 'vcge'.
|
||||
0x800A1C76, // Small 'vcgt'.
|
||||
0x8002B076, // Small 'vcle'.
|
||||
0x8009B076, // Small 'vcls'.
|
||||
0x800A3076, // Small 'vclt'.
|
||||
0x800D3076, // Small 'vclz'.
|
||||
0x80163476, // Small 'vcmla'.
|
||||
0x80083476, // Small 'vcmp'.
|
||||
0x80583476, // Small 'vcmpe'.
|
||||
0x800A3876, // Small 'vcnt'.
|
||||
0x800A5876, // Small 'vcvt'.
|
||||
0x801A5876, // Small 'vcvta'.
|
||||
0x802A5876, // Small 'vcvtb'.
|
||||
0x80DA5876, // Small 'vcvtm'.
|
||||
0x80EA5876, // Small 'vcvtn'.
|
||||
0x810A5876, // Small 'vcvtp'.
|
||||
0x812A5876, // Small 'vcvtr'.
|
||||
0x814A5876, // Small 'vcvtt'.
|
||||
0x800B2496, // Small 'vdiv'.
|
||||
0x800A3C96, // Small 'vdot'.
|
||||
0x80085496, // Small 'vdup'.
|
||||
0x80093CB6, // Small 'veor'.
|
||||
0x800A60B6, // Small 'vext'.
|
||||
0x8000B4D6, // Small 'vfma'.
|
||||
0x8020B4D6, // Small 'vfmab'.
|
||||
0x80C0B4D6, // Small 'vfmal'.
|
||||
0x8140B4D6, // Small 'vfmat'.
|
||||
0x8009B4D6, // Small 'vfms'.
|
||||
0x80C9B4D6, // Small 'vfmsl'.
|
||||
0x8016B8D6, // Small 'vfnma'.
|
||||
0x8136B8D6, // Small 'vfnms'.
|
||||
0x80420516, // Small 'vhadd'.
|
||||
0x802ACD16, // Small 'vhsub'.
|
||||
0x8009B936, // Small 'vins'.
|
||||
0x814B0D56, // Small 'vjcvt'.
|
||||
0x800E1196, // Small 'vld1'.
|
||||
0x812E1196, // Small 'vld1r'.
|
||||
0x800E9196, // Small 'vld2'.
|
||||
0x812E9196, // Small 'vld2r'.
|
||||
0x800F1196, // Small 'vld3'.
|
||||
0x812F1196, // Small 'vld3r'.
|
||||
0x800F9196, // Small 'vld4'.
|
||||
0x812F9196, // Small 'vld4r'.
|
||||
0x84469196, // Small 'vldmdb'.
|
||||
0x82969196, // Small 'vldmia'.
|
||||
0x80091196, // Small 'vldr'.
|
||||
0x800C05B6, // Small 'vmax'.
|
||||
0x9AEC05B6, // Small 'vmaxnm'.
|
||||
0x800725B6, // Small 'vmin'.
|
||||
0x9AE725B6, // Small 'vminnm'.
|
||||
0x8000B1B6, // Small 'vmla'.
|
||||
0x80C0B1B6, // Small 'vmlal'.
|
||||
0x8009B1B6, // Small 'vmls'.
|
||||
0x80C9B1B6, // Small 'vmlsl'.
|
||||
0x801635B6, // Small 'vmmla'.
|
||||
0x800B3DB6, // Small 'vmov'.
|
||||
0x80CB3DB6, // Small 'vmovl'.
|
||||
0x80EB3DB6, // Small 'vmovn'.
|
||||
0x818B3DB6, // Small 'vmovx'.
|
||||
0x800655B6, // Small 'vmul'.
|
||||
0x80C655B6, // Small 'vmull'.
|
||||
0x800759B6, // Small 'vmvn'.
|
||||
0x800395D6, // Small 'vneg'.
|
||||
0x801635D6, // Small 'vnmla'.
|
||||
0x813635D6, // Small 'vnmls'.
|
||||
0x80CAB5D6, // Small 'vnmul'.
|
||||
0x800749F6, // Small 'vorn'.
|
||||
0x800949F6, // Small 'vorr'.
|
||||
0x98120616, // Small 'vpadal'.
|
||||
0x80420616, // Small 'vpadd'.
|
||||
0x98420616, // Small 'vpaddl'.
|
||||
0x8180B616, // Small 'vpmax'.
|
||||
0x80E4B616, // Small 'vpmin'.
|
||||
0x80083E16, // Small 'vpop'.
|
||||
0x8089D616, // Small 'vpush'.
|
||||
0x81310636, // Small 'vqabs'.
|
||||
0x80420636, // Small 'vqadd'.
|
||||
0x403D3072, // Large 'vqd|mlal'.
|
||||
0x404A3072, // Large 'vqd|mlsl'.
|
||||
0x30134075, // Large 'vqdm|ulh'.
|
||||
0x10116079, // Large 'vqdmul|l'.
|
||||
0x9D67B636, // Small 'vqmovn'.
|
||||
0x201C507F, // Large 'vqmov|un'.
|
||||
0x8072BA36, // Small 'vqneg'.
|
||||
0x1001700C, // Large 'vqrdmla|h'.
|
||||
0x2000600C, // Large 'vqrdml|sh'.
|
||||
0x3013500C, // Large 'vqrdm|ulh'.
|
||||
0x9889CA36, // Small 'vqrshl'.
|
||||
0x101D6016, // Large 'vqrshr|n'.
|
||||
0x00008016, // Large 'vqrshrun'.
|
||||
0x80C44E36, // Small 'vqshl'.
|
||||
0xAAC44E36, // Small 'vqshlu'.
|
||||
0x9D244E36, // Small 'vqshrn'.
|
||||
0x5019200C, // Large 'vq|shrun'.
|
||||
0x802ACE36, // Small 'vqsub'.
|
||||
0x101D6084, // Large 'vraddh|n'.
|
||||
0x8B019656, // Small 'vrecpe'.
|
||||
0xA7019656, // Small 'vrecps'.
|
||||
0x100550C9, // Large 'vrev1|6'.
|
||||
0xBBEB1656, // Small 'vrev32'.
|
||||
0x20CE40C9, // Large 'vrev|64'.
|
||||
0x8840A256, // Small 'vrhadd'.
|
||||
0x83472656, // Small 'vrinta'.
|
||||
0x9B472656, // Small 'vrintm'.
|
||||
0x9D472656, // Small 'vrintn'.
|
||||
0xA1472656, // Small 'vrintp'.
|
||||
0xA5472656, // Small 'vrintr'.
|
||||
0xB1472656, // Small 'vrintx'.
|
||||
0xB5472656, // Small 'vrintz'.
|
||||
0x80C44E56, // Small 'vrshl'.
|
||||
0x81244E56, // Small 'vrshr'.
|
||||
0x9D244E56, // Small 'vrshrn'.
|
||||
0x0000708A, // Large 'vrsqrte'.
|
||||
0x1000608A, // Large 'vrsqrt|s'.
|
||||
0x80194E56, // Small 'vrsra'.
|
||||
0x101D6091, // Large 'vrsubh|n'.
|
||||
0x81479276, // Small 'vsdot'.
|
||||
0xA2561676, // Small 'vseleq'.
|
||||
0x8A761676, // Small 'vselge'.
|
||||
0xA8761676, // Small 'vselgt'.
|
||||
0xA7661676, // Small 'vselvs'.
|
||||
0x80062276, // Small 'vshl'.
|
||||
0x80C62276, // Small 'vshll'.
|
||||
0x80092276, // Small 'vshr'.
|
||||
0x80E92276, // Small 'vshrn'.
|
||||
0x8004B276, // Small 'vsli'.
|
||||
0x82C6B676, // Small 'vsmmla'.
|
||||
0x81494676, // Small 'vsqrt'.
|
||||
0x8000CA76, // Small 'vsra'.
|
||||
0x8004CA76, // Small 'vsri'.
|
||||
0x800E5276, // Small 'vst1'.
|
||||
0x800ED276, // Small 'vst2'.
|
||||
0x800F5276, // Small 'vst3'.
|
||||
0x800FD276, // Small 'vst4'.
|
||||
0x8446D276, // Small 'vstmdb'.
|
||||
0x8296D276, // Small 'vstmia'.
|
||||
0x80095276, // Small 'vstr'.
|
||||
0x80015676, // Small 'vsub'.
|
||||
0x9C815676, // Small 'vsubhn'.
|
||||
0x80C15676, // Small 'vsubl'.
|
||||
0x81715676, // Small 'vsubw'.
|
||||
0xA8F25676, // Small 'vsudot'.
|
||||
0x80085E76, // Small 'vswp'.
|
||||
0x80060A96, // Small 'vtbl'.
|
||||
0x800C0A96, // Small 'vtbx'.
|
||||
0x80074A96, // Small 'vtrn'.
|
||||
0x800A4E96, // Small 'vtst'.
|
||||
0x814792B6, // Small 'vudot'.
|
||||
0x82C6B6B6, // Small 'vummla'.
|
||||
0xA8F24EB6, // Small 'vusdot'.
|
||||
0x30104097, // Large 'vusm|mla'.
|
||||
0x80086AB6, // Small 'vuzp'.
|
||||
0x80082756, // Small 'vzip'.
|
||||
0x800014D7, // Small 'wfe'.
|
||||
0x800024D7, // Small 'wfi'.
|
||||
0x80461539 // Small 'yield'.
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
// ${a32::NameData:End}
|
||||
|
||||
#endif // !ASMJIT_NO_TEXT
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_AARCH32
|
||||
0
asmjit/arm/a32instdb.h
Normal file
0
asmjit/arm/a32instdb.h
Normal file
38
asmjit/arm/a32instdb_p.h
Normal file
38
asmjit/arm/a32instdb_p.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32INSTDB_H_P_INCLUDED
|
||||
#define ASMJIT_ARM_A32INSTDB_H_P_INCLUDED
|
||||
|
||||
#include <asmjit/core/codeholder.h>
|
||||
#include <asmjit/core/instdb_p.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
namespace InstDB {
|
||||
|
||||
// a32::InstDB - Tables
|
||||
// ====================
|
||||
|
||||
#ifndef ASMJIT_NO_TEXT
|
||||
extern const InstNameIndex inst_name_index;
|
||||
extern const char _inst_name_string_table[];
|
||||
extern const uint32_t _inst_name_index_table[];
|
||||
#endif // !ASMJIT_NO_TEXT
|
||||
|
||||
} // {InstDB}
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32INSTDB_H_P_INCLUDED
|
||||
|
||||
803
asmjit/arm/a32operand.h
Normal file
803
asmjit/arm/a32operand.h
Normal file
@@ -0,0 +1,803 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_A32OPERAND_H_INCLUDED
|
||||
#define ASMJIT_ARM_A32OPERAND_H_INCLUDED
|
||||
|
||||
#include <asmjit/core/operand.h>
|
||||
#include <asmjit/arm/a32globals.h>
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
|
||||
//! \addtogroup asmjit_a32
|
||||
//! \{
|
||||
|
||||
//! General purpose register (AArch32).
|
||||
class Gp : public UniGp {
|
||||
public:
|
||||
ASMJIT_DEFINE_ABSTRACT_REG(Gp, UniGp)
|
||||
|
||||
//! \name Constants
|
||||
//! \{
|
||||
|
||||
//! Special register id.
|
||||
enum Id : uint32_t {
|
||||
//! Frame pointer register id.
|
||||
kIdFP = 11u,
|
||||
//! Stack register id.
|
||||
kIdSP = 13u,
|
||||
//! Link register id.
|
||||
kIdLR = 14u,
|
||||
//! Program counter register id.
|
||||
kIdPC = 15u
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Static Constructors
|
||||
//! \{
|
||||
|
||||
//! Creates a new 32-bit low general purpose register (R) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp make_r32(uint32_t reg_id) noexcept { return Gp(signature_of_t<RegType::kGp32>(), reg_id); }
|
||||
|
||||
//! Creates a new 32-bit low general purpose register (R) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp make_r(uint32_t reg_id) noexcept { return make_r32(reg_id); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Gp Register Accessors
|
||||
//! \{
|
||||
|
||||
//! Test whether this register is FP register.
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_fp() const noexcept { return id() == kIdFP; }
|
||||
|
||||
//! Test whether this register is SP register.
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_sp() const noexcept { return id() == kIdSP; }
|
||||
|
||||
//! Test whether this register is LR register.
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_lr() const noexcept { return id() == kIdLR; }
|
||||
|
||||
//! Test whether this register is PC register.
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_pc() const noexcept { return id() == kIdPC; }
|
||||
|
||||
//! Returns whether the register contains a shift operation predicate
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR bool hast_shift_op() const noexcept { return predicate() != 0u; }
|
||||
|
||||
//! Returns shift operation predicate.
|
||||
ASMJIT_INLINE_CONSTEXPR ShiftOp shift_op() const noexcept { return ShiftOp(predicate()); }
|
||||
|
||||
//! Sets a shift operation predicate to `op`.
|
||||
ASMJIT_INLINE_CONSTEXPR void set_shift_op(ShiftOp op) noexcept { set_predicate(uint32_t(op)); }
|
||||
|
||||
//! Resets a shift operation predicate.
|
||||
ASMJIT_INLINE_CONSTEXPR void reset_shift_op() noexcept { return reset_predicate(); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Clone
|
||||
//! \{
|
||||
|
||||
//! Clones the register with assigned shift operation predicate `op`.
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Gp shifted(ShiftOp op) const noexcept {
|
||||
Gp r(*this);
|
||||
r.set_shift_op(op);
|
||||
return r;
|
||||
}
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Vector register (AArch32).
|
||||
class Vec : public UniVec {
|
||||
public:
|
||||
ASMJIT_DEFINE_ABSTRACT_REG(Vec, UniVec)
|
||||
|
||||
//! \cond
|
||||
|
||||
// Register has element index (1 bit).
|
||||
// |........|........|X.......|........|
|
||||
static inline constexpr uint32_t kSignatureRegElementFlagShift = 15;
|
||||
static inline constexpr uint32_t kSignatureRegElementFlagMask = 0x01 << kSignatureRegElementFlagShift;
|
||||
|
||||
// Register element index (4 bits).
|
||||
// |........|....XXXX|........|........|
|
||||
static inline constexpr uint32_t kSignatureRegElementIndexShift = 16;
|
||||
static inline constexpr uint32_t kSignatureRegElementIndexMask = 0x0F << kSignatureRegElementIndexShift;
|
||||
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR OperandSignature _make_element_access_signature(uint32_t element_index) noexcept {
|
||||
return OperandSignature{
|
||||
uint32_t(RegTraits<RegType::kVec128>::kSignature) |
|
||||
uint32_t(kSignatureRegElementFlagMask) |
|
||||
(uint32_t(element_index << kSignatureRegElementIndexShift))
|
||||
};
|
||||
}
|
||||
|
||||
//! \endcond
|
||||
|
||||
//! \name Static Constructors
|
||||
//! \{
|
||||
|
||||
//! Creates a new 32-bit vector register (S) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_v32(uint32_t reg_id) noexcept { return Vec(signature_of_t<RegType::kVec32>(), reg_id); }
|
||||
|
||||
//! Creates a new 64-bit vector register (D) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_v64(uint32_t reg_id) noexcept { return Vec(signature_of_t<RegType::kVec64>(), reg_id); }
|
||||
|
||||
//! Creates a new 128-bit vector register (Q) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_v128(uint32_t reg_id) noexcept { return Vec(signature_of_t<RegType::kVec128>(), reg_id); }
|
||||
|
||||
//! Creates a new 32-bit vector register (S) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_s(uint32_t reg_id) noexcept { return make_v32(reg_id); }
|
||||
|
||||
//! Creates a new 64-bit vector register (D) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_d(uint32_t reg_id) noexcept { return make_v64(reg_id); }
|
||||
|
||||
//! Creates a new 128-bit vector register (Q) having the given register id `reg_id`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_q(uint32_t reg_id) noexcept { return make_v128(reg_id); }
|
||||
|
||||
//! Creates a new 128-bit vector of type specified by `element_type` and `element_index`.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec make_v128_with_element_index(uint32_t element_index, uint32_t reg_id) noexcept {
|
||||
return Vec(_make_element_access_signature(element_index), reg_id);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Vector Register Accessors
|
||||
//! \{
|
||||
|
||||
//! Clones and casts the register to a 32-bit S register (element type & index is not cloned).
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec v32() const noexcept { return make_v32(id()); }
|
||||
|
||||
//! Clones and casts the register to a 64-bit D register (element type & index is not cloned).
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec v64() const noexcept { return make_v64(id()); }
|
||||
|
||||
//! Clones and casts the register to a 128-bit Q register (element type & index is not cloned).
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec v128() const noexcept { return make_v128(id()); }
|
||||
|
||||
//! Clones and casts the register to a 32-bit S register (element type & index is not cloned).
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec s() const noexcept { return make_v32(id()); }
|
||||
|
||||
//! Clones and casts the register to a 64-bit D register (element type & index is not cloned).
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec d() const noexcept { return make_v64(id()); }
|
||||
|
||||
//! Clones and casts the register to a 128-bit Q register (element type & index is not cloned).
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec q() const noexcept { return make_v128(id()); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Element Index Accessors
|
||||
//! \{
|
||||
|
||||
//! Returns whether the register has element index (it's an element index access).
|
||||
ASMJIT_INLINE_CONSTEXPR bool has_element_index() const noexcept {
|
||||
return _signature.has_field<kSignatureRegElementFlagMask>();
|
||||
}
|
||||
|
||||
//! Returns element index of the register.
|
||||
ASMJIT_INLINE_CONSTEXPR uint32_t element_index() const noexcept {
|
||||
return _signature.get_field<kSignatureRegElementIndexMask>();
|
||||
}
|
||||
|
||||
//! Sets element index of the register to `element_type`.
|
||||
ASMJIT_INLINE_CONSTEXPR void set_element_index(uint32_t element_index) noexcept {
|
||||
_signature |= kSignatureRegElementFlagMask;
|
||||
_signature.set_field<kSignatureRegElementIndexMask>(element_index);
|
||||
}
|
||||
|
||||
//! Resets element index of the register.
|
||||
ASMJIT_INLINE_CONSTEXPR void reset_element_index() noexcept {
|
||||
_signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask);
|
||||
}
|
||||
|
||||
//! Clones a vector register with element access enabled at the given `element_index`.
|
||||
[[nodiscard]]
|
||||
ASMJIT_INLINE_CONSTEXPR Vec at(uint32_t element_index) const noexcept {
|
||||
return Vec((signature() & ~kSignatureRegElementIndexMask) | (element_index << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id());
|
||||
}
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Register-list of 32-bit GP registers.
|
||||
class GpList : public RegListT<Gp> {
|
||||
public:
|
||||
//! \name Constants
|
||||
//! \{
|
||||
|
||||
static inline constexpr uint32_t kSignature =
|
||||
Signature::from_op_type(OperandType::kRegList).bits() | (RegTraits<RegType::kGp32>::kSignature & ~Signature::kOpTypeMask);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a dummy register-list operand.
|
||||
ASMJIT_INLINE_NODEBUG constexpr GpList() noexcept
|
||||
: RegListT<Gp>(Signature{kSignature}, RegMask(0)) {}
|
||||
|
||||
//! Creates a register-list operand which is the same as `other` .
|
||||
ASMJIT_INLINE_NODEBUG constexpr GpList(const GpList& other) noexcept
|
||||
: RegListT<Gp>(other) {}
|
||||
|
||||
//! Creates a register-list operand initialized to the given `regMask`.
|
||||
ASMJIT_INLINE_NODEBUG explicit constexpr GpList(RegMask regMask) noexcept
|
||||
: RegListT<Gp>(Signature{kSignature}, regMask) {}
|
||||
|
||||
//! Creates a register-list operand initialized to `regs`.
|
||||
ASMJIT_INLINE_NODEBUG explicit GpList(std::initializer_list<Gp> regs) noexcept
|
||||
: RegListT(Signature{kSignature}, regs) {}
|
||||
|
||||
ASMJIT_INLINE_NODEBUG explicit GpList(Globals::NoInit_) noexcept
|
||||
: RegListT<Gp>(Globals::NoInit) {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
ASMJIT_INLINE_NODEBUG GpList& operator=(const GpList& other) noexcept = default;
|
||||
|
||||
ASMJIT_INLINE_NODEBUG GpList& operator|=(const GpList& other) noexcept { add_list(other); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG GpList& operator&=(const GpList& other) noexcept { and_list(other); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG GpList& operator^=(const GpList& other) noexcept { xor_list(other); return *this; }
|
||||
|
||||
ASMJIT_INLINE_NODEBUG GpList operator|(const GpList& other) const noexcept { return GpList(list() | other.list()); }
|
||||
ASMJIT_INLINE_NODEBUG GpList operator&(const GpList& other) const noexcept { return GpList(list() & other.list()); }
|
||||
ASMJIT_INLINE_NODEBUG GpList operator^(const GpList& other) const noexcept { return GpList(list() ^ other.list()); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Register-list of 32-bit (vector) S registers.
|
||||
class VecSList : public RegListT<Vec> {
|
||||
public:
|
||||
//! \name Constants
|
||||
//! \{
|
||||
|
||||
static inline constexpr uint32_t kSignature =
|
||||
Signature::from_op_type(OperandType::kRegList).bits() | (RegTraits<RegType::kVec32>::kSignature & ~Signature::kOpTypeMask);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a dummy register-list operand.
|
||||
ASMJIT_INLINE_NODEBUG constexpr VecSList() noexcept
|
||||
: RegListT<Vec>(Signature{kSignature}, RegMask(0)) {}
|
||||
|
||||
//! Creates a register-list operand which is the same as `other` .
|
||||
ASMJIT_INLINE_NODEBUG constexpr VecSList(const VecSList& other) noexcept
|
||||
: RegListT<Vec>(other) {}
|
||||
|
||||
//! Creates a register-list operand initialized to the given `regMask`.
|
||||
ASMJIT_INLINE_NODEBUG explicit constexpr VecSList(RegMask regMask) noexcept
|
||||
: RegListT<Vec>(Signature{kSignature}, regMask) {}
|
||||
|
||||
//! Creates a register-list operand initialized to `regs`.
|
||||
ASMJIT_INLINE_NODEBUG explicit VecSList(std::initializer_list<Vec> regs) noexcept
|
||||
: RegListT(Signature{kSignature}, regs) {}
|
||||
|
||||
ASMJIT_INLINE_NODEBUG explicit VecSList(Globals::NoInit_) noexcept
|
||||
: RegListT<Vec>(Globals::NoInit) {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
ASMJIT_INLINE_NODEBUG VecSList& operator=(const VecSList& other) noexcept = default;
|
||||
|
||||
ASMJIT_INLINE_NODEBUG VecSList& operator|=(const VecSList& other) noexcept { add_list(other); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG VecSList& operator&=(const VecSList& other) noexcept { and_list(other); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG VecSList& operator^=(const VecSList& other) noexcept { xor_list(other); return *this; }
|
||||
|
||||
ASMJIT_INLINE_NODEBUG VecSList operator|(const VecSList& other) const noexcept { return VecSList(list() | other.list()); }
|
||||
ASMJIT_INLINE_NODEBUG VecSList operator&(const VecSList& other) const noexcept { return VecSList(list() & other.list()); }
|
||||
ASMJIT_INLINE_NODEBUG VecSList operator^(const VecSList& other) const noexcept { return VecSList(list() ^ other.list()); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Register-list of 32-bit (vector) D registers.
|
||||
class VecDList : public RegListT<Vec> {
|
||||
public:
|
||||
//! \name Constants
|
||||
//! \{
|
||||
|
||||
static inline constexpr uint32_t kSignature =
|
||||
Signature::from_op_type(OperandType::kRegList).bits() | (RegTraits<RegType::kVec64>::kSignature & ~Signature::kOpTypeMask);
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Creates a dummy register-list operand.
|
||||
ASMJIT_INLINE_NODEBUG constexpr VecDList() noexcept
|
||||
: RegListT<Vec>(Signature{kSignature}, RegMask(0)) {}
|
||||
|
||||
//! Creates a register-list operand which is the same as `other` .
|
||||
ASMJIT_INLINE_NODEBUG constexpr VecDList(const VecDList& other) noexcept
|
||||
: RegListT<Vec>(other) {}
|
||||
|
||||
//! Creates a register-list operand initialized to the given `regMask`.
|
||||
ASMJIT_INLINE_NODEBUG explicit constexpr VecDList(RegMask regMask) noexcept
|
||||
: RegListT<Vec>(Signature{kSignature}, regMask) {}
|
||||
|
||||
//! Creates a register-list operand initialized to `regs`.
|
||||
ASMJIT_INLINE_NODEBUG explicit VecDList(std::initializer_list<Vec> regs) noexcept
|
||||
: RegListT(Signature{kSignature}, regs) {}
|
||||
|
||||
ASMJIT_INLINE_NODEBUG explicit VecDList(Globals::NoInit_) noexcept
|
||||
: RegListT<Vec>(Globals::NoInit) {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
ASMJIT_INLINE_NODEBUG VecDList& operator=(const VecDList& other) noexcept = default;
|
||||
|
||||
ASMJIT_INLINE_NODEBUG VecDList& operator|=(const VecDList& other) noexcept { add_list(other); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG VecDList& operator&=(const VecDList& other) noexcept { and_list(other); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG VecDList& operator^=(const VecDList& other) noexcept { xor_list(other); return *this; }
|
||||
|
||||
ASMJIT_INLINE_NODEBUG VecDList operator|(const VecDList& other) const noexcept { return VecDList(list() | other.list()); }
|
||||
ASMJIT_INLINE_NODEBUG VecDList operator&(const VecDList& other) const noexcept { return VecDList(list() & other.list()); }
|
||||
ASMJIT_INLINE_NODEBUG VecDList operator^(const VecDList& other) const noexcept { return VecDList(list() ^ other.list()); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Memory operand (AArch32).
|
||||
class Mem : public BaseMem {
|
||||
public:
|
||||
//! \cond INTERNAL
|
||||
|
||||
// Index shift value (5 bits).
|
||||
// |........|.....XXX|XX......|........|
|
||||
static inline constexpr uint32_t kSignatureMemShiftValueShift = 14;
|
||||
static inline constexpr uint32_t kSignatureMemShiftValueMask = 0x1Fu << kSignatureMemShiftValueShift;
|
||||
|
||||
// Index shift operation (4 bits).
|
||||
// |........|XXXX....|........|........|
|
||||
static inline constexpr uint32_t kSignatureMemShiftOpShift = 20;
|
||||
static inline constexpr uint32_t kSignatureMemShiftOpMask = 0x0Fu << kSignatureMemShiftOpShift;
|
||||
|
||||
// Offset mode type (2 bits).
|
||||
// |......XX|........|........|........|
|
||||
static inline constexpr uint32_t kSignatureMemOffsetModeShift = 24;
|
||||
static inline constexpr uint32_t kSignatureMemOffsetModeMask = 0x03u << kSignatureMemOffsetModeShift;
|
||||
|
||||
//! \endcond
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
//! Construct a default `Mem` operand, that points to [0].
|
||||
ASMJIT_INLINE_CONSTEXPR Mem() noexcept
|
||||
: BaseMem() {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR Mem(const Mem& other) noexcept
|
||||
: BaseMem(other) {}
|
||||
|
||||
ASMJIT_INLINE_NODEBUG explicit Mem(Globals::NoInit_) noexcept
|
||||
: BaseMem(Globals::NoInit) {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR Mem(const Signature& signature, uint32_t base_id, uint32_t index_id, int32_t offset) noexcept
|
||||
: BaseMem(signature, base_id, index_id, offset) {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR explicit Mem(const Label& base, int32_t off = 0, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::from_op_type(OperandType::kMem) |
|
||||
Signature::from_mem_base_type(RegType::kLabelTag) |
|
||||
signature, base.id(), 0, off) {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR explicit Mem(const Reg& base, int32_t off = 0, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::from_op_type(OperandType::kMem) |
|
||||
Signature::from_mem_base_type(base.reg_type()) |
|
||||
signature, base.id(), 0, off) {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR Mem(const Reg& base, const Reg& index, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::from_op_type(OperandType::kMem) |
|
||||
Signature::from_mem_base_type(base.reg_type()) |
|
||||
Signature::from_mem_index_type(index.reg_type()) |
|
||||
signature, base.id(), index.id(), 0) {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR Mem(const Reg& base, const Reg& index, const Shift& shift, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::from_op_type(OperandType::kMem) |
|
||||
Signature::from_mem_base_type(base.reg_type()) |
|
||||
Signature::from_mem_index_type(index.reg_type()) |
|
||||
Signature::from_value<kSignatureMemShiftOpMask>(uint32_t(shift.op())) |
|
||||
Signature::from_value<kSignatureMemShiftValueMask>(shift.value()) |
|
||||
signature, base.id(), index.id(), 0) {}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR explicit Mem(uint64_t base, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::from_op_type(OperandType::kMem) |
|
||||
signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR Mem& operator=(const Mem& other) noexcept {
|
||||
copy_from(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Clone
|
||||
//! \{
|
||||
|
||||
//! Clones the memory operand.
|
||||
ASMJIT_INLINE_CONSTEXPR Mem clone() const noexcept { return Mem(*this); }
|
||||
|
||||
//! Gets new memory operand adjusted by `off`.
|
||||
ASMJIT_INLINE_CONSTEXPR Mem clone_adjusted(int64_t off) const noexcept {
|
||||
Mem result(*this);
|
||||
result.add_offset(off);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand and makes it pre-index.
|
||||
ASMJIT_INLINE_CONSTEXPR Mem pre() const noexcept {
|
||||
Mem result(*this);
|
||||
result.set_offset_mode(OffsetMode::kPreIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand, applies a given offset `off` and makes it pre-index.
|
||||
ASMJIT_INLINE_CONSTEXPR Mem pre(int64_t off) const noexcept {
|
||||
Mem result(*this);
|
||||
result.set_offset_mode(OffsetMode::kPreIndex);
|
||||
result.add_offset(off);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand and makes it post-index.
|
||||
ASMJIT_INLINE_CONSTEXPR Mem post() const noexcept {
|
||||
Mem result(*this);
|
||||
result.set_offset_mode(OffsetMode::kPostIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand, applies a given offset `off` and makes it post-index.
|
||||
ASMJIT_INLINE_CONSTEXPR Mem post(int64_t off) const noexcept {
|
||||
Mem result(*this);
|
||||
result.set_offset_mode(OffsetMode::kPostIndex);
|
||||
result.add_offset(off);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Base & Index
|
||||
//! \{
|
||||
|
||||
//! Converts memory `base_type` and `base_id` to `arm::Reg` instance.
|
||||
//!
|
||||
//! The memory must have a valid base register otherwise the result will be wrong.
|
||||
ASMJIT_INLINE_NODEBUG Reg base_reg() const noexcept { return Reg::from_type_and_id(base_type(), base_id()); }
|
||||
|
||||
//! Converts memory `index_type` and `index_id` to `arm::Reg` instance.
|
||||
//!
|
||||
//! The memory must have a valid index register otherwise the result will be wrong.
|
||||
ASMJIT_INLINE_NODEBUG Reg index_reg() const noexcept { return Reg::from_type_and_id(index_type(), index_id()); }
|
||||
|
||||
using BaseMem::set_index;
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR void set_index(const Reg& index, uint32_t shift) noexcept {
|
||||
set_index(index);
|
||||
set_shift(shift);
|
||||
}
|
||||
|
||||
ASMJIT_INLINE_CONSTEXPR void set_index(const Reg& index, Shift shift) noexcept {
|
||||
set_index(index);
|
||||
set_shift(shift);
|
||||
}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name ARM Specific Features
|
||||
//! \{
|
||||
|
||||
//! Gets offset mode.
|
||||
ASMJIT_INLINE_CONSTEXPR OffsetMode offset_mode() const noexcept { return OffsetMode(_signature.get_field<kSignatureMemOffsetModeMask>()); }
|
||||
//! Sets offset mode to `mode`.
|
||||
ASMJIT_INLINE_CONSTEXPR void set_offset_mode(OffsetMode mode) noexcept { _signature.set_field<kSignatureMemOffsetModeMask>(uint32_t(mode)); }
|
||||
//! Resets offset mode to default (fixed offset, without write-back).
|
||||
ASMJIT_INLINE_CONSTEXPR void reset_offset_mode() noexcept { _signature.set_field<kSignatureMemOffsetModeMask>(uint32_t(OffsetMode::kFixed)); }
|
||||
|
||||
//! Tests whether the current memory offset mode is fixed (see \ref arm::OffsetMode::kFixed).
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_fixed_offset() const noexcept { return offset_mode() == OffsetMode::kFixed; }
|
||||
//! Tests whether the current memory offset mode is either pre-index or post-index (write-back is used).
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_pre_or_post() const noexcept { return offset_mode() != OffsetMode::kFixed; }
|
||||
//! Tests whether the current memory offset mode is pre-index (write-back is used).
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_pre_index() const noexcept { return offset_mode() == OffsetMode::kPreIndex; }
|
||||
//! Tests whether the current memory offset mode is post-index (write-back is used).
|
||||
ASMJIT_INLINE_CONSTEXPR bool is_post_index() const noexcept { return offset_mode() == OffsetMode::kPostIndex; }
|
||||
|
||||
//! Sets offset mode of this memory operand to pre-index (write-back is used).
|
||||
ASMJIT_INLINE_CONSTEXPR void make_pre_index() noexcept { set_offset_mode(OffsetMode::kPreIndex); }
|
||||
//! Sets offset mode of this memory operand to post-index (write-back is used).
|
||||
ASMJIT_INLINE_CONSTEXPR void make_post_index() noexcept { set_offset_mode(OffsetMode::kPostIndex); }
|
||||
|
||||
//! Gets shift operation that is used by index register.
|
||||
ASMJIT_INLINE_CONSTEXPR ShiftOp shift_op() const noexcept { return ShiftOp(_signature.get_field<kSignatureMemShiftOpMask>()); }
|
||||
//! Sets shift operation that is used by index register.
|
||||
ASMJIT_INLINE_CONSTEXPR void set_shift_op(ShiftOp sop) noexcept { _signature.set_field<kSignatureMemShiftOpMask>(uint32_t(sop)); }
|
||||
//! Resets shift operation that is used by index register to LSL (default value).
|
||||
ASMJIT_INLINE_CONSTEXPR void reset_shift_op() noexcept { _signature.set_field<kSignatureMemShiftOpMask>(uint32_t(ShiftOp::kLSL)); }
|
||||
|
||||
//! Gets whether the memory operand has shift (aka scale) constant.
|
||||
ASMJIT_INLINE_CONSTEXPR bool has_shift() const noexcept { return _signature.has_field<kSignatureMemShiftValueMask>(); }
|
||||
//! Gets the memory operand's shift (aka scale) constant.
|
||||
ASMJIT_INLINE_CONSTEXPR uint32_t shift() const noexcept { return _signature.get_field<kSignatureMemShiftValueMask>(); }
|
||||
//! Sets the memory operand's shift (aka scale) constant.
|
||||
ASMJIT_INLINE_CONSTEXPR void set_shift(uint32_t shift) noexcept { _signature.set_field<kSignatureMemShiftValueMask>(shift); }
|
||||
|
||||
//! Sets the memory operand's shift and shift operation.
|
||||
ASMJIT_INLINE_CONSTEXPR void set_shift(Shift shift) noexcept {
|
||||
_signature.set_field<kSignatureMemShiftOpMask>(uint32_t(shift.op()));
|
||||
_signature.set_field<kSignatureMemShiftValueMask>(shift.value());
|
||||
}
|
||||
|
||||
//! Resets the memory operand's shift (aka scale) constant to zero.
|
||||
ASMJIT_INLINE_CONSTEXPR void reset_shift() noexcept { _signature.set_field<kSignatureMemShiftValueMask>(0); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
#ifndef _DOXYGEN
|
||||
namespace regs {
|
||||
#endif
|
||||
|
||||
//! Creates a 32-bit R register operand.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp r(uint32_t id) noexcept { return Gp::make_r32(id); }
|
||||
|
||||
//! Creates a 32-bit S register operand.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec s(uint32_t id) noexcept { return Vec::make_v32(id); }
|
||||
|
||||
//! Creates a 64-bit D register operand.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec d(uint32_t id) noexcept { return Vec::make_v64(id); }
|
||||
|
||||
//! Creates a 128-bit V register operand.
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Vec q(uint32_t id) noexcept { return Vec::make_v128(id); }
|
||||
|
||||
static constexpr Gp r0 = Gp::make_r32(0);
|
||||
static constexpr Gp r1 = Gp::make_r32(1);
|
||||
static constexpr Gp r2 = Gp::make_r32(2);
|
||||
static constexpr Gp r3 = Gp::make_r32(3);
|
||||
static constexpr Gp r4 = Gp::make_r32(4);
|
||||
static constexpr Gp r5 = Gp::make_r32(5);
|
||||
static constexpr Gp r6 = Gp::make_r32(6);
|
||||
static constexpr Gp r7 = Gp::make_r32(7);
|
||||
static constexpr Gp r8 = Gp::make_r32(8);
|
||||
static constexpr Gp r9 = Gp::make_r32(9);
|
||||
static constexpr Gp r10 = Gp::make_r32(10);
|
||||
static constexpr Gp r11 = Gp::make_r32(11);
|
||||
static constexpr Gp r12 = Gp::make_r32(12);
|
||||
static constexpr Gp r13 = Gp::make_r32(13);
|
||||
static constexpr Gp r14 = Gp::make_r32(14);
|
||||
static constexpr Gp r15 = Gp::make_r32(15);
|
||||
|
||||
static constexpr Gp fp = Gp::make_r32(Gp::kIdFP);
|
||||
static constexpr Gp sp = Gp::make_r32(Gp::kIdSP);
|
||||
static constexpr Gp lr = Gp::make_r32(Gp::kIdLR);
|
||||
static constexpr Gp pc = Gp::make_r32(Gp::kIdPC);
|
||||
|
||||
static constexpr Vec s0 = Vec::make_v32(0);
|
||||
static constexpr Vec s1 = Vec::make_v32(1);
|
||||
static constexpr Vec s2 = Vec::make_v32(2);
|
||||
static constexpr Vec s3 = Vec::make_v32(3);
|
||||
static constexpr Vec s4 = Vec::make_v32(4);
|
||||
static constexpr Vec s5 = Vec::make_v32(5);
|
||||
static constexpr Vec s6 = Vec::make_v32(6);
|
||||
static constexpr Vec s7 = Vec::make_v32(7);
|
||||
static constexpr Vec s8 = Vec::make_v32(8);
|
||||
static constexpr Vec s9 = Vec::make_v32(9);
|
||||
static constexpr Vec s10 = Vec::make_v32(10);
|
||||
static constexpr Vec s11 = Vec::make_v32(11);
|
||||
static constexpr Vec s12 = Vec::make_v32(12);
|
||||
static constexpr Vec s13 = Vec::make_v32(13);
|
||||
static constexpr Vec s14 = Vec::make_v32(14);
|
||||
static constexpr Vec s15 = Vec::make_v32(15);
|
||||
static constexpr Vec s16 = Vec::make_v32(16);
|
||||
static constexpr Vec s17 = Vec::make_v32(17);
|
||||
static constexpr Vec s18 = Vec::make_v32(18);
|
||||
static constexpr Vec s19 = Vec::make_v32(19);
|
||||
static constexpr Vec s20 = Vec::make_v32(20);
|
||||
static constexpr Vec s21 = Vec::make_v32(21);
|
||||
static constexpr Vec s22 = Vec::make_v32(22);
|
||||
static constexpr Vec s23 = Vec::make_v32(23);
|
||||
static constexpr Vec s24 = Vec::make_v32(24);
|
||||
static constexpr Vec s25 = Vec::make_v32(25);
|
||||
static constexpr Vec s26 = Vec::make_v32(26);
|
||||
static constexpr Vec s27 = Vec::make_v32(27);
|
||||
static constexpr Vec s28 = Vec::make_v32(28);
|
||||
static constexpr Vec s29 = Vec::make_v32(29);
|
||||
static constexpr Vec s30 = Vec::make_v32(30);
|
||||
static constexpr Vec s31 = Vec::make_v32(31);
|
||||
|
||||
static constexpr Vec d0 = Vec::make_v64(0);
|
||||
static constexpr Vec d1 = Vec::make_v64(1);
|
||||
static constexpr Vec d2 = Vec::make_v64(2);
|
||||
static constexpr Vec d3 = Vec::make_v64(3);
|
||||
static constexpr Vec d4 = Vec::make_v64(4);
|
||||
static constexpr Vec d5 = Vec::make_v64(5);
|
||||
static constexpr Vec d6 = Vec::make_v64(6);
|
||||
static constexpr Vec d7 = Vec::make_v64(7);
|
||||
static constexpr Vec d8 = Vec::make_v64(8);
|
||||
static constexpr Vec d9 = Vec::make_v64(9);
|
||||
static constexpr Vec d10 = Vec::make_v64(10);
|
||||
static constexpr Vec d11 = Vec::make_v64(11);
|
||||
static constexpr Vec d12 = Vec::make_v64(12);
|
||||
static constexpr Vec d13 = Vec::make_v64(13);
|
||||
static constexpr Vec d14 = Vec::make_v64(14);
|
||||
static constexpr Vec d15 = Vec::make_v64(15);
|
||||
static constexpr Vec d16 = Vec::make_v64(16);
|
||||
static constexpr Vec d17 = Vec::make_v64(17);
|
||||
static constexpr Vec d18 = Vec::make_v64(18);
|
||||
static constexpr Vec d19 = Vec::make_v64(19);
|
||||
static constexpr Vec d20 = Vec::make_v64(20);
|
||||
static constexpr Vec d21 = Vec::make_v64(21);
|
||||
static constexpr Vec d22 = Vec::make_v64(22);
|
||||
static constexpr Vec d23 = Vec::make_v64(23);
|
||||
static constexpr Vec d24 = Vec::make_v64(24);
|
||||
static constexpr Vec d25 = Vec::make_v64(25);
|
||||
static constexpr Vec d26 = Vec::make_v64(26);
|
||||
static constexpr Vec d27 = Vec::make_v64(27);
|
||||
static constexpr Vec d28 = Vec::make_v64(28);
|
||||
static constexpr Vec d29 = Vec::make_v64(29);
|
||||
static constexpr Vec d30 = Vec::make_v64(30);
|
||||
static constexpr Vec d31 = Vec::make_v64(31);
|
||||
|
||||
static constexpr Vec q0 = Vec::make_v128(0);
|
||||
static constexpr Vec q1 = Vec::make_v128(1);
|
||||
static constexpr Vec q2 = Vec::make_v128(2);
|
||||
static constexpr Vec q3 = Vec::make_v128(3);
|
||||
static constexpr Vec q4 = Vec::make_v128(4);
|
||||
static constexpr Vec q5 = Vec::make_v128(5);
|
||||
static constexpr Vec q6 = Vec::make_v128(6);
|
||||
static constexpr Vec q7 = Vec::make_v128(7);
|
||||
static constexpr Vec q8 = Vec::make_v128(8);
|
||||
static constexpr Vec q9 = Vec::make_v128(9);
|
||||
static constexpr Vec q10 = Vec::make_v128(10);
|
||||
static constexpr Vec q11 = Vec::make_v128(11);
|
||||
static constexpr Vec q12 = Vec::make_v128(12);
|
||||
static constexpr Vec q13 = Vec::make_v128(13);
|
||||
static constexpr Vec q14 = Vec::make_v128(14);
|
||||
static constexpr Vec q15 = Vec::make_v128(15);
|
||||
|
||||
#ifndef _DOXYGEN
|
||||
} // {regs}
|
||||
|
||||
// Make `a32::regs` accessible through `a32` namespace as well.
|
||||
using namespace regs;
|
||||
#endif
|
||||
|
||||
//! \name Shift Operation Construction
|
||||
//! \{
|
||||
|
||||
//! Constructs a `LSL #value` shift (logical shift left).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp lsl(const Gp& gp) noexcept { return gp.shifted(ShiftOp::kLSL); }
|
||||
|
||||
//! Constructs a `LSR #value` shift (logical shift right).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp lsr(const Gp& gp) noexcept { return gp.shifted(ShiftOp::kLSR); }
|
||||
|
||||
//! Constructs a `ASR #value` shift (arithmetic shift right).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp asr(const Gp& gp) noexcept { return gp.shifted(ShiftOp::kASR); }
|
||||
|
||||
//! Constructs a `ROR #value` shift (rotate right).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Gp ror(const Gp& gp) noexcept { return gp.shifted(ShiftOp::kROR); }
|
||||
|
||||
//! Constructs a `LSL #value` shift (logical shift left).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); }
|
||||
|
||||
//! Constructs a `LSR #value` shift (logical shift right).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); }
|
||||
|
||||
//! Constructs a `ASR #value` shift (arithmetic shift right).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); }
|
||||
|
||||
//! Constructs a `ROR #value` shift (rotate right).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Memory Operand Construction
|
||||
//! \{
|
||||
|
||||
//! Creates `[base, offset]` memory operand (offset mode) (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr(const Gp& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset);
|
||||
}
|
||||
|
||||
//! Creates `[base, offset]!` memory operand (pre-index mode) (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset, OperandSignature::from_value<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPreIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base], offset` memory operand (post-index mode) (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset, OperandSignature::from_value<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPostIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base, index]` memory operand (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr(const Gp& base, const Gp& index) noexcept {
|
||||
return Mem(base, index);
|
||||
}
|
||||
|
||||
//! Creates `[base, index]!` memory operand (pre-index mode) (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr_pre(const Gp& base, const Gp& index) noexcept {
|
||||
return Mem(base, index, OperandSignature::from_value<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPreIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base], index` memory operand (post-index mode) (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr_post(const Gp& base, const Gp& index) noexcept {
|
||||
return Mem(base, index, OperandSignature::from_value<Mem::kSignatureMemOffsetModeMask>(OffsetMode::kPostIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base, index, SHIFT_OP #shift]` memory operand (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept {
|
||||
return Mem(base, index, shift);
|
||||
}
|
||||
|
||||
//! Creates `[base, offset]` memory operand (AArch32).
|
||||
[[nodiscard]]
|
||||
static ASMJIT_INLINE_CONSTEXPR Mem ptr(const Label& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset);
|
||||
}
|
||||
|
||||
|
||||
//! \}
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // ASMJIT_ARM_A32OPERAND_H_INCLUDED
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <asmjit/core/misc_p.h>
|
||||
#include <asmjit/support/support.h>
|
||||
#include <asmjit/arm/armformatter_p.h>
|
||||
#include <asmjit/arm/a32operand.h>
|
||||
#include <asmjit/arm/a64operand.h>
|
||||
#include <asmjit/arm/a64instapi_p.h>
|
||||
#include <asmjit/arm/a64instdb_p.h>
|
||||
@@ -395,6 +396,15 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::format_register(
|
||||
}
|
||||
else {
|
||||
letter = 'r';
|
||||
|
||||
if (reg_id == a32::Gp::kIdSP)
|
||||
return sb.append("sp", 2);
|
||||
|
||||
if (reg_id == a32::Gp::kIdLR)
|
||||
return sb.append("lr", 2);
|
||||
|
||||
if (reg_id == a32::Gp::kIdPC)
|
||||
return sb.append("pc", 2);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -102,6 +102,12 @@
|
||||
#define ASMJIT_NO_X86
|
||||
#undef ASMJIT_NO_X86
|
||||
|
||||
//! \def ASMJIT_NO_AARCH32
|
||||
//!
|
||||
//! Disables AArch32 backend.
|
||||
#define ASMJIT_NO_AARCH32
|
||||
#undef ASMJIT_NO_AARCH32
|
||||
|
||||
//! \def ASMJIT_NO_AARCH64
|
||||
//!
|
||||
//! Disables AArch64 backend.
|
||||
@@ -304,6 +310,10 @@
|
||||
#define ASMJIT_NO_X86
|
||||
#endif
|
||||
|
||||
#if ASMJIT_ARCH_ARM != 32 && !defined(ASMJIT_NO_AARCH32)
|
||||
#define ASMJIT_NO_AARCH32
|
||||
#endif
|
||||
|
||||
#if ASMJIT_ARCH_ARM != 64 && !defined(ASMJIT_NO_AARCH64)
|
||||
#define ASMJIT_NO_AARCH64
|
||||
#endif
|
||||
|
||||
@@ -261,6 +261,10 @@ static ASMJIT_INLINE_NODEBUG uint32_t data_type_size(DataType dt) noexcept {
|
||||
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a32)
|
||||
using namespace arm;
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
ASMJIT_BEGIN_SUB_NAMESPACE(a64)
|
||||
using namespace arm;
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#include <asmjit/x86/x86archtraits_p.h>
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
#include <asmjit/arm/a32archtraits_p.h>
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
#include <asmjit/arm/a64archtraits_p.h>
|
||||
#endif
|
||||
@@ -74,7 +78,11 @@ ASMJIT_VARAPI const ArchTraits _arch_traits[uint32_t(Arch::kMaxValue) + 1] = {
|
||||
no_arch_traits,
|
||||
|
||||
// ARM architecture
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
a32::a32_arch_traits,
|
||||
#else
|
||||
no_arch_traits,
|
||||
#endif
|
||||
|
||||
// AArch64 architecture.
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
@@ -84,7 +92,11 @@ ASMJIT_VARAPI const ArchTraits _arch_traits[uint32_t(Arch::kMaxValue) + 1] = {
|
||||
#endif
|
||||
|
||||
// ARM/Thumb architecture.
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
a32::a32_arch_traits,
|
||||
#else
|
||||
no_arch_traits,
|
||||
#endif
|
||||
|
||||
// Reserved.
|
||||
no_arch_traits,
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <asmjit/x86/x86formatter_p.h>
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
#include <asmjit/arm/a32formatter_p.h>
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
#include <asmjit/arm/a64formatter_p.h>
|
||||
#endif
|
||||
@@ -126,7 +130,7 @@ Error format_feature(String& sb, Arch arch, uint32_t feature_id) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
#if !defined(ASMJIT_NO_AARCH32) && !defined(ASMJIT_NO_AARCH64)
|
||||
if (Environment::is_family_arm(arch)) {
|
||||
return arm::FormatterInternal::format_feature(sb, feature_id);
|
||||
}
|
||||
@@ -184,7 +188,7 @@ Error format_register(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
#if !defined(ASMJIT_NO_AARCH32) || !defined(ASMJIT_NO_AARCH64)
|
||||
if (Environment::is_family_arm(arch)) {
|
||||
return arm::FormatterInternal::format_register(sb, format_flags, emitter, arch, reg_type, reg_id);
|
||||
}
|
||||
@@ -206,7 +210,7 @@ Error format_operand(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
#if !defined(ASMJIT_NO_AARCH32) || !defined(ASMJIT_NO_AARCH64)
|
||||
if (Environment::is_family_arm(arch)) {
|
||||
return arm::FormatterInternal::format_operand(sb, format_flags, emitter, arch, op);
|
||||
}
|
||||
@@ -318,6 +322,11 @@ Error format_instruction(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if (Environment::is_family_aarch32(arch))
|
||||
return a32::FormatterInternal::format_instruction(sb, format_flags, emitter, arch, inst, operands);
|
||||
#endif
|
||||
|
||||
return make_error(Error::kInvalidArch);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include <asmjit/x86/x86instapi_p.h>
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
#include <asmjit/arm/a32instapi_p.h>
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH64)
|
||||
#include <asmjit/arm/a64instapi_p.h>
|
||||
#endif
|
||||
@@ -34,6 +38,11 @@ Error InstAPI::inst_id_to_string(Arch arch, InstId inst_id, InstStringifyOptions
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if (Environment::is_family_aarch32(arch))
|
||||
return a32::InstInternal::inst_id_to_string(inst_id, options, output);
|
||||
#endif
|
||||
|
||||
return make_error(Error::kInvalidArch);
|
||||
}
|
||||
|
||||
@@ -50,6 +59,11 @@ InstId InstAPI::string_to_inst_id(Arch arch, const char* s, size_t len) noexcept
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if (Environment::is_family_aarch32(arch))
|
||||
return a32::InstInternal::string_to_inst_id(s, len);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // !ASMJIT_NO_TEXT
|
||||
@@ -76,6 +90,10 @@ Error InstAPI::validate(Arch arch, const BaseInst& inst, const Operand_* operand
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if (Environment::is_family_aarch32(arch))
|
||||
return a32::InstInternal::validate(inst, operands, op_count, validation_flags);
|
||||
#endif
|
||||
return make_error(Error::kInvalidArch);
|
||||
}
|
||||
#endif // !ASMJIT_NO_INTROSPECTION
|
||||
@@ -101,6 +119,11 @@ Error InstAPI::query_rw_info(Arch arch, const BaseInst& inst, const Operand_* op
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if (Environment::is_family_aarch32(arch))
|
||||
return a32::InstInternal::query_rw_info(inst, operands, op_count, out);
|
||||
#endif
|
||||
|
||||
return make_error(Error::kInvalidArch);
|
||||
}
|
||||
#endif // !ASMJIT_NO_INTROSPECTION
|
||||
@@ -122,6 +145,11 @@ Error InstAPI::query_features(Arch arch, const BaseInst& inst, const Operand_* o
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(ASMJIT_NO_AARCH32)
|
||||
if (Environment::is_family_aarch32(arch))
|
||||
return a32::InstInternal::query_features(inst, operands, op_count, out);
|
||||
#endif
|
||||
return make_error(Error::kInvalidArch);
|
||||
}
|
||||
#endif // !ASMJIT_NO_INTROSPECTION
|
||||
|
||||
@@ -17,7 +17,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
||||
|
||||
Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() {
|
||||
_arch_mask = (uint64_t(1) << uint32_t(Arch::kX86)) |
|
||||
(uint64_t(1) << uint32_t(Arch::kX64)) ;
|
||||
(uint64_t(1) << uint32_t(Arch::kX64)) ;
|
||||
init_emitter_funcs(this);
|
||||
|
||||
if (code) {
|
||||
|
||||
@@ -18,7 +18,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
||||
|
||||
Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() {
|
||||
_arch_mask = (uint64_t(1) << uint32_t(Arch::kX86)) |
|
||||
(uint64_t(1) << uint32_t(Arch::kX64)) ;
|
||||
(uint64_t(1) << uint32_t(Arch::kX64)) ;
|
||||
init_emitter_funcs(this);
|
||||
|
||||
if (code) {
|
||||
|
||||
1622
tools/tablegen-a32.js
Normal file
1622
tools/tablegen-a32.js
Normal file
File diff suppressed because it is too large
Load Diff
3
tools/tablegen-a32.sh
Executable file
3
tools/tablegen-a32.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
node ./tablegen-a32.js
|
||||
417
tools/testgen-a32.js
Normal file
417
tools/testgen-a32.js
Normal file
@@ -0,0 +1,417 @@
|
||||
// This file is part of AsmJit project <https://asmjit.com>
|
||||
//
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
"use strict";
|
||||
|
||||
const core = require("./tablegen.js");
|
||||
const isa = new core.asmdb.aarch32.ISA();
|
||||
|
||||
const LLVM_MC = "/home/petr/workspace/3rdparty/llvm-project-build/bin/llvm-mc";
|
||||
|
||||
function lsbFromMul(mul) {
|
||||
for (let i = 0; i < 32; i++)
|
||||
if ((mul & (1 << i)) != 0)
|
||||
return i;
|
||||
return 32;
|
||||
}
|
||||
class TestsGenerator {
|
||||
constructor(isa) {
|
||||
this.isa = isa;
|
||||
}
|
||||
|
||||
generate() {
|
||||
const child_process = require("child_process");
|
||||
const tests = {
|
||||
"gp": [],
|
||||
"vec": []
|
||||
};
|
||||
|
||||
function flatten(inputArray) {
|
||||
const outputArray = [inputArray];
|
||||
|
||||
let i = 0;
|
||||
while (i < outputArray.length) {
|
||||
let didFlatten = false;
|
||||
const items = outputArray[i];
|
||||
|
||||
for (let j = 0; j < items.length; j++) {
|
||||
if (Array.isArray(items[j])) {
|
||||
const flattenedItems = [];
|
||||
for (let k = 0; k < items[j].length; k++) {
|
||||
const copy = items.slice();
|
||||
copy[j] = items[j][k];
|
||||
flattenedItems.push(copy);
|
||||
}
|
||||
|
||||
outputArray.splice(i, 1, ...flattenedItems);
|
||||
didFlatten = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i += Number(!didFlatten);
|
||||
}
|
||||
|
||||
return outputArray;
|
||||
}
|
||||
|
||||
function makeShiftOp(sop, op) {
|
||||
if (sop === "sop")
|
||||
return ["lsl " + op, "lsr " + op, "asr " + op, "ror " + op];
|
||||
else if (sop === "lsl_or_asr")
|
||||
return ["lsl " + op, "asr " + op];
|
||||
else
|
||||
return sop + " " + op;
|
||||
}
|
||||
|
||||
function encodingFromText(s) {
|
||||
let m = s.match(/@\s*encoding\:\s*\[0x([\w]{2}),0x([\w]{2}),0x([\w]{2}),0x([\w]{2})\]/);
|
||||
if (m)
|
||||
return ('"' + m[1] + m[2] + m[3] + m[4] + '"').toUpperCase();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
function codeFromInstruction(s) {
|
||||
s = s.trim();
|
||||
var sIdx = s.indexOf(" ");
|
||||
var name = s.substr(0, sIdx !== -1 ? sIdx : s.length).replace(/\./g, "_");
|
||||
var operands = s.substr(name.length).trim();
|
||||
|
||||
var sops = operands.replace(/(v\d+)\.(\d+)?([a-z]+)\[(\d+)\]/g, "$1.$3$2($4)")
|
||||
.replace(/([d|s|q]\d+)\[(\d+)\]/g, "$1.at($2)")
|
||||
.replace(/\[(\w+),\s*[#]?([-]?\w+)\]!/g, "ptr_pre($1, $2)")
|
||||
.replace(/\[(\w+)\],\s*[#]?([-]?\w+)/g, "ptr_post($1, $2)")
|
||||
.replace(/\[(\w+),\s*[#]?([-]?\w+)\]/g, "ptr($1, $2)")
|
||||
.replace(/\[(\w+)\]/g, "ptr($1)")
|
||||
.replace(/\beq\b/g, "Cond::kEQ")
|
||||
.replace(/#((?:0x)?[-]?[\dA-Fa-f]+)\b/g, "$1")
|
||||
.replace(/(lsl|lsr|asr|ror)\s+([r]?\d+)/g, "$1($2)")
|
||||
.replace(/[{}]/g, "");
|
||||
|
||||
if (name === "and")
|
||||
name = "and_";
|
||||
|
||||
return name + "(" + sops + ")";
|
||||
}
|
||||
|
||||
for (let inst of isa.instructions) {
|
||||
if (inst.encoding !== "A32")
|
||||
continue;
|
||||
|
||||
let category = "gp";
|
||||
let elements = [""];
|
||||
|
||||
const dt1Array = inst.dt.length ? inst.dt : ["any"];
|
||||
const dt2Array = inst.dt2.length ? inst.dt2 : ["any"];
|
||||
const dataTypes = [];
|
||||
|
||||
for (let dt2 of dt2Array) {
|
||||
for (let dt1 of dt1Array) {
|
||||
if (dt2 !== "any")
|
||||
dataTypes.push(`.${dt1}.${dt2}`);
|
||||
else if (dt1 !== "any")
|
||||
dataTypes.push(`.${dt1}`);
|
||||
else
|
||||
dataTypes.push(``);
|
||||
}
|
||||
}
|
||||
|
||||
for (let dataType of dataTypes) {
|
||||
let instruction = inst.name + dataType;
|
||||
let ops = [];
|
||||
let proceed = true;
|
||||
|
||||
for (let i = 0; i < inst.operands.length; i++) {
|
||||
const operand = inst.operands[i];
|
||||
let regId = i + 1;
|
||||
|
||||
if (/^(ldaexd|ldrd|ldrexd|strd)$/.test(inst.name)) {
|
||||
regId--;
|
||||
}
|
||||
else if (/^(stlexd|strexd)$/.test(inst.name)) {
|
||||
if (i == 0)
|
||||
regId = 7;
|
||||
else
|
||||
regId = i - 1;
|
||||
}
|
||||
|
||||
switch (operand.type) {
|
||||
case "reg": {
|
||||
if (operand.regType === "r" && operand.shiftOp) {
|
||||
ops.push(makeShiftOp(operand.shiftOp, `r${i + 1}`));
|
||||
}
|
||||
else if (operand.regType === "r") {
|
||||
ops.push(`r${regId}`);
|
||||
}
|
||||
else if (operand.regType === "s") {
|
||||
ops.push(`s${regId}`);
|
||||
category = "vec";
|
||||
}
|
||||
else if (operand.regType === "d") {
|
||||
ops.push(`d${regId}`);
|
||||
category = "vec";
|
||||
}
|
||||
else if (operand.regType === "v") {
|
||||
ops.push(`q${regId}`);
|
||||
category = "vec";
|
||||
}
|
||||
else {
|
||||
proceed = false;
|
||||
}
|
||||
|
||||
if (operand.element) {
|
||||
ops[ops.length - 1] += "[@element@]";
|
||||
switch (dataType) {
|
||||
case ".8":
|
||||
case ".s8":
|
||||
case ".u8":
|
||||
elements = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
break;
|
||||
case ".16":
|
||||
case ".s16":
|
||||
case ".u16":
|
||||
case ".f16":
|
||||
if (inst.name === "vcmla" || inst.name === "vfmsl" || inst.name === "vfmal")
|
||||
elements = [0, 1];
|
||||
else
|
||||
elements = [0, 1, 2, 3];
|
||||
break;
|
||||
case ".32":
|
||||
case ".s32":
|
||||
case ".u32":
|
||||
case ".f32":
|
||||
if (inst.name === "vcmla")
|
||||
elements = [0];
|
||||
else
|
||||
elements = [0, 1];
|
||||
break;
|
||||
case ".64":
|
||||
case ".s64":
|
||||
case ".u64":
|
||||
case ".f64":
|
||||
elements = [0, 1];
|
||||
break;
|
||||
|
||||
case ".bf16":
|
||||
if (inst.name === "vdot")
|
||||
elements = [0, 1];
|
||||
else
|
||||
elements = [0, 1, 2, 3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "imm": {
|
||||
if (inst.name === "vcadd")
|
||||
ops.push(["#90", "#270"]);
|
||||
else if (inst.name === "vcmla")
|
||||
ops.push(["#0", "#90", "#180", "#270"]);
|
||||
else if (operand.shiftOp)
|
||||
ops.push(makeShiftOp(operand.shiftOp, "#8"));
|
||||
else if (operand.imm === "zero")
|
||||
ops.push("#0");
|
||||
else if (operand.imm === "immA")
|
||||
ops.push(["#0xFF", "0xFF00", "0xFF000000", "0xF000000F"]);
|
||||
else if (operand.imm === "immZ")
|
||||
ops.push("#1");
|
||||
else if (operand.imm === "immV" && instruction.endsWith("16"))
|
||||
ops.push(["#0x1F", "#0x80", "#0xFF", "0x1F00", "0xFF00"]);
|
||||
else if (operand.imm === "immV" && instruction.endsWith("32"))
|
||||
ops.push(["#0x1F", "#0x80", "#0xFF", "0x1F00", "0xFF00", "0x1F0000", "0xFF0000", "0xFF000000", "0xFFFF0000", "0x0000FFFF", "0xFFFFFF00", "0x00FFFFFF", "0xC0F00000"]);
|
||||
else if (operand.imm === "immV" && instruction.endsWith("64"))
|
||||
ops.push(["#00FFFF0000000000", "#0xFF00FF0000000000", "#0x00000000FFFFFFFF"]);
|
||||
else if (operand.imm === "lsb")
|
||||
ops.push("#3");
|
||||
else if (operand.imm === "width")
|
||||
ops.push("#5");
|
||||
else if (operand.imm === "sat")
|
||||
ops.push("#8");
|
||||
else if (operand.imm === "imm")
|
||||
ops.push("#0");
|
||||
else if (operand.imm === "n")
|
||||
ops.push("#3");
|
||||
else
|
||||
proceed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case "mem": {
|
||||
const combinations = [];
|
||||
var off = "4";
|
||||
|
||||
if (operand.offset && operand.offset.exp) {
|
||||
const e = operand.offset.exp;
|
||||
if (e.op === "==") {
|
||||
off = e.right.toString();
|
||||
if (off.indexOf("sz") !== -1 && dataType) {
|
||||
const sz = dataType.match(/(\d+)/);
|
||||
off = eval(off.replace("sz", parseInt(lsbFromMul(sz[1] / 8))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operand.memModes.offset) {
|
||||
if (operand.index)
|
||||
combinations.push(`[r${regId}, r${regId + 1}]`);
|
||||
else if (operand.offset)
|
||||
combinations.push(`[r${regId}, #${off}]`);
|
||||
else
|
||||
combinations.push(`[r${regId}]`);
|
||||
}
|
||||
|
||||
if (operand.memModes.preIndex) {
|
||||
if (operand.index)
|
||||
combinations.push(`[r${regId}, r${regId + 1}]!`);
|
||||
else if (operand.offset)
|
||||
combinations.push(`[r${regId}, #${off}]!`);
|
||||
}
|
||||
|
||||
if (operand.memModes.postIndex) {
|
||||
if (operand.index)
|
||||
combinations.push(`[r${regId}], r${regId + 1}`);
|
||||
else if (operand.offset)
|
||||
combinations.push(`[r${regId}], #${off}`);
|
||||
}
|
||||
|
||||
ops.push(combinations);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
proceed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!proceed) {
|
||||
console.log(`IGNORING: ${inst.name}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const opsArray = flatten(ops);
|
||||
|
||||
const args = [
|
||||
"--arch=arm",
|
||||
"-mattr=+v8.5a",
|
||||
"-mattr=+aes",
|
||||
"-mattr=+bf16",
|
||||
"-mattr=+crc",
|
||||
"-mattr=+crypto",
|
||||
"-mattr=+hwdiv-arm",
|
||||
"-mattr=+fp16fml",
|
||||
"-mattr=+fullfp16",
|
||||
"-mattr=+i8mm",
|
||||
"-mattr=+mp",
|
||||
"-mattr=+trustzone",
|
||||
"-mattr=+virtualization",
|
||||
"-show-encoding",
|
||||
"-output-asm-variant=0"
|
||||
];
|
||||
|
||||
for (let element of elements) {
|
||||
for (let opsRow of opsArray) {
|
||||
let line = instruction;
|
||||
opsRow = opsRow.map(function(s) { return s.replace("@element@", element) });
|
||||
|
||||
let o = opsRow.slice();
|
||||
switch (inst.name) {
|
||||
case "pop":
|
||||
case "push": {
|
||||
o[0] = "{" + o[0];
|
||||
o[o.length - 1] += "}";
|
||||
break;
|
||||
}
|
||||
|
||||
case "vcls": {
|
||||
line = line.replace(".u", ".s");
|
||||
break;
|
||||
}
|
||||
|
||||
case "vtbx":
|
||||
case "vtbl": {
|
||||
o[1] = "{" + o[1];
|
||||
o[o.length - 2] += "}";
|
||||
break;
|
||||
}
|
||||
|
||||
case "rfe":
|
||||
case "rfeda":
|
||||
case "rfedb":
|
||||
case "rfeib": {
|
||||
o[0] = o[0].replace(/[\[\]]/g, "");
|
||||
break;
|
||||
}
|
||||
|
||||
case "vld1r":
|
||||
case "vld2r":
|
||||
case "vld3r":
|
||||
case "vld4r": {
|
||||
line = line.replace("vld1r", "vld1")
|
||||
.replace("vld2r", "vld2")
|
||||
.replace("vld3r", "vld3")
|
||||
.replace("vld4r", "vld4");
|
||||
for (let i = 0; i < o.length - 1; i++)
|
||||
o[i] += "[]";
|
||||
// fallthrough;
|
||||
}
|
||||
|
||||
case "vld1":
|
||||
case "vld2":
|
||||
case "vld3":
|
||||
case "vld4":
|
||||
case "vst1":
|
||||
case "vst2":
|
||||
case "vst3":
|
||||
case "vst4": {
|
||||
o[o.length - 1] = o[o.length - 1].replace(/,\s*#\d+$/g, "!");
|
||||
o[0] = "{" + o[0];
|
||||
o[o.length - 2] += "}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const out = child_process.execFileSync(LLVM_MC, args, {
|
||||
input: line + " " + o.join(", "),
|
||||
encoding: "utf-8"
|
||||
});
|
||||
|
||||
const encoding = encodingFromText(out);
|
||||
const code = codeFromInstruction(instruction + " " + opsRow.join(", "));
|
||||
|
||||
tests[category].push(`TEST_INSTRUCTION(${encoding}, ${code});`);
|
||||
}
|
||||
catch (ex) {
|
||||
console.log(`FATAL: ${line} ${opsRow.join(", ")}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("static void ASMJIT_NOINLINE testA32AssemblerGp(AssemblerTester<a32::Assembler>& tester) noexcept {");
|
||||
console.log(" using namespace a32;");
|
||||
console.log("");
|
||||
for (let test of tests.gp) {
|
||||
console.log(" " + test);
|
||||
}
|
||||
console.log("}");
|
||||
|
||||
console.log("");
|
||||
|
||||
console.log("static void ASMJIT_NOINLINE testA32AssemblerVec(AssemblerTester<a32::Assembler>& tester) noexcept {");
|
||||
console.log(" using namespace a32;");
|
||||
console.log("");
|
||||
for (let test of tests.vec)
|
||||
console.log(" " + test);
|
||||
console.log("}");
|
||||
}
|
||||
}
|
||||
new TestsGenerator(isa).generate();
|
||||
Reference in New Issue
Block a user